import {
  doublePrecision,
  index,
  integer,
  jsonb,
  pgTable,
  text,
  timestamp,
  uniqueIndex,
  uuid,
} from "drizzle-orm/pg-core";
import { createdAt, jobStatusEnum, jobTypeEnum, scanTypeEnum, updatedAt } from "./_shared.js";
import { households } from "./households.js";
import { users } from "./users.js";

/**
 * Asynkrona skannings-/AI-jobb (spec §50, §54):
 * App → signed S3 upload → API job → worker → AAMOS → result → app.
 */
export const scanJobs = pgTable(
  "scan_jobs",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    userId: uuid("user_id")
      .notNull()
      .references(() => users.id, { onDelete: "cascade" }),
    householdId: uuid("household_id").references(() => households.id, { onDelete: "set null" }),
    scanType: scanTypeEnum("scan_type").notNull(),
    jobType: jobTypeEnum("job_type").notNull(),
    status: jobStatusEnum("status").notNull().default("queued"),
    s3Keys: text("s3_keys").array().notNull().default([]),
    context: jsonb("context"),
    /** Strukturerat AI-resultat validerat mot ai-contracts innan lagring. */
    result: jsonb("result"),
    error: text("error"),
    modelVersion: text("model_version"),
    promptVersion: text("prompt_version"),
    latencyMs: integer("latency_ms"),
    costUsd: doublePrecision("cost_usd"),
    attempts: integer("attempts").notNull().default(0),
    completedAt: timestamp("completed_at", { withTimezone: true }),
    createdAt: createdAt(),
    updatedAt: updatedAt(),
  },
  (t) => [
    index("scan_jobs_user_idx").on(t.userId, t.createdAt),
    index("scan_jobs_status_idx").on(t.status),
  ],
);

/**
 * Verifierade korrigeringar (spec §33): AI sa X, användaren sa Y.
 * Grund för träningsdata – används ENDAST enligt samtycke.
 */
export const aiCorrections = pgTable(
  "ai_corrections",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    scanJobId: uuid("scan_job_id").references(() => scanJobs.id, { onDelete: "set null" }),
    userId: uuid("user_id")
      .notNull()
      .references(() => users.id, { onDelete: "cascade" }),
    taskType: text("task_type").notNull(),
    aiOutput: jsonb("ai_output").notNull(),
    userCorrection: jsonb("user_correction").notNull(),
    /** The specific AI proposal item this correction refers to. */
    proposal: jsonb("proposal"),
    /** First stored image key when image_training consent granted, otherwise null. */
    imageS3Key: text("image_s3_key"),
    modelVersion: text("model_version"),
    promptVersion: text("prompt_version"),
    /** Snapshot av samtyckesläget när korrigeringen skapades. */
    consentSnapshot: jsonb("consent_snapshot").notNull(),
    exportedToTraining: timestamp("exported_to_training", { withTimezone: true }),
    trainingBatchId: text("training_batch_id"),
    createdAt: createdAt(),
  },
  (t) => [index("ai_corrections_task_idx").on(t.taskType, t.createdAt)],
);

/**
 * App-owned, versioned training dataset (spec §33 + Skiva 1 fixrunda).
 * BUILD_TRAINING_SAMPLE banks eligible ai_corrections here instead of
 * calling external AAMOS/Gemini runTask. The bank is the consented place
 * for richer (image, proposal, correction) data.
 */
export const aiTrainingBank = pgTable(
  "ai_training_bank",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    correctionId: uuid("correction_id")
      .notNull()
      .references(() => aiCorrections.id, { onDelete: "cascade" }),
    scanJobId: uuid("scan_job_id").references(() => scanJobs.id, { onDelete: "set null" }),
    version: text("version").notNull().default("v1"),
    taskType: text("task_type").notNull(),
    imageS3Key: text("image_s3_key"),
    proposal: jsonb("proposal").notNull(),
    action: text("action").notNull(),
    corrected: jsonb("corrected"),
    modelVersion: text("model_version"),
    promptVersion: text("prompt_version"),
    consentSnapshot: jsonb("consent_snapshot").notNull().default({}),
    exportedAt: timestamp("exported_at", { withTimezone: true }).notNull().defaultNow(),
    createdAt: createdAt(),
  },
  (t) => [
    uniqueIndex("ai_training_bank_correction_unique").on(t.correctionId),
    index("ai_training_bank_version_idx").on(t.version, t.taskType),
    index("ai_training_bank_scan_job_idx").on(t.scanJobId),
    index("ai_training_bank_created_at_idx").on(t.createdAt),
  ],
);
