import type { MutationCtx } from "../_generated/server";
import type { Id } from "../_generated/dataModel";
import { audit } from "./audit";
import { notify } from "./notify";
import { nextCode } from "./seq";
import { getSettings, type AppSettings } from "./settings";
import type { ActorLite } from "./access";
import { fmtMoney } from "../../src/lib/format";

/**
 * Commission engine — one commission per reservation for its creator when the
 * configured trigger fires, only for non-admin creators. Rows are never
 * deleted; cancellations are status transitions with history.
 */
export async function evaluateCommission(ctx: MutationCtx, reservationId: Id<"reservations">, event: "RESERVATION_CONFIRMED" | "CHECK_IN", actor: ActorLite) {
  const settings = await getSettings(ctx);
  if (settings.commissionTrigger !== event || settings.commissionAmount <= 0) return null;
  const r = await ctx.db.get(reservationId);
  if (!r) return null;
  const creator = await ctx.db.get(r.createdById);
  const role = creator?.roleId ? await ctx.db.get(creator.roleId) : null;
  if (!creator || role?.key === "ADMIN") return null;
  const existing = (await ctx.db.query("commissions").withIndex("by_reservation", (q) => q.eq("reservationId", reservationId)).collect()).find((c) => !["CANCELLED", "REVERSED"].includes(c.status));
  if (existing) return existing;
  const code = await nextCode(ctx, "commission");
  const id = await ctx.db.insert("commissions", { code, workerId: r.createdById, reservationId, amount: settings.commissionAmount, triggerEvent: event, status: "PENDING", history: [{ from: "—", to: "PENDING", by: actor?.fullName ?? "System", at: Date.now() }], createdAt: Date.now() });
  await audit(ctx, actor, { action: "COMMISSION_CREATED", module: "commissions", entityType: "commission", entityId: id, entityLabel: code, newValue: { worker: creator.fullName, reservation: r.code, amount: settings.commissionAmount, trigger: event }, reservationId });
  await notify(ctx, { type: "COMMISSION_CREATED", title: "Commission earned", body: `${fmtMoney(settings.commissionAmount, settings.currency)} commission created for ${r.code} (pending approval).`, href: "/my-commission", targetUserIds: [r.createdById], actorId: null });
  return ctx.db.get(id);
}

export async function cancelCommissionsFor(ctx: MutationCtx, reservationId: Id<"reservations">, reason: string, settings: AppSettings, actor: ActorLite) {
  if (settings.commissionOnCancel === "KEEP") return;
  const rows = await ctx.db.query("commissions").withIndex("by_reservation", (q) => q.eq("reservationId", reservationId)).collect();
  for (const c of rows) {
    if (c.status === "PENDING" || c.status === "APPROVED") {
      await ctx.db.patch(c._id, { status: "CANCELLED", adminNotes: reason, history: [...c.history, { from: c.status, to: "CANCELLED", by: actor?.fullName ?? "System", at: Date.now(), note: reason }] });
      await audit(ctx, actor, { action: "COMMISSION_CHANGED", module: "commissions", entityType: "commission", entityId: c._id, entityLabel: c.code, previousValue: c.status, newValue: "CANCELLED", reason, reservationId });
    } else if (c.status === "PAID") {
      await ctx.db.patch(c._id, { status: "REVERSED", adminNotes: `${reason} — paid commission reversed`, history: [...c.history, { from: "PAID", to: "REVERSED", by: actor?.fullName ?? "System", at: Date.now(), note: reason }] });
      await audit(ctx, actor, { action: "COMMISSION_CHANGED", module: "commissions", entityType: "commission", entityId: c._id, entityLabel: c.code, previousValue: "PAID", newValue: "REVERSED", reason, reservationId });
    }
  }
}
