import { zValidator } from "@hono/zod-validator";
import { Hono } from "hono";
import { authMiddleware, requireAuth, type AuthVariables } from "../middleware/auth.middleware";
import { tenantMiddleware, requireHousehold, type TenantVariables } from "../middleware/tenant.middleware";
import {
  CreateFixedCostSchema,
  UpdateFixedCostSchema,
  CreateTransferLineItemSchema,
  UpdateTransferLineItemSchema,
  CreateMonthlyTransferSchema,
} from "@haushaltsApp/shared/schemas/fixed-costs.schema";
import {
  getFixedCosts,
  createFixedCost,
  updateFixedCost,
  deleteFixedCost,
  getTransferLineItems,
  createTransferLineItem,
  updateTransferLineItem,
  deleteTransferLineItem,
  getMonthlyTransfers,
  createMonthlyTransfer,
  getSettlementV2,
  getNettoMonth,
} from "../services/fixed-costs.service";

type Variables = AuthVariables & TenantVariables;

export const fixedCostsRoutes = new Hono<{ Variables: Variables }>();
fixedCostsRoutes.use("/*", authMiddleware, requireAuth, tenantMiddleware, requireHousehold);

// ── Fixed Costs ───────────────────────────────────────────────────────────────

fixedCostsRoutes.get("/", async (c) => {
  const householdId = c.get("householdId") as string;
  const data = await getFixedCosts(householdId);
  return c.json({ fixedCosts: data });
});

fixedCostsRoutes.post("/", zValidator("json", CreateFixedCostSchema), async (c) => {
  const householdId = c.get("householdId") as string;
  const input = c.req.valid("json");
  const fixedCost = await createFixedCost(householdId, input);
  return c.json({ fixedCost }, 201);
});

fixedCostsRoutes.patch("/:id", zValidator("json", UpdateFixedCostSchema), async (c) => {
  const householdId = c.get("householdId") as string;
  const { id } = c.req.param();
  const input = c.req.valid("json");
  const fixedCost = await updateFixedCost(id, householdId, input);
  if (!fixedCost) return c.json({ error: "Not found" }, 404);
  return c.json({ fixedCost });
});

fixedCostsRoutes.delete("/:id", async (c) => {
  const householdId = c.get("householdId") as string;
  const { id } = c.req.param();
  const ok = await deleteFixedCost(id, householdId);
  if (!ok) return c.json({ error: "Not found" }, 404);
  return c.json({ success: true });
});

// ── Transfer Line Items ───────────────────────────────────────────────────────

fixedCostsRoutes.get("/line-items", async (c) => {
  const householdId = c.get("householdId") as string;
  const data = await getTransferLineItems(householdId);
  return c.json({ lineItems: data });
});

fixedCostsRoutes.post("/line-items", zValidator("json", CreateTransferLineItemSchema), async (c) => {
  const householdId = c.get("householdId") as string;
  const input = c.req.valid("json");
  const lineItem = await createTransferLineItem(householdId, input);
  return c.json({ lineItem }, 201);
});

fixedCostsRoutes.patch("/line-items/:id", zValidator("json", UpdateTransferLineItemSchema), async (c) => {
  const householdId = c.get("householdId") as string;
  const { id } = c.req.param();
  const input = c.req.valid("json");
  const lineItem = await updateTransferLineItem(id, householdId, input);
  if (!lineItem) return c.json({ error: "Not found" }, 404);
  return c.json({ lineItem });
});

fixedCostsRoutes.delete("/line-items/:id", async (c) => {
  const householdId = c.get("householdId") as string;
  const { id } = c.req.param();
  const ok = await deleteTransferLineItem(id, householdId);
  if (!ok) return c.json({ error: "Not found" }, 404);
  return c.json({ success: true });
});

// ── Monthly Transfers ─────────────────────────────────────────────────────────

fixedCostsRoutes.get("/monthly-transfers/:month", async (c) => {
  const householdId = c.get("householdId") as string;
  const { month } = c.req.param();
  const transfers = await getMonthlyTransfers(householdId, month);
  return c.json({ transfers });
});

fixedCostsRoutes.post("/monthly-transfers", zValidator("json", CreateMonthlyTransferSchema), async (c) => {
  const householdId = c.get("householdId") as string;
  const user = c.get("user") as { id: string };
  const input = c.req.valid("json");
  const transfer = await createMonthlyTransfer(householdId, user.id, input);
  return c.json({ transfer }, 201);
});

// ── Settlement V2 ─────────────────────────────────────────────────────────────

fixedCostsRoutes.get("/settlement/:month", async (c) => {
  const householdId = c.get("householdId") as string;
  const user = c.get("user") as { id: string };
  const { month } = c.req.param();
  const settlement = await getSettlementV2(householdId, user.id, month);
  return c.json({ settlement });
});

// ── Netto Month ───────────────────────────────────────────────────────────────

fixedCostsRoutes.get("/netto/:month", async (c) => {
  const householdId = c.get("householdId") as string;
  const user = c.get("user") as { id: string };
  const { month } = c.req.param();
  const netto = await getNettoMonth(householdId, user.id, month);
  return c.json({ netto });
});
