import * as vscode from 'vscode';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import { execSync } from 'child_process';
import { getConfig } from '../config';
import { logInfo, logWarn, logError, getActiveBrainProfile } from '../utils';
import { getBridgeBaseUrl } from '../features/datacollect/bridgeClient';

/**
 * HealthCheckMonitor: Periodically monitors the environment
 * (Ollama, Disk, API) to ensure the agent stays functional.
 *
 * v2.2.245: 머신 로컬 전제 조건 4종 추가 — Bridge 응답·두뇌 볼륨 마운트·
 * git push 자격증명·Antigravity 확장 버전 정합. 한 세션에서 이 4가지가 전부
 * 사고로 터진 적이 있는데 (URL 분석 실패 / 인벤토리 미생성 / 동기화 실패 /
 * 구버전 실행), 전부 사후 디버깅으로만 발견됐다. 이제 readyBar ⚠️ 로 사전 가시화.
 *
 * Properly tracks the interval timer for cleanup on deactivation.
 */
export class HealthCheckMonitor {
    private static intervalHandle: ReturnType<typeof setInterval> | null = null;
    /** 마지막 검사 결과 — readyBar payload 가 읽어간다 (재검사 비용 없이). */
    private static _lastReports: string[] = [];
    /** 직전 토스트 내용 — 같은 경고를 10분마다 반복 토스트하지 않기 위한 dedupe. */
    private static _lastToastKey = '';

    public static get lastReports(): string[] {
        return this._lastReports.slice();
    }

