import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";

import { afterEach, beforeEach, describe, expect, test } from "vitest";

import { createSqliteRepository } from "../sqlite-repository";

describe("createSqliteRepository", () => {
  let tempDir: string;
  let dbPath: string;

  beforeEach(() => {
    tempDir = mkdtempSync(join(tmpdir(), "geo-repository-"));
    dbPath = join(tempDir, "app.db");
  });

  afterEach(() => {
    rmSync(tempDir, { recursive: true, force: true });
  });

  test("creates and reads an article job through the async repository interface", async () => {
    const repository = createSqliteRepository(dbPath);

    const job = await repository.createArticleJob({
      source_title: "Title",
      source_body: "Body",
      image_inputs: [],
      publish_platform: "official_site",
      user_instructions: "",
    });

    await expect(repository.getArticleJob(job.id)).resolves.toMatchObject({
      id: job.id,
      source_title: "Title",
      export_paths: {},
    });
  });

  test("persists scoring, publication, performance, and calibration event", async () => {
    const repository = createSqliteRepository(dbPath);
    const job = await repository.createArticleJob({
      source_title: "Title",
      source_body: "Body",
      image_inputs: [],
      publish_platform: "official_site",
      user_instructions: "",
    });
    const article = await repository.saveOptimizedArticle(job.id, {
      title: "Optimized",
      summary: "Summary",
      body_markdown: "Body",
      image_suggestions: [],
      changed_sections: [],
      requires_user_confirmation: [],
    });

    await repository.saveRubricVersion({
      id: "rubric_geo_v1",
      version: "v1",
      name: "GEO rubric",
      dimensions: [],
      formula: "weighted_average_0_to_10",
      is_active: true,
      created_at: "2026-06-24T00:00:00.000Z",
    });
    const scoringRun = await repository.saveScoringRun({
      id: "score_1",
      job_id: job.id,
      revision: article.revision ?? 1,
      rubric_version_id: "rubric_geo_v1",
      dimension_scores: { readability: 4 },
      composite_score: 8,
      rationale: "Readable",
      created_at: "2026-06-24T00:00:00.000Z",
    });
    const publication = await repository.createPublicationRecord({
      job_id: job.id,
      revision: article.revision ?? 1,
      platform: "official_site",
      url: "https://example.com/article",
      published_at: "2026-06-24T12:00:00.000Z",
      status: "published",
      notes: "官网首发",
    });
    const snapshot = await repository.savePerformanceSnapshot({
      id: "perf_1",
      publication_id: publication.id,
      source: "manual",
      window_label: "T+7d",
      metrics: { views: 1200 },
      feedback_summary: "用户追问案例依据",
      snapshot_at: "2026-07-01T12:00:00.000Z",
    });
    const event = await repository.saveCalibrationEvent({
      id: "cal_1",
      publication_id: publication.id,
      scoring_run_id: scoringRun.id,
      performance_snapshot_id: snapshot.id,
      direction: "better_than_expected",
      observations: ["表现高于预期"],
      recommended_action: "继续积累样本",
      created_at: "2026-07-01T12:10:00.000Z",
    });

    await expect(repository.listPublicationRecords(job.id)).resolves.toHaveLength(1);
    await expect(repository.getLatestScoringRun(job.id, article.revision ?? 1))
      .resolves.toMatchObject({ id: scoringRun.id, composite_score: 8 });
    await expect(repository.listPerformanceSnapshots(publication.id)).resolves.toEqual([
      expect.objectContaining({ id: snapshot.id }),
    ]);
    expect(event.observations).toEqual(["表现高于预期"]);
  });
});
