"use server";

import { db } from "@/db";
import { transactions } from "@/db/schema";
import { requireHousehold } from "@/lib/session";
import { eq, and } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import { z } from "zod";

const TxSchema = z.object({
  bankAccountId: z.string().min(1),
  date: z.string().min(8),
  description: z.string().min(1).max(200),
  amount: z.coerce.number(),
  categoryId: z.string().optional().nullable().or(z.literal("")),
  status: z.enum(["posted", "projected"]).default("posted"),
});

export async function addTransactionAction(formData: FormData) {
  const { householdId, user } = await requireHousehold();
  const parsed = TxSchema.parse({
    bankAccountId: formData.get("bankAccountId"),
    date: formData.get("date"),
    description: formData.get("description"),
    amount: formData.get("amount"),
    categoryId: formData.get("categoryId") || null,
    status: formData.get("status") || "posted",
  });
  await db.insert(transactions).values({
    householdId,
    bankAccountId: parsed.bankAccountId,
    categoryId: parsed.categoryId || null,
    date: parsed.date,
    amountMinor: Math.round(parsed.amount * 100),
    description: parsed.description,
    status: parsed.status,
    source: "manual",
    createdByUserId: user.id,
  });
  revalidatePath("/ledger");
  revalidatePath("/");
}

export async function markPostedAction(formData: FormData) {
  const { householdId, user } = await requireHousehold();
  const id = String(formData.get("id"));
  const date = String(formData.get("date"));
  const recurringRuleId = formData.get("recurringRuleId")?.toString() || null;
  const bankAccountId = String(formData.get("bankAccountId"));
  const description = String(formData.get("description"));
  const amount = Number(formData.get("amount") ?? 0);
  const categoryId = formData.get("categoryId")?.toString() || null;

  if (id.startsWith("proj_")) {
    await db.insert(transactions).values({
      householdId,
      bankAccountId,
      categoryId,
      date,
      amountMinor: Math.round(amount * 100),
      description,
      status: "posted",
      source: "recurring",
      recurringRuleId,
      createdByUserId: user.id,
    });
  } else {
    await db
      .update(transactions)
      .set({ status: "posted" })
      .where(and(eq(transactions.id, id), eq(transactions.householdId, householdId)));
  }
  revalidatePath("/ledger");
  revalidatePath("/");
}

export async function deleteTransactionAction(formData: FormData) {
  const { householdId } = await requireHousehold();
  const id = String(formData.get("id"));
  if (id.startsWith("proj_")) return; // can't delete a projection without cancelling the rule
  await db
    .delete(transactions)
    .where(and(eq(transactions.id, id), eq(transactions.householdId, householdId)));
  revalidatePath("/ledger");
  revalidatePath("/");
}
