import { Router, type IRouter } from "express";
import { eq } from "drizzle-orm";
import { db } from "@workspace/db";
import { appSettingsTable, auditLogsTable } from "@workspace/db";
import { requireAdmin } from "../middlewares/auth";
import { UpdateAppSettingsBody } from "@workspace/api-zod";

const router: IRouter = Router();

async function ensureSettingsRow() {
  await db
    .insert(appSettingsTable)
    .values({ id: 1 })
    .onConflictDoNothing({ target: appSettingsTable.id });
}

async function readSettings() {
  await ensureSettingsRow();
  const [row] = await db.select().from(appSettingsTable).where(eq(appSettingsTable.id, 1));
  return row;
}

router.get("/settings", async (_req, res): Promise<void> => {
  res.json(await readSettings());
});

router.patch("/settings", requireAdmin, async (req, res): Promise<void> => {
  const parsed = UpdateAppSettingsBody.safeParse(req.body);
  if (!parsed.success) {
    res.status(400).json({ error: parsed.error.message });
    return;
  }
  await ensureSettingsRow();
  const [previous] = await db
    .select()
    .from(appSettingsTable)
    .where(eq(appSettingsTable.id, 1));
  const [updated] = await db
    .update(appSettingsTable)
    .set(parsed.data)
    .where(eq(appSettingsTable.id, 1))
    .returning();

  if (previous) {
    const changes: Record<string, { from: unknown; to: unknown }> = {};
    for (const [key, value] of Object.entries(parsed.data)) {
      const prevValue = (previous as Record<string, unknown>)[key];
      if (prevValue !== value) {
        changes[key] = { from: prevValue ?? null, to: value ?? null };
      }
    }
    if (Object.keys(changes).length > 0) {
      await db.insert(auditLogsTable).values({
        actorUserId: req.session.userId ?? null,
        action: "settings.update",
        targetType: "settings",
        targetId: 1,
        metadata: { changes },
      });
    }
  }

  res.json(updated);
});

export default router;