    public static async runAllChecks(): Promise<{ ok: boolean; reports: string[] }> {
        const reports: string[] = [];
        const config = getConfig();

        // 1. AI Engine Connectivity Check
        try {
            const res = await fetch(`${config.ollamaUrl}/api/tags`, { signal: AbortSignal.timeout(3000) });
            if (res.ok) {
                logInfo('Health Check: AI engine connectivity OK.');
            } else {
                reports.push('AI Server is reachable but returned an error.');
            }
        } catch {
            reports.push('AI Server is NOT reachable. Please check if it is running.');
        }

        // 2. Workspace Validation
        const workspaceFolders = vscode.workspace.workspaceFolders;
        if (!workspaceFolders || workspaceFolders.length === 0) {
            reports.push('No workspace folder open. Agent capabilities will be limited.');
        }

        // 3. Simple Disk/Permissions Check
        try {
            const testFile = workspaceFolders ? vscode.Uri.joinPath(workspaceFolders[0].uri, '.g1-health-check') : null;
            if (testFile) {
                await vscode.workspace.fs.writeFile(testFile, Buffer.from('ok'));
                await vscode.workspace.fs.delete(testFile);
                logInfo('Health Check: Write permissions OK.');
            }
        } catch {
            reports.push('Write permissions denied in the current workspace.');
        }

        // 4. Datacollect Bridge 응답 — 어떤 HTTP 응답이든(404 포함) 살아 있는 것.
        //    네트워크 오류만 다운으로 판정. Bridge 다운이어도 URL 분석은 직접
        //    fetch 폴백으로 동작하므로 경고는 영향 범위를 정확히 알린다.
        try {
            const bridgeUrl = getBridgeBaseUrl();
            if (bridgeUrl) {
                try {
                    await fetch(bridgeUrl, { signal: AbortSignal.timeout(3000) });
                } catch {
                    reports.push(`Datacollect Bridge(${bridgeUrl})가 응답하지 않습니다 — /wikify·/benchmark 와 고품질 URL 추출이 비활성 (URL 분석 자체는 직접 fetch 폴백으로 동작).`);
                }
            }
        } catch { /* config 읽기 실패 등 — 검사 자체를 조용히 skip */ }

        // 5. 두뇌 볼륨/경로 — 외장 볼륨이 늦게 마운트되면 검색·레슨·인벤토리가
        //    조용히 비활성화되던 사고의 사전 감지.
        let brain: ReturnType<typeof getActiveBrainProfile> | undefined;
        try {
            brain = getActiveBrainProfile();
            if (brain?.localBrainPath && !fs.existsSync(brain.localBrainPath)) {
                reports.push(`두뇌 폴더가 없습니다 (외장 볼륨 미마운트?): ${brain.localBrainPath} — 검색·레슨·인벤토리가 비활성화됩니다.`);
            }
        } catch { /* profile 읽기 실패 — skip */ }

        // 6. git push 자격증명 — 원격 동기화를 *설정한* 두뇌만 검사 (secondBrainRepo
        //    비어 있으면 두뇌 동기화가 로컬 새로고침 모드라 자격증명 불필요).
        try {
            if (brain?.secondBrainRepo?.trim() && brain.localBrainPath && fs.existsSync(brain.localBrainPath)) {
                try {
                    execSync('git push --dry-run', {
                        cwd: brain.localBrainPath,
                        env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
                        timeout: 5000,
                        stdio: ['ignore', 'pipe', 'pipe'],
                    });
                } catch (e: any) {
                    const msg = String(e?.stderr || e?.message || '');
                    if (/could not read Username|Authentication failed|terminal prompts disabled/i.test(msg)) {
                        reports.push(`두뇌 원격 push 자격증명이 없습니다 — 터미널에서 "cd ${brain.localBrainPath} && git push" 1회 실행으로 키체인에 저장하세요.`);
                    }
                    // 그 외(오프라인·upstream 없음 등)는 소음 방지 — 보고하지 않음.
                }
            }
        } catch { /* skip */ }

        // 7. Antigravity 확장 버전 정합 — VS Code 와 Antigravity 양쪽에 설치된
        //    경우 버전이 갈리면 "고쳤는데 안 고쳐짐" 혼란의 단골 원인 (실사례:
        //    2.2.19 vs 2.2.232 공존). Antigravity 미사용 머신에서는 자동 skip.
        try {
            const agExtRegistry = path.join(os.homedir(), '.antigravity', 'extensions', 'extensions.json');
            if (fs.existsSync(agExtRegistry)) {
                const arr = JSON.parse(fs.readFileSync(agExtRegistry, 'utf8'));
                const mine = Array.isArray(arr)
                    ? arr.find((e: any) => e?.identifier?.id === 'g1nation.astra')
                    : null;
                const myVersion = vscode.extensions.getExtension('g1nation.astra')?.packageJSON?.version;
                if (mine?.version && myVersion && mine.version !== myVersion) {
                    reports.push(`Antigravity 에 다른 버전의 Astra(${mine.version})가 설치되어 있습니다 — 현재 실행 중 ${myVersion}. Antigravity 쪽은 수동 업데이트가 필요합니다.`);
                }
            }
        } catch { /* registry 파싱 실패 — skip */ }

        this._lastReports = reports;

        if (reports.length > 0) {
            logWarn(`Health Check Warnings: ${reports.join(' | ')}`);
            // 동일 경고 반복 토스트 방지 — 내용이 바뀐 경우에만 1회 토스트.
            const toastKey = reports.join('|');
            if (toastKey !== this._lastToastKey) {
                this._lastToastKey = toastKey;
                vscode.window.showWarningMessage(`Astra Health Warning: ${reports[0]}${reports.length > 1 ? ` (외 ${reports.length - 1}건 — 준비 상태 바 참조)` : ''}`);
            }
        } else {
            this._lastToastKey = '';
        }

        return {
            ok: reports.length === 0,
            reports
        };
    }

    public static startInterval(ms: number = 300000) {
        // Prevent duplicate intervals
        if (this.intervalHandle !== null) {
            clearInterval(this.intervalHandle);
        }
        this.intervalHandle = setInterval(() => this.runAllChecks(), ms);
    }

    /**
     * Stops periodic health checks and releases resources.
     * Should be called from extension.deactivate().
     */
    public static dispose(): void {
        if (this.intervalHandle !== null) {
            clearInterval(this.intervalHandle);
            this.intervalHandle = null;
            logInfo('Health Check: Interval stopped.');
        }
    }
}
