import { supabase } from "@/integrations/supabase/client";
import { accounting } from "@/lib/accountingClient";

/**
 * Shared data access for the owner-ledger-based accounting reports
 * (AR Aging by property, Pre-Paid Homeowners). The accounting dashboard is
 * keyed by company; the owner ledger lives in the public schema keyed by
 * association — companies.association_id bridges the two.
 */

export type OwnerLedgerEntry = {
  unit_id: string | null;
  owner_id: string | null;
  date: string;
  transaction_type: string | null;
  debit: number;
  credit: number;
};

export type UnitInfo = {
  id: string;
  unit_number: string | null;
  address: string | null;
  account_number: string | null;
};

export type OwnerInfo = {
  id: string;
  first_name: string | null;
  last_name: string | null;
  unit_id: string | null;
};

export async function fetchAssociationId(companyId: string): Promise<string | null> {
  const { data } = await accounting
    .from("companies")
    .select("association_id")
    .eq("id", companyId)
    .maybeSingle();
  return (data as any)?.association_id ?? null;
}

/** All owner-ledger entries for an association up to (and including) asOf, paged past the 1000-row cap. */
export async function fetchOwnerLedger(associationId: string, asOf: string): Promise<OwnerLedgerEntry[]> {
  const PAGE = 1000;
  const out: OwnerLedgerEntry[] = [];
  for (let offset = 0; ; offset += PAGE) {
    const { data, error } = await supabase
      .from("owner_ledger_entries")
      .select("unit_id, owner_id, date, transaction_type, debit, credit")
      .eq("association_id", associationId)
      .lte("date", asOf)
      .order("id", { ascending: true })
      .range(offset, offset + PAGE - 1);
    if (error) throw error;
    const rows = (data ?? []) as any[];
    for (const r of rows) {
      out.push({
        unit_id: r.unit_id ?? null,
        owner_id: r.owner_id ?? null,
        date: String(r.date ?? "").slice(0, 10),
        transaction_type: r.transaction_type ?? null,
        debit: Number(r.debit || 0),
        credit: Number(r.credit || 0),
      });
    }
    if (rows.length < PAGE) break;
  }
  return out;
}

export async function fetchUnitsAndOwners(associationId: string): Promise<{ units: UnitInfo[]; owners: OwnerInfo[] }> {
  const [unitsRes, ownersRes] = await Promise.all([
    supabase.from("units").select("id, unit_number, address, account_number").eq("association_id", associationId),
    supabase.from("owners").select("id, first_name, last_name, unit_id").eq("association_id", associationId),
  ]);
  return {
    units: (unitsRes.data ?? []) as UnitInfo[],
    owners: (ownersRes.data ?? []) as OwnerInfo[],
  };
}

/** Buildium-style label for a unit row: "account# - address unit# - Owner last name". */
export function unitLabel(unit: UnitInfo | undefined, ownerLastName: string | null): string {
  const parts: string[] = [];
  if (unit?.account_number) parts.push(unit.account_number);
  const addr = [unit?.address, unit?.unit_number && !unit?.address?.includes(unit.unit_number) ? unit.unit_number : null]
    .filter(Boolean)
    .join(" ");
  if (addr) parts.push(addr);
  else if (unit?.unit_number) parts.push(`Unit ${unit.unit_number}`);
  if (ownerLastName) parts.push(ownerLastName);
  return parts.join(" - ") || "Unknown property";
}

const CHARGE_TYPE_LABELS: Record<string, string> = {
  assessment: "Assessments",
  special_assessment: "Special Assessments",
  interest: "Interest",
  late_fee: "Late Fees",
  admin_fee: "Admin Fees",
  legal_fee: "Legal Fees",
  violation: "Violation Fines",
  bank_fee: "Bank Fees",
  prepayment: "Prepayments",
  charge: "Charges",
};

export function chargeTypeLabel(t: string | null | undefined): string {
  const key = String(t || "charge").toLowerCase();
  if (CHARGE_TYPE_LABELS[key]) return CHARGE_TYPE_LABELS[key];
  return key.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
}

/** Always two decimals, thousands-separated, negatives in parentheses. */
export function num(n: number): string {
  const v = Math.round((n + Number.EPSILON) * 100) / 100 || 0;
  const abs = Math.abs(v).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  return v < 0 ? `(${abs})` : abs;
}

export function money(n: number): string {
  const v = Math.round((n + Number.EPSILON) * 100) / 100 || 0;
  const abs = Math.abs(v).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  return v < 0 ? `($${abs})` : `$${abs}`;
}
