import { NextResponse } from "next/server";

import { requireApiAccess } from "../../../../../lib/api/auth";
import { buildArticleCaseSummary, createProcessStep } from "../../../../../lib/cases/summaries";
import { getRepositoryFromRuntime, type AppRepository } from "../../../../../lib/db/repository";
import type { ArticleJob } from "../../../../../lib/db/repositories";
import type { LlmAuditSummary } from "../../../../../lib/llm/audit";
import { LlmValidationError } from "../../../../../lib/llm/client";
import { getExportStoreFromRuntime } from "../../../../../lib/workflow/export-store";
import { runOptimizationWorkflow } from "../../../../../lib/workflow/orchestrator";
import {
  recordWorkflowProgress,
  startWorkflowProgress,
} from "../../../../../lib/workflow/progress-store";

interface RouteContext {
  params: Promise<{ jobId: string }>;
}

export async function POST(request: Request, context: RouteContext) {
  const access = requireApiAccess(request);
  if (!access.ok) {
    return access.response;
  }

  const { jobId } = await context.params;
  const repository = getRepositoryFromRuntime();
  const job = await repository.getArticleJob(jobId);
  if (!job) {
    return NextResponse.json({ error: "Job not found" }, { status: 404 });
  }

  const factCardRecord = await repository.getFactCard(jobId);
  if (!factCardRecord) {
    return NextResponse.json(
      { error: "Confirm the fact card before optimizing" },
      { status: 409 },
    );
  }

  const requestStartedAt = Date.now();
  const caseId = await ensureArticleCase(repository, job);
  const llmAuditSummary: LlmAuditSummary[] = [];
  startWorkflowProgress(jobId);
  try {
    const result = await runOptimizationWorkflow({
      input: {
        title: job.source_title,
        body: job.source_body,
        images: job.image_inputs,
        platform: job.publish_platform,
        user_instructions: job.user_instructions,
      },
      factCard: factCardRecord,
      onProgress: (event) => {
        recordWorkflowProgress(jobId, event);
      },
      onAuditSummary: (summary) => {
        llmAuditSummary.push(summary);
      },
    });
    const optimizedArticle = await repository.saveOptimizedArticle(
      jobId,
      result.article,
    );
    const qaReport = await repository.saveQaReport(
      jobId,
      optimizedArticle.revision ?? 1,
      result.qaReport,
    );
    const exportStore = getExportStoreFromRuntime();
    const exportPaths = await exportStore.writeJobExports({
      jobId,
      article: optimizedArticle,
      qaReport,
    });
    await repository.updateArticleJob(jobId, {
      status: "optimized",
      export_paths: exportPaths,
    });
    const resultVersion = await repository.createOptimizationResultVersion({
      case_id: caseId,
      case_type: "article",
      status: "optimized",
      article_job_id: jobId,
      article_revision: optimizedArticle.revision ?? 1,
      result_summary: optimizedArticle.summary,
      payload: {
        article: optimizedArticle,
        qa_report: qaReport,
        export_paths: exportPaths,
      },
      process_summary: [],
      llm_audit_summary: llmAuditSummary,
      error_stage: null,
      error_summary: null,
    });

    return NextResponse.json({
      case: { id: caseId, case_type: "article" },
      resultVersion: { id: resultVersion.id, version: resultVersion.version },
      optimizedArticle,
      qaReport,
      exportPaths,
      rewriteRounds: result.rewrite_rounds,
      stoppedAfterMaxRewrites: result.stopped_after_max_rewrites,
      timing: result.timing,
    });
  } catch (error) {
    const message = error instanceof Error ? error.message : "LLM optimization failed";
    await repository.createOptimizationResultVersion({
      case_id: caseId,
      case_type: "article",
      status: "failed",
      article_job_id: jobId,
      article_revision: null,
      result_summary: "",
      payload: null,
      process_summary: [
        createProcessStep({
          stage: "optimize",
          startedAt: requestStartedAt,
          endedAt: Date.now(),
          status: "failed",
          errorSummary: message,
          producedResultVersion: false,
        }),
      ],
      llm_audit_summary: llmAuditSummary,
      error_stage: "optimize",
      error_summary: message,
    });
    return NextResponse.json(
      {
        error: message,
        timing: {
          total_ms: Date.now() - requestStartedAt,
          steps: [],
        },
      },
      { status: getErrorStatus(error) },
    );
  }
}

async function ensureArticleCase(
  repository: AppRepository,
  job: ArticleJob,
) {
  if (job.case_id) return job.case_id;

  const caseSummary = buildArticleCaseSummary({
    source_title: job.source_title,
    source_body: job.source_body,
    publish_platform: job.publish_platform,
  });
  const optimizationCase = await repository.createOptimizationCase({
    case_type: "article",
    ...caseSummary,
  });
  await repository.saveCaseInput({
    case_id: optimizationCase.id,
    case_type: "article",
    article_job_id: job.id,
    payload: {
      source_title: job.source_title,
      source_body: job.source_body,
      image_inputs: job.image_inputs,
      publish_platform: job.publish_platform,
      user_instructions: job.user_instructions,
    },
  });
  return optimizationCase.id;
}

function getErrorStatus(error: unknown) {
  if (error instanceof LlmValidationError) return 502;
  if (error instanceof Error && /^LLM\b|provider/i.test(error.message)) return 502;
  return 500;
}
