/**
 * ============================================================
 * Project Memory (프로젝트 기억)
 * 
 * 프로젝트별 요구사항, 코드 구조, 아키텍처 결정, 버그 기록 등을
 * Astra 확장 프로그램 내부에 저장하고 관리합니다.
 * 저장 위치: {ConnectAI}/.astra/project_memory.json
 * (기존: {projectRoot}/.astra/ → 변경됨)
 * ============================================================
 */

import * as fs from 'fs';
import * as path from 'path';
import * as crypto from 'crypto';
import { ProjectMemoryStore, ArchitectureDecision, BugRecord, MemoryContextResult } from './types';
import { getAstraDataDir } from '../core/astraPath';

export class ProjectMemory {
    private store: ProjectMemoryStore;
    private filePath: string;
    private dirty = false;

    constructor(projectRoot: string) {
        // .astra 디렉토리를 ConnectAI 내부에서 해결 (사용자 프로젝트 루트에 생성하지 않음)
        const astraDir = getAstraDataDir();
        this.filePath = path.join(astraDir, 'project_memory.json');
        this.store = this.load(projectRoot);
    }

    // ─── Persistence ───

    private load(projectRoot: string): ProjectMemoryStore {
        try {
            if (fs.existsSync(this.filePath)) {
                const raw = fs.readFileSync(this.filePath, 'utf-8');
                return JSON.parse(raw) as ProjectMemoryStore;
            }
        } catch { /* start fresh */ }

        return {
            version: 1,
            projectId: this.hashPath(projectRoot),
            projectName: path.basename(projectRoot),
            techStack: [],
            architectureDecisions: [],
            bugRecords: [],
            requirements: [],
            designDirection: '',
            codeConventions: [],
            lastUpdated: Date.now()
        };
    }

    public save(): void {
        if (!this.dirty) return;
        try {
            this.store.lastUpdated = Date.now();
            fs.writeFileSync(this.filePath, JSON.stringify(this.store, null, 2), 'utf-8');
            this.dirty = false;
        } catch { /* silently fail */ }
    }

    private hashPath(p: string): string {
        return crypto.createHash('sha256').update(p).digest('hex').slice(0, 12);
    }

    // ─── Getters ───

    public getStore(): ProjectMemoryStore {
        return { ...this.store };
    }

    // ─── Tech Stack ───

    public setTechStack(stack: string[]): void {
        this.store.techStack = [...new Set(stack)];
        this.dirty = true;
        this.save();
    }

    public addTechStack(tech: string): void {
        if (!this.store.techStack.includes(tech)) {
            this.store.techStack.push(tech);
            this.dirty = true;
            this.save();
        }
    }

    // ─── Architecture Decisions ───

    public addArchitectureDecision(
        title: string,
        decision: string,
        rationale: string,
        alternatives: string[] = []
    ): ArchitectureDecision {
        const entry: ArchitectureDecision = {
            id: crypto.randomUUID(),
            title,
            decision,
            rationale,
            alternatives,
            date: Date.now()
        };
        this.store.architectureDecisions.push(entry);
        this.dirty = true;
        this.save();
        return entry;
    }

    // ─── Bug Records ───

    public addBugRecord(
        description: string,
        rootCause: string,
        fix: string,
        relatedFiles: string[] = []
    ): BugRecord {
        const entry: BugRecord = {
            id: crypto.randomUUID(),
            description,
            rootCause,
            fix,
            date: Date.now(),
            relatedFiles
        };
        this.store.bugRecords.push(entry);
        this.dirty = true;
        this.save();
        return entry;
    }

    // ─── Requirements ───

    public addRequirement(req: string): void {
        if (!this.store.requirements.includes(req)) {
            this.store.requirements.push(req);
            this.dirty = true;
            this.save();
        }
    }

    // ─── Design Direction ───

    public setDesignDirection(direction: string): void {
        this.store.designDirection = direction;
        this.dirty = true;
        this.save();
    }

    // ─── Code Conventions ───

    public addCodeConvention(convention: string): void {
        if (!this.store.codeConventions.includes(convention)) {
            this.store.codeConventions.push(convention);
            this.dirty = true;
            this.save();
        }
    }

    // ─── Context Building ───

    public buildContext(currentPrompt: string): MemoryContextResult | null {
        const sections: string[] = [];

        if (this.store.techStack.length > 0) {
            sections.push(`Tech Stack: ${this.store.techStack.join(', ')}`);
        }

        if (this.store.designDirection) {
            sections.push(`Design Direction: ${this.store.designDirection}`);
        }

        if (this.store.codeConventions.length > 0) {
            sections.push(`Code Conventions:\n${this.store.codeConventions.map((c) => `  - ${c}`).join('\n')}`);
        }

        if (this.store.requirements.length > 0) {
            const reqs = this.store.requirements.slice(-5);
            sections.push(`Recent Requirements:\n${reqs.map((r) => `  - ${r}`).join('\n')}`);
        }

        // Show recent architecture decisions (last 3)
        if (this.store.architectureDecisions.length > 0) {
            const recent = this.store.architectureDecisions
                .sort((a, b) => b.date - a.date)
                .slice(0, 3);
            sections.push(
                `Architecture Decisions:\n${recent.map((d) => `  - ${d.title}: ${d.decision}`).join('\n')}`
            );
        }

        // Show recent bugs (last 3)
        if (this.store.bugRecords.length > 0) {
            const recent = this.store.bugRecords
                .sort((a, b) => b.date - a.date)
                .slice(0, 3);
            sections.push(
                `Recent Bugs:\n${recent.map((b) => `  - ${b.description} → ${b.fix}`).join('\n')}`
            );
        }

        if (sections.length === 0) return null;

        return {
            layer: 'project',
            label: `Project Memory (${this.store.projectName})`,
            content: sections.join('\n'),
            relevance: 0.8
        };
    }
}
