import type { FieldSpec, DataRow, RecordSpec } from "@/types/spec";

/** Format a field value using spec metadata or heuristic fallback. */
export function formatFieldValue(key: string, value: unknown, fieldMeta?: FieldSpec): string | null {
  if (value == null || value === "") return null;

  // Spec-driven formatting
  if (fieldMeta?.format === "currency") {
    const num = typeof value === "number" ? value : parseFloat(String(value));
    if (!isNaN(num)) {
      const sym = fieldMeta.symbol || "$";
      return sym + num.toLocaleString(undefined, { minimumFractionDigits: num % 1 === 0 ? 0 : 2, maximumFractionDigits: 2 });
    }
  }
  if (fieldMeta?.format === "percent") {
    const num = typeof value === "number" ? value : parseFloat(String(value));
    if (!isNaN(num)) return Math.round(num * (num <= 1 && num >= 0 ? 100 : 1)) + "%";
  }
  if (fieldMeta?.format === "rating") {
    const num = typeof value === "number" ? value : parseFloat(String(value));
    if (!isNaN(num)) {
      const max = fieldMeta.max || 5;
      const full = Math.floor(Math.min(Math.max(num, 0), max));
      return "★".repeat(full) + "☆".repeat(max - full);
    }
  }

  // Heuristic fallback by field name
  const k = key.toLowerCase();
  if (typeof value === "number" || (typeof value === "string" && !isNaN(parseFloat(value)) && isFinite(Number(value)))) {
    const num = typeof value === "number" ? value : parseFloat(value);
    if (/amount|price|revenue|cost|salary|budget|income|expense|fee|payment/.test(k))
      return "$" + num.toLocaleString(undefined, { minimumFractionDigits: num % 1 === 0 ? 0 : 2, maximumFractionDigits: 2 });
    if (/rate|percent|completion|progress/.test(k))
      return Math.round(num * (num <= 1 && num >= 0 ? 100 : 1)) + "%";
    if (/rating|score|stars/.test(k)) {
      const full = Math.floor(Math.min(Math.max(num, 0), 5));
      return "★".repeat(full) + "☆".repeat(5 - full);
    }
  }
  return null;
}

export function formatNum(n: unknown): string {
  return typeof n === "number" ? n.toLocaleString(undefined, { maximumFractionDigits: 2 }) : String(n ?? "—");
}

export function isImageUrl(val: unknown): boolean {
  if (typeof val !== "string") return false;
  return /\.(jpg|jpeg|png|gif|webp|svg)(\?.*)?$/i.test(val) || val.startsWith("data:image/");
}

/** Resolve a foreign key field to a display name. */
export function resolveFK(
  key: string,
  val: unknown,
  rec: RecordSpec | undefined,
  allRecords: RecordSpec[],
  allData: Record<string, DataRow[]>,
): { name: string; table: string; id: string } | null {
  if (!key.endsWith("_id") || !val || !rec) return null;
  const baseField = key.replace("_id", "");
  const fkMeta = rec.fields[baseField];
  if (!fkMeta?.link) return null;
  const linkedRec = allRecords.find((r) => r.table === fkMeta.link);
  const linked = (allData[fkMeta.link!] || []).find((r) => String(r.id) === String(val));
  if (!linked) return null;
  const displayField =
    linkedRec?.display ||
    Object.keys(linked).find(
      (k) => k !== "id" && k !== "created_at" && k !== "updated_at" && !k.endsWith("_id") && typeof linked[k] === "string" && linked[k],
    );
  return { name: displayField ? String(linked[displayField]) : String(val), table: fkMeta.link!, id: String(linked.id) };
}

/** Get the image field value from a row if one exists. */
export function getImageField(row: DataRow, rec?: RecordSpec): string | null {
  if (!rec) return null;
  for (const [fn, fm] of Object.entries(rec.fields)) {
    if ((fm.type === "image" || isImageUrl(row[fn])) && row[fn]) return String(row[fn]);
  }
  return null;
}
