import { z } from 'zod';
import { writeFile, mkdir } from 'node:fs/promises';
import { dirname, join, isAbsolute } from 'node:path';
import { safe } from './safe-handler.js';
import { hashProjectPath, projectDataDir } from '../storage/base-store.js';
import { specStore, knowledgeStore, decisionStore, metricsStore } from '../storage/index.js';
import { loadAllRiskRegisters } from '../storage/risk-store.js';
import { generateProposal } from '../engine/doc-generator/proposal/proposal-generator.js';
import { SpecIdSchema } from './schemas/index.js';
// ── Zod schema ────────────────────────────────────────────────────────────────
const PhaseSchema = z.object({
    name: z.string().describe('Phase name (e.g. "Phase 1 — Core", "MVP")'),
    specIds: z.array(SpecIdSchema).describe('List of spec IDs included in this phase'),
    color: z
        .string()
        .optional()
        .describe('Hex color for the phase bar in the Gantt chart (e.g. "#7c3aed")'),
});
const ProposalInputSchema = {
    projectPath: z.string().describe('Absolute path to the project root directory'),
    title: z
        .string()
        .optional()
        .describe('Custom title for the proposal document (default: project folder name)'),
    subtitle: z
        .string()
        .optional()
        .describe('Subtitle or tagline (e.g. "Technical Proposal Q2 2026")'),
    client: z
        .string()
        .optional()
        .describe('Client or stakeholder name displayed in the hero section'),
    author: z.string().optional().describe('Author or company name'),
    logo: z
        .string()
        .optional()
        .describe('URL or base64 data URI for the logo image (displayed in hero)'),
    currency: z.string().optional().describe('Currency code for cost display (default: USD)'),
    hourlyRate: z
        .number()
        .positive()
        .optional()
        .describe('Custom hourly rate in the specified currency — overrides spec-level rates'),
    phases: z
        .array(PhaseSchema)
        .optional()
        .describe('Group specs into named phases for the timeline and breakdown table'),
    includeSections: z
        .array(z.string())
        .optional()
        .describe('Only render these sections. Valid values: hero, executive-summary, scope, ' +
        'spec-breakdown, timeline, budget, investment-summary, architecture, risk, ' +
        'decisions, impact-analysis, gap-analysis, team-resources, pricing-methodology, ' +
        'design-system, quality-metrics, living-spec, assumptions, alternatives, ' +
        'post-launch, module-mapping'),
    excludeSections: z
        .array(z.string())
        .optional()
        .describe('Sections to exclude from the output (same values as includeSections)'),
    theme: z
        .enum(['dark', 'light', 'corporate', 'startup'])
        .optional()
        .describe('Visual theme for the document. Values: dark (dark bg, purple/red accent), ' +
        'light (white bg, indigo accent), corporate (navy, professional), ' +
        'startup (green gradient, modern). Default: light'),
    language: z
        .enum(['en', 'es', 'pt'])
        .optional()
        .describe('Document language for all static labels. Values: en (English), es (Spanish), pt (Portuguese). Default: en'),
    outputPath: z
        .string()
        .optional()
        .describe('Output file path relative to projectPath (default: planu/proposal.html)'),
    confidential: z.boolean().optional().describe('Add CONFIDENTIAL banner to the document'),
    expiresAt: z
        .string()
        .optional()
        .describe('Proposal expiry date displayed in the hero (e.g. "2026-06-30")'),
    ganttStartDate: z
        .string()
        .optional()
        .describe('Start date for the Gantt chart (ISO format, e.g. "2026-04-01")'),
    paymentTerms: z
        .string()
        .optional()
        .describe('Payment terms text shown in the scope section (e.g. "50% upfront, 50% on delivery")'),
};
// ── Handler ───────────────────────────────────────────────────────────────────
async function handleGenerateProposal(args) {
    const projectId = hashProjectPath(args.projectPath);
    const dataDir = projectDataDir(projectId);
    // Load specs (required)
    const specs = await specStore.listSpecs(projectId);
    // Load optional data — catch errors gracefully
    const [risks, decisions, knowledge, metricsHistory] = await Promise.all([
        loadAllRiskRegisters(dataDir).catch(() => []),
        decisionStore.getDecisions(projectId).catch(() => []),
        knowledgeStore.getKnowledge(projectId).catch(() => null),
        metricsStore.getMetricsHistory(projectId).catch(() => undefined),
    ]);
    const config = {
        title: args.title,
        subtitle: args.subtitle,
        client: args.client,
        author: args.author,
        logo: args.logo,
        currency: args.currency ?? 'USD',
        hourlyRate: args.hourlyRate,
        phases: args.phases,
        includeSections: args.includeSections,
        excludeSections: args.excludeSections,
        theme: args.theme ?? 'light',
        language: args.language ?? 'en',
        outputPath: args.outputPath,
        confidential: args.confidential ?? false,
        expiresAt: args.expiresAt,
        ganttStartDate: args.ganttStartDate,
        paymentTerms: args.paymentTerms,
    };
    // Derive project name from path
    const projectName = args.projectPath.split('/').filter(Boolean).pop() ?? 'Project';
    const proposalData = {
        config,
        projectName,
        projectPath: args.projectPath,
        specs,
        risks: risks.length > 0 ? risks : undefined,
        decisions: decisions.length > 0 ? decisions : undefined,
        knowledge: knowledge ?? undefined,
        metrics: metricsHistory ?? undefined,
    };
    const html = generateProposal(proposalData);
    // Resolve output path
    const relOutput = args.outputPath ?? 'planu/proposal.html';
    const outputFilePath = isAbsolute(relOutput) ? relOutput : join(args.projectPath, relOutput);
    await mkdir(dirname(outputFilePath), { recursive: true });
    await writeFile(outputFilePath, html, 'utf-8');
    const sizeKb = Math.round(html.length / 1024);
    const riskCount = risks.flatMap((r) => r.risks).length;
    const decisionCount = decisions.length;
    return {
        content: [
            {
                type: 'text',
                text: [
                    `Proposal generated successfully.`,
                    `File: ${outputFilePath}`,
                    `Specs: ${String(specs.length)} | Risks: ${String(riskCount)} | Decisions: ${String(decisionCount)}`,
                    `Size: ${String(sizeKb)} KB | Theme: ${config.theme ?? 'light'} | Language: ${config.language ?? 'en'}`,
                ].join('\n'),
            },
        ],
    };
}
// ── Registration ──────────────────────────────────────────────────────────────
export function registerGenerateProposalTool(server) {
    server.registerTool('generate_proposal', {
        description: 'Generate a self-contained HTML project proposal with KPI grid, Gantt chart, ' +
            'spec breakdown table, risk analysis, budget summary, and architecture overview. ' +
            'Pulls real data from spec-store, risk-store, decision-store, and knowledge-store. ' +
            'Supports 4 visual themes (dark/light/corporate/startup), 3 languages (en/es/pt), ' +
            'and 22 conditional sections. Output is a single HTML file ready for client delivery.',
        inputSchema: ProposalInputSchema,
        annotations: { title: 'Generate Project Proposal', readOnlyHint: false },
    }, safe(async (args) => handleGenerateProposal(args)));
}
//# sourceMappingURL=generate-proposal.js.map