import { readFile } from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import fs from 'node:fs';
import spawn from 'cross-spawn';
import { resolveClaudeCodeExecutablePath } from '../../../../shared/claude-cli-path.js';
import { readObjectRecord, readOptionalString } from '../../../../shared/utils.js';
const FCC_ENV_PATH = path.join(os.homedir(), '.config', 'free-claude-code', '.env');
function readFccEnvValue(key) {
    try {
        const content = fs.readFileSync(FCC_ENV_PATH, 'utf8');
        for (const line of content.split('\n')) {
            const trimmed = line.trim();
            if (!trimmed || trimmed.startsWith('#'))
                continue;
            const eqIdx = trimmed.indexOf('=');
            if (eqIdx === -1)
                continue;
            const k = trimmed.slice(0, eqIdx).trim();
            if (k === key) {
                const value = trimmed.slice(eqIdx + 1).trim();
                return value || undefined;
            }
        }
    }
    catch {
        // fcc config is optional
    }
    return undefined;
}
export class ClaudeProviderAuth {
    /**
     * Checks whether the Claude Code CLI is available on this host.
     */
    checkInstalled() {
        const cliPath = resolveClaudeCodeExecutablePath(process.env.CLAUDE_CLI_PATH);
        try {
            spawn.sync(cliPath, ['--version'], { stdio: 'ignore', timeout: 5000 });
            return true;
        }
        catch {
            return false;
        }
    }
    /**
     * Returns Claude installation and credential status using Claude Code's auth priority.
     */
    async getStatus() {
        const installed = this.checkInstalled();
        if (!installed) {
            return {
                installed,
                provider: 'claude',
                authenticated: false,
                email: null,
                method: null,
                error: 'Claude Code CLI is not installed',
            };
        }
        const credentials = await this.checkCredentials();
        return {
            installed,
            provider: 'claude',
            authenticated: credentials.authenticated,
            email: credentials.authenticated ? credentials.email || 'Authenticated' : credentials.email,
            method: credentials.method,
            error: credentials.authenticated ? undefined : credentials.error || 'Not authenticated',
        };
    }
    /**
     * Reads Claude settings env values that the CLI can use even when the server process env is empty.
     */
    async loadSettingsEnv() {
        try {
            const settingsPath = path.join(os.homedir(), '.claude', 'settings.json');
            const content = await readFile(settingsPath, 'utf8');
            const settings = readObjectRecord(JSON.parse(content));
            return readObjectRecord(settings?.env) ?? {};
        }
        catch {
            return {};
        }
    }
    /**
     * Checks Claude credentials in the same priority order used by Claude Code.
     */
    async checkCredentials() {
        if (process.env.ANTHROPIC_API_KEY?.trim()) {
            return { authenticated: true, email: 'API Key Auth', method: 'api_key' };
        }
        if (process.env.ANTHROPIC_AUTH_TOKEN?.trim()) {
            return { authenticated: true, email: 'Auth Token (env)', method: 'auth_token' };
        }
        const settingsEnv = await this.loadSettingsEnv();
        if (readOptionalString(settingsEnv.ANTHROPIC_API_KEY)) {
            return { authenticated: true, email: 'API Key Auth', method: 'api_key' };
        }
        if (readOptionalString(settingsEnv.ANTHROPIC_AUTH_TOKEN)) {
            return { authenticated: true, email: 'Configured via settings.json', method: 'auth_token' };
        }
        const fccAuthToken = readFccEnvValue('ANTHROPIC_AUTH_TOKEN');
        if (fccAuthToken) {
            return { authenticated: true, email: 'Free Claude Code', method: 'auth_token' };
        }
        try {
            const credPath = path.join(os.homedir(), '.claude', '.credentials.json');
            const content = await readFile(credPath, 'utf8');
            const creds = readObjectRecord(JSON.parse(content)) ?? {};
            const oauth = readObjectRecord(creds.claudeAiOauth);
            const accessToken = readOptionalString(oauth?.accessToken);
            if (accessToken) {
                const expiresAt = typeof oauth?.expiresAt === 'number' ? oauth.expiresAt : undefined;
                const email = readOptionalString(creds.email) ?? readOptionalString(creds.user) ?? null;
                if (!expiresAt || Date.now() < expiresAt) {
                    return {
                        authenticated: true,
                        email,
                        method: 'credentials_file',
                    };
                }
                return {
                    authenticated: false,
                    email,
                    method: 'credentials_file',
                    error: 'OAuth token has expired. Please re-authenticate with claude login',
                };
            }
            return { authenticated: false, email: null, method: null };
        }
        catch {
            return { authenticated: false, email: null, method: null };
        }
    }
}
//# sourceMappingURL=claude-auth.provider.js.map