import "./setup-env.js";
import { describe, it, expect, beforeAll, afterAll } from "vitest";
import { eq } from "drizzle-orm";
import { createDatabase, closeDatabase, schema } from "@app/database";
import { processTrainingExport } from "../src/processors/maintenance.js";

describe("BUILD_TRAINING_SAMPLE banks locally", () => {
  const testDb = createDatabase(process.env.TEST_DATABASE_URL!);
  const email = "training-export-test@example.invalid";

  async function cleanup() {
    const existing = await testDb.db.select({ id: schema.users.id }).from(schema.users).where(eq(schema.users.email, email));
    for (const u of existing) {
      await testDb.db.delete(schema.aiCorrections).where(eq(schema.aiCorrections.userId, u.id));
      await testDb.db.delete(schema.userConsents).where(eq(schema.userConsents.userId, u.id));
      await testDb.db.delete(schema.scanJobs).where(eq(schema.scanJobs.userId, u.id));
      await testDb.db.delete(schema.users).where(eq(schema.users.id, u.id));
    }
  }

  beforeAll(async () => {
    await cleanup();
  });

  afterAll(async () => {
    await cleanup();
    await closeDatabase();
  });

  it("banks eligible corrections locally and does not throw in gemini mode", async () => {
    const [user] = await testDb.db
      .insert(schema.users)
      .values({
        email: "training-export-test@example.invalid",
        passwordHash: "not-used",
        displayName: "Training Export Test",
      })
      .returning();
    const userId = user!.id;

    await testDb.db.insert(schema.userConsents).values([
      { userId, kind: "anonymized_improvement", status: "granted" },
      { userId, kind: "image_training", status: "granted" },
    ]);

    const [job] = await testDb.db
      .insert(schema.scanJobs)
      .values({
        userId,
        scanType: "fridge",
        jobType: "ANALYZE_FRIDGE_IMAGE",
        status: "completed",
        s3Keys: ["fridge-scans/train.jpg"],
        result: { items: [] },
      })
      .returning();

    const [correction] = await testDb.db
      .insert(schema.aiCorrections)
      .values({
        scanJobId: job!.id,
        userId,
        taskType: "ANALYZE_FRIDGE_IMAGE",
        aiOutput: { raw: { items: [] } },
        proposal: { detectedName: "Mellanmjölk", confidence: 0.98 },
        userCorrection: { action: "accept", corrected: { displayName: "Mellanmjölk", quantity: 1, unit: "LITER" } },
        imageS3Key: "fridge-scans/train.jpg",
        modelVersion: "gemini-2.5-flash",
        promptVersion: "gemini-fridge-v1",
        consentSnapshot: { anonymized_improvement: "granted", image_training: "granted" },
      })
      .returning();

    // Force gemini mode in environment so we prove the job does not call AAMOS.
    const previousMode = process.env.AAMOS_MODE;
    process.env.AAMOS_MODE = "gemini";

    const exported = await processTrainingExport({ db: testDb.db } as never);

    process.env.AAMOS_MODE = previousMode;

    expect(exported).toBe(1);

    const banked = await testDb.db
      .select()
      .from(schema.aiTrainingBank)
      .where(eq(schema.aiTrainingBank.correctionId, correction!.id));
    expect(banked).toHaveLength(1);
    expect(banked[0]!.version).toBe("v1");
    expect(banked[0]!.imageS3Key).toBe("fridge-scans/train.jpg");
    expect(banked[0]!.action).toBe("accept");

    const updated = await testDb.db
      .select()
      .from(schema.aiCorrections)
      .where(eq(schema.aiCorrections.id, correction!.id));
    expect(updated[0]!.exportedToTraining).not.toBeNull();
    expect(updated[0]!.trainingBatchId).toMatch(/^cibello-local-v1-/);
  });
});
