import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import { ProjectChronicleManager, ProjectProfile } from '../src/features/projectChronicle';

function makeProfile(root: string): ProjectProfile {
    const now = '2026-05-02T00:00:00.000Z';
    return {
        projectId: 'test-project',
        projectName: 'Test Project',
        projectRoot: root,
        recordRoot: path.join(root, 'records', 'Test Project'),
        description: 'Test project records',
        corePurpose: 'Verify chronicle records',
        detailLevel: 'standard',
        createdAt: now,
        updatedAt: now
    };
}

describe('ProjectChronicleManager', () => {
    let tempRoot: string;
    let manager: ProjectChronicleManager;
    let profile: ProjectProfile;

    beforeEach(() => {
        tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'chronicle-'));
        manager = new ProjectChronicleManager();
        profile = makeProfile(tempRoot);
    });

    afterEach(() => {
        fs.rmSync(tempRoot, { recursive: true, force: true });
    });

    it('creates the project record structure and seed files', () => {
        manager.ensureProject(profile);

        expect(fs.existsSync(path.join(profile.recordRoot, 'README.md'))).toBe(true);
        expect(fs.existsSync(path.join(profile.recordRoot, 'chronicle.config.json'))).toBe(true);
        expect(fs.existsSync(path.join(profile.recordRoot, 'project-profile.md'))).toBe(true);
        expect(fs.existsSync(path.join(profile.recordRoot, 'timeline.md'))).toBe(true);
        expect(fs.existsSync(path.join(profile.recordRoot, 'planning'))).toBe(true);
        expect(fs.existsSync(path.join(profile.recordRoot, 'decisions'))).toBe(true);
        expect(fs.existsSync(path.join(profile.recordRoot, 'development'))).toBe(true);
        expect(fs.existsSync(path.join(profile.recordRoot, 'bugs'))).toBe(true);

        const config = JSON.parse(fs.readFileSync(path.join(profile.recordRoot, 'chronicle.config.json'), 'utf8'));
        expect(config.projectId).toBe(profile.projectId);
        expect(config.recordRoot).toBe(profile.recordRoot);
    });

    it('writes planning records without overwriting existing files', () => {
        const first = manager.writePlanning(profile, {
            featureName: 'Record Guard',
            purpose: 'Purpose',
            background: 'Background',
            userIntent: 'Intent',
            scope: ['Scope'],
            outOfScope: ['Out'],
            developmentDirection: 'Direction',
            dependencyStrategy: 'Dependency',
            expectedValue: 'Value',
            successCriteria: ['Success'],
            developerInstruction: 'Instruction',
            createdAt: '2026-05-02T00:00:00.000Z'
        });

        const second = manager.writePlanning(profile, {
            featureName: 'Record Guard',
            purpose: 'Purpose',
            background: 'Background',
            userIntent: 'Intent',
            scope: ['Scope'],
            outOfScope: ['Out'],
            developmentDirection: 'Direction',
            dependencyStrategy: 'Dependency',
            expectedValue: 'Value',
            successCriteria: ['Success'],
            developerInstruction: 'Instruction',
            createdAt: '2026-05-02T00:00:00.000Z'
        });

        expect(first.filePath).not.toBe(second.filePath);
        expect(path.basename(second.filePath)).toBe('2026-05-02_record-guard-2.md');
    });

    it('increments ADR and bug numbers from existing files', () => {
        manager.ensureProject(profile);
        fs.writeFileSync(path.join(profile.recordRoot, 'decisions', 'ADR-0007-existing.md'), '# Existing\n');
        fs.writeFileSync(path.join(profile.recordRoot, 'bugs', 'BUG-0003-existing.md'), '# Existing\n');

        expect(manager.nextAdrNumber(profile)).toBe(8);
        expect(manager.nextBugNumber(profile)).toBe(4);
    });

    it('writes discussion, decision, bug, development, and retrospective records', () => {
        const discussion = manager.writeDiscussion(profile, {
            title: 'Question Intent',
            userRequest: 'Record why the AI asked a question.',
            interpretedIntent: 'Preserve reasoning behind clarification.',
            questions: [{
                question: 'Which project should this be recorded under?',
                reason: 'Records must not be mixed across projects.',
                expectedInformation: 'The active project name and record path.',
                impactOnDecision: 'Determines where generated Markdown is written.'
            }],
            discussions: ['The project context must be explicit before writing files.'],
            decisions: [],
            createdAt: '2026-05-02T00:00:00.000Z'
        });

        const decision = manager.writeDecision(profile, {
            title: 'Use Markdown Records',
            status: 'accepted',
            context: 'Records should be portable.',
            decision: 'Store records as Markdown.',
            reason: 'Markdown works without external services.',
            alternatives: ['External DB'],
            consequences: ['Easy to inspect in the repository.'],
            createdAt: '2026-05-02T00:00:00.000Z'
        }, manager.nextAdrNumber(profile));

        const development = manager.writeDevelopmentLog(profile, {
            featureName: 'Chronicle Writer',
            purpose: 'Verify write paths.',
            implementationSummary: 'Wrote supported record types.',
            architecture: 'Manager -> Writer -> Markdown.',
            changedFiles: ['src/features/projectChronicle/index.ts'],
            dependencyNotes: 'No external services.',
            bugs: [],
            lessons: ['Keep record types explicit.'],
            createdAt: '2026-05-02T00:00:00.000Z'
        });

        const bug = manager.writeBug(profile, {
            title: 'Missing Record Root',
            symptom: 'Write cannot proceed.',
            cause: 'Record root is empty.',
            fix: 'Validate profile before write.',
            prevention: 'Require selected project.',
            createdAt: '2026-05-02T00:00:00.000Z'
        }, manager.nextBugNumber(profile));

        const retrospective = manager.writeRetrospective(profile, {
            title: 'Chronicle Iteration',
            summary: 'Record generation was expanded.',
            wentWell: ['Independent module stayed small.'],
            toImprove: ['Add richer UI later.'],
            nextActions: ['Capture events automatically.'],
            createdAt: '2026-05-02T00:00:00.000Z'
        });

        for (const result of [discussion, decision, development, bug, retrospective]) {
            expect(fs.existsSync(result.filePath)).toBe(true);
        }

        expect(discussion.relativePath).toContain('discussions' + path.sep);
        expect(decision.relativePath).toContain('decisions' + path.sep);
        expect(development.relativePath).toContain('development' + path.sep);
        expect(bug.relativePath).toContain('bugs' + path.sep);
        expect(retrospective.relativePath).toContain('retrospectives' + path.sep);
    });

    it('lists chronicle records across sections with relative paths', () => {
        manager.writePlanning(profile, {
            featureName: 'Record List',
            purpose: 'Purpose',
            background: 'Background',
            userIntent: 'Intent',
            scope: ['Scope'],
            outOfScope: ['Out'],
            developmentDirection: 'Direction',
            dependencyStrategy: 'Dependency',
            expectedValue: 'Value',
            successCriteria: ['Success'],
            developerInstruction: 'Instruction',
            createdAt: '2026-05-02T00:00:00.000Z'
        });
        manager.writeBug(profile, {
            title: 'List Bug',
            symptom: 'Symptom',
            cause: 'Cause',
            fix: 'Fix',
            prevention: 'Prevention',
            createdAt: '2026-05-02T00:00:00.000Z'
        }, 1);

        const records = manager.listRecords(profile);

        expect(records.length).toBe(2);
        expect(records.map(record => record.relativePath)).toEqual(
            expect.arrayContaining([
                path.join('planning', '2026-05-02_record-list.md'),
                path.join('bugs', 'BUG-0001-list-bug.md')
            ])
        );
    });
});
