"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CliAppService = void 0;
const api_client_1 = require("../api-client");
const config_storage_1 = require("../config-storage");
class CliAppService {
    constructor(apiClient, clusterId) {
        this.apiClient = apiClient;
        this.clusterId = clusterId;
    }
    static async create(clusterId) {
        const configStorage = new config_storage_1.ConfigStorage();
        const apiUrl = configStorage.getApiUrlOrThrow();
        const apiKey = configStorage.getApiKey();
        if (!apiKey) {
            throw new Error('Not logged in. Run `flui auth login` first.');
        }
        const apiClient = new api_client_1.ApiClient({ baseUrl: apiUrl, apiKey });
        return new CliAppService(apiClient, clusterId);
    }
    async listApps() {
        return this.apiClient.get(`/clusters/${this.clusterId}/applications`);
    }
    async getAppByName(name) {
        const apps = await this.listApps();
        const app = apps.find((a) => a.name.toLowerCase() === name.toLowerCase() ||
            a.slug.toLowerCase() === name.toLowerCase());
        if (!app) {
            throw new Error(`App "${name}" not found in cluster.`);
        }
        return app;
    }
    async getRuntime(appId) {
        return this.apiClient.get(`/applications/${appId}/runtime`);
    }
    async getLogs(options) {
        const params = new URLSearchParams();
        if (options.app)
            params.append('app', options.app);
        if (options.namespace)
            params.append('namespace', options.namespace);
        if (options.level)
            params.append('level', options.level);
        if (options.tail)
            params.append('tail', String(options.tail));
        if (options.search)
            params.append('search', options.search);
        const qs = params.toString();
        const qsSuffix = qs ? `?${qs}` : '';
        return this.apiClient.get(`/observability/clusters/${this.clusterId}/apps/logs${qsSuffix}`);
    }
    async scale(appId, replicas) {
        return this.apiClient.patch(`/applications/${appId}/replicas`, {
            replicas,
        });
    }
    async restart(appId) {
        return this.apiClient.post(`/applications/${appId}/restart`);
    }
    async stop(appId) {
        return this.apiClient.post(`/applications/${appId}/stop`);
    }
    async start(appId) {
        return this.apiClient.post(`/applications/${appId}/start`);
    }
    async getCrashes(appId) {
        return this.apiClient.get(`/applications/${appId}/crash-diagnoses`);
    }
    async getCrash(appId, id) {
        return this.apiClient.get(`/applications/${appId}/crash-diagnoses/${id}`);
    }
    async dismissCrash(appId, id) {
        return this.apiClient.post(`/applications/${appId}/crash-diagnoses/${id}/dismiss`);
    }
    async getMetrics(appId) {
        return this.apiClient.get(`/applications/${appId}/metrics`);
    }
    async getAppDetail(appId) {
        return this.apiClient.get(`/applications/${appId}`);
    }
    async uninstall(catalogInstallId) {
        return this.apiClient.delete(`/catalog/installs/${catalogInstallId}`);
    }
    async deleteApp(appId) {
        return this.apiClient.delete(`/applications/${appId}`);
    }
    async getInstallStatus(catalogInstallId) {
        return this.apiClient.get(`/catalog/installs/${catalogInstallId}`);
    }
    // ── Builds ──────────────────────────────────────────────────────────────
    async listBuilds(appId) {
        return this.apiClient.get(`/applications/${appId}/builds`);
    }
    async getLatestBuild(appId) {
        try {
            return await this.apiClient.get(`/applications/${appId}/builds/latest`);
        }
        catch (err) {
            if (err?.status === 404)
                return null;
            throw err;
        }
    }
    async getBuild(buildId) {
        return this.apiClient.get(`/applications/builds/${buildId}`);
    }
    async refreshBuild(buildId) {
        return this.apiClient.post(`/applications/builds/${buildId}/refresh`);
    }
    async cancelBuild(buildId) {
        return this.apiClient.post(`/applications/builds/${buildId}/cancel`);
    }
    async deployFromBuild(appId, buildId) {
        return this.apiClient.post(`/applications/${appId}/builds/${buildId}/deploy`);
    }
    // ── Releases ────────────────────────────────────────────────────────────
    async getCurrentRelease(appId) {
        return this.apiClient.get(`/applications/${appId}/release`);
    }
    async listReleases(appId) {
        const res = await this.apiClient.get(`/applications/${appId}/releases`);
        return res.releases;
    }
    // ── Versions / Images ───────────────────────────────────────────────────
    async listAvailableVersions(appId) {
        return this.apiClient.get(`/applications/${appId}/available-versions`);
    }
    async redeployTag(appId, tag) {
        return this.apiClient.post(`/image-registry/apps/${appId}/ghcr/${encodeURIComponent(tag)}/deploy`);
    }
    async deleteImageVersion(appId, versionId, options) {
        const qs = options?.force ? '?force=true' : '';
        return this.apiClient.delete(`/image-registry/apps/${appId}/ghcr/${versionId}${qs}`);
    }
    // ── Volume snapshots ────────────────────────────────────
    async createAppSnapshot(appId, body = {}) {
        return this.apiClient.post(`/applications/${appId}/snapshots`, body);
    }
    async listAppSnapshots(appId) {
        return this.apiClient.get(`/applications/${appId}/snapshots`);
    }
    async deleteAppSnapshot(appId, snapshotId) {
        return this.apiClient.delete(`/applications/${appId}/snapshots/${encodeURIComponent(snapshotId)}`);
    }
    async listClusterSnapshots() {
        return this.apiClient.get(`/clusters/${this.clusterId}/snapshots`);
    }
    async restoreAppSnapshot(appId, snapshotId) {
        return this.apiClient.post(`/applications/${appId}/snapshots/${encodeURIComponent(snapshotId)}/restore`, {});
    }
    async swapAppVolume(appId, volumeName, newClaimName) {
        return this.apiClient.post(`/applications/${appId}/volumes/${encodeURIComponent(volumeName)}/swap`, { newClaimName });
    }
    // ── Volume backups (s3-archive sink) ────────────────────────
    async createAppBackup(appId, body) {
        return this.apiClient.post(`/applications/${appId}/backups`, body);
    }
    async deleteAppBackup(appId, exportId, destination) {
        await this.apiClient.delete(`/applications/${appId}/backups/${encodeURIComponent(exportId)}`, { data: { destination } });
    }
}
exports.CliAppService = CliAppService;
