import { writeFileSync, mkdirSync, existsSync } from "node:fs";
import { join } from "node:path";
import type { RoastResponse, RoastIssue, ToolResponse } from "./api.js";

const REPORT_DIR = ".sally";

/** Ensure .sally/ directory exists in the project root */
function ensureReportDir(): string {
  const dir = join(process.cwd(), REPORT_DIR);
  if (!existsSync(dir)) {
    mkdirSync(dir, { recursive: true, mode: 0o700 });
  }
  return dir;
}

/** Shared voice footer for all report types (#5: deduplicated) */
function appendVoiceFooter(lines: string[], voice: { bright_side: string; hardest_sneer: string }): void {
  lines.push("---");
  lines.push("");
  if (voice.bright_side) {
    lines.push(`> ✨ ${voice.bright_side}`);
    lines.push("");
  }
  if (voice.hardest_sneer) {
    lines.push(`> 🔥 ${voice.hardest_sneer}`);
    lines.push("");
  }
  lines.push("---");
  lines.push("");
  lines.push("*Generated by [Cynical Sally](https://cynicalsally.com)*");
  lines.push("");
}

/**
 * Save a Full Truth review as a markdown report.
 * Returns the file path if saved, null if skipped/failed.
 */
export function saveReport(response: RoastResponse, source: string): string | null {
  try {
    const { data, voice, meta } = response;
    const date = new Date().toISOString().split("T")[0];
    const dir = ensureReportDir();
    const filename = `review-${date}.md`;
    const filepath = join(dir, filename);

    const lines: string[] = [];

    lines.push(`# Sally's ${meta.mode === "full_truth" ? "Full Truth" : "Quick Roast"} Review`);
    lines.push("");
    lines.push(`**Date:** ${date}`);
    lines.push(`**Source:** ${source}`);
    lines.push(`**Files reviewed:** ${meta.files_reviewed}`);
    lines.push(`**Score:** ${data.score.toFixed(1)}/10`);
    lines.push("");
    lines.push("---");
    lines.push("");

    lines.push("## Sally's Verdict");
    lines.push("");
    const paragraphs = voice.roast.split("\n\n");
    for (const p of paragraphs) {
      lines.push(p);
      lines.push("");
    }

    if (data.issues && data.issues.length > 0) {
      lines.push("---");
      lines.push("");
      lines.push("## Top Issues");
      lines.push("");

      for (let i = 0; i < data.issues.length; i++) {
        const issue = data.issues[i] as RoastIssue;
        const severity = issue.severity.toUpperCase();
        lines.push(`### ${i + 1}. \`${issue.issue_code}\` — ${severity}`);
        lines.push("");
        lines.push(`**${issue.title}**`);
        lines.push("");
        lines.push(issue.description);
        lines.push("");

        if (issue.evidence && issue.evidence.length > 0) {
          for (const e of issue.evidence) {
            lines.push(`- → ${e}`);
          }
          lines.push("");
        }

        if (issue.fix) {
          lines.push(`**Fix:** ${issue.fix}`);
          lines.push("");
        }
      }
    }

    if (data.actionable_fixes && data.actionable_fixes.length > 0) {
      lines.push("---");
      lines.push("");
      lines.push("## Actionable Fixes");
      lines.push("");
      for (const fix of data.actionable_fixes) {
        lines.push(`- ✓ ${fix}`);
      }
      lines.push("");
    }

    appendVoiceFooter(lines, voice);

    writeFileSync(filepath, lines.join("\n"), { encoding: "utf-8", mode: 0o600 });
    return filepath;
  } catch {
    return null;
  }
}

/**
 * Save a premium tool response as a markdown report.
 * Returns the file path if saved, null if skipped/failed.
 */
export function saveToolReport(response: ToolResponse): string | null {
  try {
    const date = new Date().toISOString().split("T")[0];
    const time = new Date().toISOString().split("T")[1].slice(0, 5).replace(":", "");
    const dir = ensureReportDir();
    const toolLabel = response.tool.replace("_", "-");
    const filename = `${toolLabel}-${date}-${time}.md`;
    const filepath = join(dir, filename);

    const lines: string[] = [];
    const displayTool = response.tool.replace("_", " ");

    lines.push(`# Sally's ${displayTool}`);
    lines.push("");
    lines.push(`**Date:** ${date}`);
    lines.push(`**Tool:** ${displayTool}`);
    lines.push("");
    lines.push("---");
    lines.push("");

    // Messages
    if (response.messages && response.messages.length > 0) {
      for (const msg of response.messages) {
        lines.push(msg.text);
        lines.push("");
      }
    }

    // Score
    const score = response.data.scorecard as number | undefined;
    if (typeof score === "number") {
      lines.push(`**Score:** ${score.toFixed(1)}/10`);
      lines.push("");
    }

    // Verdict
    const verdict = response.data.verdict as string | undefined;
    if (verdict) {
      lines.push(`**Verdict:** ${verdict}`);
      lines.push("");
    }

    // Refactors
    const refactors = response.data.refactors as Array<{ title: string; priority: string; before: string; after: string }> | undefined;
    if (refactors && refactors.length > 0) {
      lines.push("## Refactoring Suggestions");
      lines.push("");
      for (let i = 0; i < refactors.length; i++) {
        const r = refactors[i];
        lines.push(`### ${i + 1}. ${r.priority.toUpperCase()} — ${r.title}`);
        if (r.before) lines.push(`\`\`\`\n// Before\n${r.before}\n\`\`\``);
        if (r.after) lines.push(`\`\`\`\n// After\n${r.after}\n\`\`\``);
        lines.push("");
      }
    }

    // Issues
    const issues = response.data.issues as Array<{ category: string; severity: string; description: string; fix: string }> | undefined;
    if (issues && issues.length > 0) {
      lines.push("## Issues");
      lines.push("");
      for (let i = 0; i < issues.length; i++) {
        const issue = issues[i];
        lines.push(`### ${i + 1}. ${issue.severity.toUpperCase()} [${issue.category}]`);
        lines.push(issue.description);
        if (issue.fix) lines.push(`**Fix:** ${issue.fix}`);
        lines.push("");
      }
    }

    // Rewrites
    const rewrites = response.data.rewrites as Array<{ original: string; improved: string; why: string }> | undefined;
    if (rewrites && rewrites.length > 0) {
      lines.push("## Copy Rewrites");
      lines.push("");
      for (const rw of rewrites) {
        lines.push(`- **Before:** "${rw.original}"`);
        lines.push(`  **After:** "${rw.improved}"`);
        lines.push(`  *${rw.why}*`);
        lines.push("");
      }
    }

    appendVoiceFooter(lines, response.voice);

    writeFileSync(filepath, lines.join("\n"), { encoding: "utf-8", mode: 0o600 });
    return filepath;
  } catch {
    return null;
  }
}
