import type { FastifyInstance } from "fastify";
import { and, desc, eq, or } from "drizzle-orm";
import { schema } from "@app/database";
import { buildMemoryOverview } from "@app/memory-client";
import { userLanguageTag } from "../lib/contentLanguage.js";
import { idParamSchema, memoryQuerySchema, updateMemoryItemInputSchema } from "@app/validation";
import { errors, parse } from "../lib/errors.js";
import { audit, emitEvent, getActiveHouseholdId } from "../lib/helpers.js";

/**
 * "Vad plattformen vet om mig" (spec §32): full transparens.
 * Användaren kan korrigera, pausa, radera varje post – och radera allt.
 */
export async function memoryRoutes(app: FastifyInstance) {
  const auth = { preHandler: [app.authenticate] };

  app.get("/v1/me/memory", auth, async (req) => {
    const q = parse(memoryQuerySchema, req.query);
    const householdId = await getActiveHouseholdId(app.db, req.userId);

    const scope = householdId
      ? or(
          eq(schema.memoryItems.userId, req.userId),
          eq(schema.memoryItems.householdId, householdId),
        )!
      : eq(schema.memoryItems.userId, req.userId);
    const conditions = [scope];
    if (q.kind) conditions.push(eq(schema.memoryItems.kind, q.kind));
    if (!q.includePaused) conditions.push(eq(schema.memoryItems.paused, false));

    const items = await app.db
      .select()
      .from(schema.memoryItems)
      .where(and(...conditions))
      .orderBy(desc(schema.memoryItems.updatedAt))
      .limit(q.limit)
      .offset(q.offset);

    const overview = buildMemoryOverview(
      items.map((i) => ({
        id: i.id,
        userId: i.userId ?? undefined,
        householdId: i.householdId ?? undefined,
        kind: i.kind,
        key: i.key,
        summarySv: i.summarySv,
        value: i.value,
        origin: i.origin,
        confidence: i.confidence,
        verifiedByUser: i.verifiedByUser,
        paused: i.paused,
        createdAt: i.createdAt.toISOString(),
        updatedAt: i.updatedAt.toISOString(),
        lastUsedAt: i.lastUsedAt?.toISOString(),
        expiresAt: i.expiresAt?.toISOString(),
      })),
      await userLanguageTag(app.db, req.userId),
    );
    return overview;
  });

  app.patch("/v1/me/memory/:id", auth, async (req) => {
    const { id } = parse(idParamSchema, req.params);
    const input = parse(updateMemoryItemInputSchema, req.body);
    const item = await getOwnedMemory(app, id, req.userId);

    const updates: Record<string, unknown> = { updatedAt: new Date() };
    if (input.summarySv != null) updates.summarySv = input.summarySv;
    if (input.value !== undefined) updates.value = input.value;
    if (input.paused != null) updates.paused = input.paused;
    if (input.verified != null || input.summarySv != null || input.value !== undefined) {
      // Användarkorrigering gör posten verifierad och användarägd (spec §30).
      updates.verifiedByUser = true;
      updates.origin = "user_stated";
      updates.confidence = 1;
    }

    const [row] = await app.db
      .update(schema.memoryItems)
      .set(updates)
      .where(eq(schema.memoryItems.id, item.id))
      .returning();

    await emitEvent(app.db, {
      type: "MEMORY_UPDATED",
      payload: { memoryItemId: id, kind: item.kind, origin: "user_stated" },
      userId: req.userId,
      correlationId: req.correlationId,
    });
    return row;
  });

  app.delete("/v1/me/memory/:id", auth, async (req) => {
    const { id } = parse(idParamSchema, req.params);
    const item = await getOwnedMemory(app, id, req.userId);
    await app.db.delete(schema.memoryItems).where(eq(schema.memoryItems.id, item.id));
    await audit(app.db, {
      actorUserId: req.userId,
      action: "memory.deleted",
      targetType: "memory_item",
      targetId: id,
    });
    return { ok: true };
  });

  /** Radera ALLT personligt minne (spec §32: "radera"). */
  app.delete("/v1/me/memory", auth, async (req) => {
    await app.db.delete(schema.memoryItems).where(eq(schema.memoryItems.userId, req.userId));
    await app.db.delete(schema.tasteSignals).where(eq(schema.tasteSignals.userId, req.userId));
    await audit(app.db, { actorUserId: req.userId, action: "memory.deleted_all" });
    return { ok: true, message: "Allt personligt minne är raderat." };
  });

  /** Pausa allt minne (spec §32: "pausa"). */
  app.post("/v1/me/memory/pause-all", auth, async (req) => {
    const body = (req.body ?? {}) as { paused?: boolean };
    const paused = body.paused ?? true;
    await app.db
      .update(schema.memoryItems)
      .set({ paused, updatedAt: new Date() })
      .where(eq(schema.memoryItems.userId, req.userId));
    await audit(app.db, {
      actorUserId: req.userId,
      action: paused ? "memory.paused_all" : "memory.resumed_all",
    });
    return { ok: true, paused };
  });
}

async function getOwnedMemory(app: FastifyInstance, id: string, userId: string) {
  const [item] = await app.db
    .select()
    .from(schema.memoryItems)
    .where(eq(schema.memoryItems.id, id))
    .limit(1);
  if (!item) throw errors.notFound("Minnesposten finns inte.");
  if (item.userId && item.userId !== userId) throw errors.forbidden();
  if (!item.userId && item.householdId) {
    const { requireMembership } = await import("../lib/helpers.js");
    await requireMembership(app.db, item.householdId, userId);
  }
  return item;
}
