/* eslint-disable import-x/order */
import { readFile } from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import spawn from 'cross-spawn';
import { readObjectRecord, readOptionalString } from '../../../../shared/utils.js';
// @ts-ignore — plain-JS module
import { getProviderCredentials } from '../../../../services/provider-credentials.js';
const GEMINI_TOKEN_INFO_TIMEOUT_MS = 5_000;
export class GeminiProviderAuth {
    /**
     * Checks whether the Gemini CLI is available on this host.
     */
    checkInstalled() {
        const cliPath = process.env.GEMINI_CLI_PATH || process.env.GEMINI_PATH || 'gemini';
        try {
            const result = spawn.sync(cliPath, ['--version'], { stdio: 'ignore', timeout: 5000 });
            return !result.error && result.status === 0;
        }
        catch {
            return false;
        }
    }
    /**
     * Returns Gemini CLI installation and credential status.
     */
    async getStatus() {
        const installed = this.checkInstalled();
        if (!installed) {
            return {
                installed,
                provider: 'gemini',
                authenticated: false,
                email: null,
                method: null,
                error: 'Gemini CLI is not installed',
            };
        }
        const credentials = await this.checkCredentials();
        return {
            installed,
            provider: 'gemini',
            authenticated: credentials.authenticated,
            email: credentials.email,
            method: credentials.method,
            error: credentials.authenticated ? undefined : credentials.error || 'Not authenticated',
        };
    }
    /**
     * Checks Gemini credentials from API key env vars or local OAuth credential files.
     */
    async checkCredentials() {
        // Pixcode-UI-saved API key takes priority (users expect the form to
        // reflect as authenticated right after Save).
        try {
            const creds = await getProviderCredentials('gemini');
            if (creds?.apiKey) {
                return { authenticated: true, email: 'API Key Auth', method: 'pixcode_store' };
            }
        }
        catch { /* fall through */ }
        if (process.env.GEMINI_API_KEY?.trim()) {
            return { authenticated: true, email: 'API Key Auth', method: 'api_key' };
        }
        try {
            const credsPath = path.join(os.homedir(), '.gemini', 'oauth_creds.json');
            const content = await readFile(credsPath, 'utf8');
            const creds = readObjectRecord(JSON.parse(content)) ?? {};
            const accessToken = readOptionalString(creds.access_token);
            if (!accessToken) {
                return {
                    authenticated: false,
                    email: null,
                    method: null,
                    error: 'No valid tokens found in oauth_creds',
                };
            }
            const refreshToken = readOptionalString(creds.refresh_token);
            const tokenInfo = await this.getTokenInfoEmail(accessToken);
            if (tokenInfo.valid) {
                return {
                    authenticated: true,
                    email: tokenInfo.email || 'OAuth Session',
                    method: 'credentials_file',
                };
            }
            if (!refreshToken) {
                return {
                    authenticated: false,
                    email: null,
                    method: 'credentials_file',
                    error: 'Access token invalid and no refresh token found',
                };
            }
            return {
                authenticated: true,
                email: await this.getActiveAccountEmail() || 'OAuth Session',
                method: 'credentials_file',
            };
        }
        catch {
            return {
                authenticated: false,
                email: null,
                method: null,
                error: 'Gemini CLI not configured',
            };
        }
    }
    /**
     * Validates a Gemini OAuth access token and returns an email when Google reports one.
     */
    async getTokenInfoEmail(accessToken) {
        const controller = new AbortController();
        const timeout = setTimeout(() => controller.abort(), GEMINI_TOKEN_INFO_TIMEOUT_MS);
        try {
            const tokenRes = await fetch(`https://oauth2.googleapis.com/tokeninfo?access_token=${accessToken}`, {
                signal: controller.signal,
            });
            if (!tokenRes.ok) {
                return { valid: false, email: null };
            }
            const tokenInfo = readObjectRecord(await tokenRes.json());
            return {
                valid: true,
                email: readOptionalString(tokenInfo?.email) ?? null,
            };
        }
        catch {
            return { valid: false, email: null };
        }
        finally {
            clearTimeout(timeout);
        }
    }
    /**
     * Reads Gemini's active local Google account as an offline fallback for display.
     */
    async getActiveAccountEmail() {
        try {
            const accPath = path.join(os.homedir(), '.gemini', 'google_accounts.json');
            const accContent = await readFile(accPath, 'utf8');
            const accounts = readObjectRecord(JSON.parse(accContent));
            return readOptionalString(accounts?.active) ?? null;
        }
        catch {
            return null;
        }
    }
}
//# sourceMappingURL=gemini-auth.provider.js.map