import { accounting } from "@/lib/accountingClient";

// Tables that reference a homeowner via customer_id — reassigned to the survivor on merge
const CUSTOMER_FK_TABLES = ["estimates", "invoices", "payments_received", "transactions", "work_orders"] as const;

// Fields copied onto the survivor from a duplicate when the survivor's value is blank
const FILLABLE_FIELDS = [
  "email", "phone", "mailing_address", "lot_number", "unit_number",
  "account_number", "unit_id", "move_in_date", "billing_address",
] as const;

function addrKey(a: string | null | undefined): string {
  return (a ?? "").trim().toLowerCase().replace(/\s+/g, " ");
}

/**
 * Merge homeowners that share the same property address.
 * The earliest-created record survives; duplicates' invoices/ledger are
 * reassigned to it, balances are summed, blank fields are backfilled, and the
 * duplicates are deleted. Idempotent — safe to run repeatedly.
 *
 * Ported from the original TanStack Start server function to a client-side
 * helper scoped to the `accounting` schema (RLS enforces access).
 */
export async function mergeHomeownersByAddress(companyId: string): Promise<{ mergedGroups: number; mergedRecords: number }> {
  const { data: customers, error } = await accounting
    .from("customers")
    .select(
      "id, name, email, phone, property_address, mailing_address, lot_number, unit_number, account_number, unit_id, move_in_date, billing_address, balance, created_at"
    )
    .eq("company_id", companyId)
    .order("created_at", { ascending: true });
  if (error) throw new Error(error.message);

  // Group by normalized property address (skip blanks — never merge on empty)
  const groups = new Map<string, any[]>();
  for (const c of customers ?? []) {
    const key = addrKey(c.property_address);
    if (!key) continue;
    const g = groups.get(key);
    if (g) g.push(c);
    else groups.set(key, [c]);
  }

  let mergedGroups = 0;
  let mergedRecords = 0;

  for (const group of groups.values()) {
    if (group.length < 2) continue;
    mergedGroups++;

    const survivor = group[0]; // earliest created_at
    const dups = group.slice(1);
    const dupIds = dups.map((d) => d.id);

    // 1. Reassign every reference from the duplicates to the survivor
    for (const tbl of CUSTOMER_FK_TABLES) {
      const { error: upErr } = await accounting
        .from(tbl)
        .update({ customer_id: survivor.id })
        .in("customer_id", dupIds);
      if (upErr) throw new Error(`Reassigning ${tbl}: ${upErr.message}`);
    }

    // 2. Delete duplicates (after references are moved off them)
    const { error: delErr } = await accounting.from("customers").delete().in("id", dupIds);
    if (delErr) throw new Error(`Deleting duplicates: ${delErr.message}`);

    // 3. Backfill blank survivor fields + sum balances across the whole group
    const patch: Record<string, any> = {
      balance: group.reduce((s, c) => s + Number(c.balance ?? 0), 0),
    };
    for (const f of FILLABLE_FIELDS) {
      if (!survivor[f]) {
        const donor = dups.find((d) => d[f]);
        if (donor) patch[f] = donor[f];
      }
    }
    const { error: patchErr } = await accounting.from("customers").update(patch as any).eq("id", survivor.id);
    if (patchErr) throw new Error(`Updating survivor: ${patchErr.message}`);

    mergedRecords += dups.length;
  }

  return { mergedGroups, mergedRecords };
}
