// supabase-client.jsx — Supabase auth + opportunity_analyses + acquisitions CRUD
window.NA = window.NA || {};
const _cfg = window.NA_CONFIG || {};

function createSupabaseClient() {
  if (!window.supabase || !_cfg.supabaseUrl || !_cfg.supabaseAnonKey) return null;
  if (window.NA._sb) return window.NA._sb;
  window.NA._sb = window.supabase.createClient(_cfg.supabaseUrl, _cfg.supabaseAnonKey);
  return window.NA._sb;
}

function computeAnalysisMetrics(input) {
  const extras = input.extras || {};
  const sumExtras = Object.values(extras).reduce((s, n) => s + (Number(n) || 0), 0);
  const parcelsRem = Math.max(0, Number(input.parcelas_total ?? input.parcelasTot ?? 0) - Number(input.parcelas_pagas ?? input.parcelasPagas ?? 0));
  const valParcela = Number(input.val_parcela ?? input.valParcela ?? 0);
  const totalQuit = parcelsRem * valParcela;
  const atrasoPenalty = Number(input.parcelas_atraso ?? input.parcelasAtraso ?? 0) * valParcela * 0.1;
  const fipe = Number(input.fipe || 0);
  const margin = Number(input.margin ?? 50);
  const venda = fipe * (1 - margin / 100);
  const inv = Math.max(0,
    Number(input.val_cliente ?? input.valCliente ?? 0) +
    sumExtras + totalQuit + atrasoPenalty -
    Number(input.pago_cliente ?? input.pagoCliente ?? 0)
  );
  const lucro = venda - inv;
  const roi = inv > 0 ? (lucro / inv) * 100 : 0;
  const verdict = lucro >= 10000 && roi >= 20 ? "excellent"
    : lucro >= 5000 && roi >= 10 ? "good"
    : lucro > 0 ? "tight"
    : lucro >= -2000 ? "marginal"
    : "loss";
  return { sumExtras, totalQuit, atrasoPenalty, venda, investimento: inv, lucro, roi, verdict };
}

function rowToForm(row) {
  if (!row) return null;
  return {
    id: row.id,
    vehType: row.veh_type || "car",
    plate: row.plate || "",
    brand: row.brand || "",
    model: row.model || "",
    year: row.year || "",
    color: row.color || "",
    chassi: row.chassi || "",
    bank: row.bank || "",
    valParcela: Number(row.val_parcela || 0),
    parcelasTot: Number(row.parcelas_total || 0),
    parcelasPagas: Number(row.parcelas_pagas || 0),
    parcelasAtraso: Number(row.parcelas_atraso || 0),
    valCliente: Number(row.val_cliente || 0),
    pagoCliente: Number(row.pago_cliente || 0),
    extras: row.extras || {},
    fipe: Number(row.fipe || 0),
    fipeSource: row.fipe_source || "manual",
    margin: Number(row.margin ?? 50),
    notes: row.notes || "",
    status: row.status || "draft",
    apiPayload: row.api_payload || null,
    sellerName: row.seller_name || "",
    sellerPhone: row.seller_phone || "",
    sellerCpf: row.seller_cpf || "",
    sellerEmail: row.seller_email || "",
    statusChangedAt: row.status_changed_at || null,
  };
}

function formToRow(form, userId) {
  const m = computeAnalysisMetrics(form);
  return {
    id: form.id || undefined,
    user_id: userId,
    plate: form.plate || null,
    veh_type: form.vehType || "car",
    brand: form.brand || null,
    model: form.model || null,
    year: form.year ? String(form.year) : null,
    color: form.color || null,
    chassi: form.chassi || null,
    bank: form.bank || null,
    val_parcela: Number(form.valParcela || 0),
    parcelas_total: Number(form.parcelasTot || 0),
    parcelas_pagas: Number(form.parcelasPagas || 0),
    parcelas_atraso: Number(form.parcelasAtraso || 0),
    val_cliente: Number(form.valCliente || 0),
    pago_cliente: Number(form.pagoCliente || 0),
    extras: form.extras || {},
    margin: Number(form.margin ?? 50),
    fipe: Number(form.fipe || 0),
    fipe_source: form.fipeSource || "manual",
    total_quit: m.totalQuit,
    venda: m.venda,
    investimento: m.investimento,
    lucro: m.lucro,
    roi: m.roi,
    verdict: m.verdict,
    status: form.status || "draft",
    notes: form.notes || null,
    api_payload: form.apiPayload || null,
    seller_name: form.sellerName || null,
    seller_phone: form.sellerPhone || null,
    seller_cpf: form.sellerCpf || null,
    seller_email: form.sellerEmail || null,
    status_changed_at: form.statusChangedAt || null,
  };
}

function rowToLegacyListItem(row) {
  return {
    id: row.id,
    plate: row.plate || "—",
    brand: row.brand || row.veh_type || "—",
    model: row.model || row.notes || "—",
    year: row.year || "—",
    bank: row.bank || "—",
    purchasePrice: Number(row.total_quit || 0),
    clientValue: Number(row.val_cliente || 0),
    fipeMax: Number(row.fipe || 0),
    status: row.status === "draft" ? "pending" : row.status,
    expectedProfit: Number(row.lucro || 0),
    savedAt: row.updated_at ? new Date(row.updated_at).toLocaleDateString("pt-BR") : "",
    isAnalysis: true,
    analysisStatus: row.status,
    sellerName: row.seller_name || "",
    sellerPhone: row.seller_phone || "",
    sellerCpf: row.seller_cpf || "",
    sellerEmail: row.seller_email || "",
    statusChangedAt: row.status_changed_at,
    roi: row.roi,
    verdict: row.verdict,
    updatedAt: row.updated_at,
    createdAt: row.created_at,
  };
}

function acquisitionRowToVehicle(row) {
  if (!row) return null;
  const acquiredOn = row.acquired_at
    ? new Date(row.acquired_at).toLocaleDateString("pt-BR")
    : "—";
  return {
    id: row.id,
    plate: row.plate || "SEM-PLACA",
    brand: row.brand || "—",
    model: row.model || "—",
    year: row.year ? (Number(row.year) || row.year) : null,
    owner: row.seller_name || "—",
    bank: row.bank || "—",
    purchasePrice: Number(row.purchase_price || 0),
    settlementValue: Number(row.settlement_value || 0),
    clientValue: Number(row.client_value || 0),
    parcels: {
      total: Number(row.installments_total || 0),
      paid: Number(row.installments_paid || 0),
      overdue: Number(row.installments_overdue || 0),
    },
    installmentValue: Number(row.installment_value || 0),
    acquiredOn,
    status: row.status || "in_process",
    trackerStatus: row.tracker_status || "inactive",
    maintenanceReady: !!row.maintenance_ready,
    trackerOwnerRemoved: !!row.tracker_owner_removed,
    trackerOursInstalled: !!row.tracker_ours_installed,
    maintenance: Array.isArray(row.maintenance) ? row.maintenance : [],
    fipeMin: Number(row.fipe_min || 0),
    fipeMax: Number(row.fipe_max || 0),
    margin: Number(row.margin ?? 50),
    roi: Number(row.roi || 0),
    lucro: Number(row.lucro || 0),
    investimento: Number(row.investimento || 0),
    extras: row.extras && typeof row.extras === "object" ? row.extras : {},
    soldBy: row.sold_by || null,
    salePrice: row.sale_price != null ? Number(row.sale_price) : null,
    soldAt: row.sold_at ? new Date(row.sold_at).toLocaleDateString("pt-BR") : null,
    analysisId: row.analysis_id || null,
    crmDealId: row.crm_deal_id || null,
    chassis: row.chassis || "",
    renavam: row.renavam || "",
    sellerName: row.seller_name || "",
    sellerCpf: row.seller_cpf || "",
    sellerPhone: row.seller_phone || "",
    sellerEmail: row.seller_email || "",
    city: row.city || "",
    state: row.state || "",
    vehType: row.veh_type || "car",
    color: row.color || "",
    notes: row.notes || "",
    createdBy: row.created_by || "",
    nextInstallmentDue: row.next_installment_due || null,
    realInvestimento: Number(row.real_investimento || 0),
    realRoi: Number(row.real_roi || 0),
    isAcquisition: true,
    updatedAt: row.updated_at,
    createdAt: row.created_at,
  };
}

function vehicleToAcquisitionRow(vehicle, userId) {
  const parcels = vehicle.parcels || {};
  const overdue = Number(parcels.overdue || 0);
  let status = vehicle.status || "in_process";
  if (status === "in_process" && overdue > 0) status = "overdue";
  const acquiredAt = vehicle.acquiredOn && vehicle.acquiredOn !== "—"
    ? (() => {
      const p = String(vehicle.acquiredOn).split("/");
      if (p.length === 3) return new Date(`${p[2]}-${p[1]}-${p[0]}`).toISOString();
      return new Date(vehicle.acquiredOn).toISOString();
    })()
    : new Date().toISOString();
  return {
    id: vehicle.id && String(vehicle.id).length > 10 ? vehicle.id : undefined,
    user_id: userId,
    plate: vehicle.plate || null,
    brand: vehicle.brand || null,
    model: vehicle.model || null,
    year: vehicle.year != null ? String(vehicle.year) : null,
    chassis: vehicle.chassis || null,
    renavam: vehicle.renavam || null,
    veh_type: vehicle.vehType || "car",
    color: vehicle.color || null,
    seller_name: vehicle.sellerName || vehicle.owner || null,
    seller_cpf: vehicle.sellerCpf || null,
    seller_phone: vehicle.sellerPhone || null,
    seller_email: vehicle.sellerEmail || null,
    city: vehicle.city || null,
    state: vehicle.state || null,
    purchase_price: Number(vehicle.purchasePrice || 0),
    settlement_value: Number(vehicle.settlementValue || 0),
    client_value: Number(vehicle.clientValue || 0),
    bank: vehicle.bank || null,
    installments_total: Number(parcels.total || 0),
    installments_paid: Number(parcels.paid || 0),
    installments_overdue: overdue,
    installment_value: Number(vehicle.installmentValue || 0),
    status,
    tracker_status: vehicle.trackerStatus || "inactive",
    maintenance_ready: !!vehicle.maintenanceReady,
    tracker_owner_removed: !!vehicle.trackerOwnerRemoved,
    tracker_ours_installed: !!vehicle.trackerOursInstalled,
    maintenance: vehicle.maintenance || [],
    fipe_min: Number(vehicle.fipeMin || 0),
    fipe_max: Number(vehicle.fipeMax || 0),
    margin: Number(vehicle.margin ?? 50),
    roi: Number(vehicle.roi || 0),
    lucro: Number(vehicle.lucro || 0),
    investimento: Number(vehicle.investimento || 0),
    extras: vehicle.extras || {},
    analysis_id: vehicle.analysisId || null,
    crm_deal_id: vehicle.crmDealId || null,
    acquired_at: acquiredAt,
    created_by: vehicle.createdBy || null,
    sold_at: vehicle.soldAt ? new Date(vehicle.soldAt).toISOString() : null,
    sale_price: vehicle.salePrice != null ? Number(vehicle.salePrice) : null,
    sold_by: vehicle.soldBy || null,
    notes: vehicle.notes || null,
    next_installment_due: vehicle.nextInstallmentDue || null,
    real_investimento: Number(vehicle.realInvestimento || 0),
    real_roi: Number(vehicle.realRoi || 0),
  };
}

function analysisToAcquisitionDraft(row) {
  if (!row) return null;
  const form = rowToForm(row);
  const metrics = computeAnalysisMetrics(form);
  const overdue = Number(form.parcelasAtraso || 0);
  const parcelsRem = Math.max(0, Number(form.parcelasTot || 0) - Number(form.parcelasPagas || 0));
  const settlementValue = Number(row.total_quit || metrics.totalQuit || parcelsRem * Number(form.valParcela || 0));
  let status = "in_process";
  if (overdue > 0) status = "overdue";
  else if (parcelsRem > 0) status = "in_settlement";
  return {
    plate: form.plate,
    brand: form.brand,
    model: form.model,
    year: form.year,
    chassis: form.chassi,
    vehType: form.vehType,
    color: form.color,
    sellerName: form.sellerName,
    sellerCpf: form.sellerCpf,
    sellerPhone: form.sellerPhone,
    sellerEmail: form.sellerEmail,
    owner: form.sellerName || form.brand || "—",
    bank: form.bank,
    purchasePrice: Number(form.valCliente || 0),
    settlementValue,
    clientValue: Number(form.valCliente || 0),
    installmentValue: Number(form.valParcela || 0),
    parcels: {
      total: Number(form.parcelasTot || 0),
      paid: Number(form.parcelasPagas || 0),
      overdue,
    },
    fipeMin: Number(form.fipe || 0),
    fipeMax: Number(form.fipe || 0),
    margin: Number(form.margin ?? 50),
    roi: Number(row.roi ?? metrics.roi ?? 0),
    lucro: Number(row.lucro ?? metrics.lucro ?? 0),
    investimento: Number(row.investimento ?? metrics.investimento ?? 0),
    extras: form.extras || {},
    status,
    analysisId: row.id,
    notes: form.notes,
    acquiredOn: new Date().toLocaleDateString("pt-BR"),
    nextInstallmentDue: (() => {
      const d = new Date();
      d.setMonth(d.getMonth() + 1);
      return d.toISOString().slice(0, 10);
    })(),
    createdBy: "analysis",
  };
}

const db = {
  isConfigured() {
    return !!(createSupabaseClient() && _cfg.supabaseUrl && _cfg.supabaseAnonKey);
  },

  async ensureSession() {
    const sb = createSupabaseClient();
    if (!sb) return null;
    const { data: { session } } = await sb.auth.getSession();
    if (session) return session;
    // Login screen is authoritative: only auto-login when explicitly enabled.
    if (!_cfg.autoLogin) return null;
    const email = _cfg.supabaseAuthEmail;
    const password = _cfg.supabaseAuthPassword;
    if (!email || !password) return null;
    if (!window.NA._ensureAuth) {
      window.NA._ensureAuth = sb.auth.signInWithPassword({ email, password })
        .then(({ data, error }) => {
          window.NA._ensureAuth = null;
          if (error) throw error;
          return data.session;
        })
        .catch((err) => {
          window.NA._ensureAuth = null;
          console.warn("NorthAuto Supabase auto-auth:", err.message || err);
          return null;
        });
    }
    return window.NA._ensureAuth;
  },

  async getSession() {
    await this.ensureSession();
    const sb = createSupabaseClient();
    if (!sb) return null;
    const { data } = await sb.auth.getSession();
    return data.session;
  },

  // Reads the current session WITHOUT triggering auto-login (used by the login gate).
  async getExistingSession() {
    const sb = createSupabaseClient();
    if (!sb) return null;
    const { data } = await sb.auth.getSession();
    return data.session || null;
  },

  // Resolves the active role/profile for a logged-in user.
  // Order: user_metadata.role_key -> profiles table -> "admin".
  async resolveUserRole(session) {
    const user = session && session.user;
    const meta = (user && user.user_metadata) || {};
    let roleKey = meta.role_key || null;
    let displayName = meta.display_name || meta.full_name || null;
    if (!roleKey && user && user.id) {
      try {
        const profile = await this.getProfile(user.id);
        if (profile) {
          roleKey = profile.role_key || roleKey;
          displayName = displayName || profile.display_name;
        }
      } catch (e) { /* fall through */ }
    }
    return {
      role_key: roleKey || "admin",
      display_name: displayName || (user && user.email) || "Usuário",
      email: user && user.email || null,
    };
  },

  onAuthStateChange(cb) {
    const sb = createSupabaseClient();
    if (!sb) return { data: { subscription: { unsubscribe: () => {} } } };
    return sb.auth.onAuthStateChange(cb);
  },

  async signIn(email, password) {
    const sb = createSupabaseClient();
    if (!sb) throw new Error("Supabase não configurado");
    const { data, error } = await sb.auth.signInWithPassword({ email, password });
    if (error) throw error;
    return data;
  },

  async signUp(email, password, meta) {
    const sb = createSupabaseClient();
    if (!sb) throw new Error("Supabase não configurado");
    const { data, error } = await sb.auth.signUp({
      email,
      password,
      options: { data: meta || {} },
    });
    if (error) throw error;
    return data;
  },

  async signOut() {
    const sb = createSupabaseClient();
    if (!sb) return;
    await sb.auth.signOut();
  },

  async getProfile(userId) {
    const sb = createSupabaseClient();
    if (!sb || !userId) return null;
    const { data, error } = await sb.from("profiles").select("*").eq("id", userId).maybeSingle();
    if (error) throw error;
    return data;
  },

  async listAnalyses(filters) {
    const sb = createSupabaseClient();
    if (!sb) return [];
    await db.ensureSession();
    let q = sb.from("opportunity_analyses").select("*").order("updated_at", { ascending: false });
    if (filters && filters.status && filters.status !== "all") {
      q = q.eq("status", filters.status);
    }
    if (filters && filters.dateFrom) q = q.gte("created_at", filters.dateFrom);
    if (filters && filters.dateTo) q = q.lte("created_at", filters.dateTo + "T23:59:59");
    const { data, error } = await q;
    if (error) throw error;
    return data || [];
  },

  async getAnalysis(id) {
    const sb = createSupabaseClient();
    if (!sb || !id) return null;
    await db.ensureSession();
    const { data, error } = await sb.from("opportunity_analyses").select("*").eq("id", id).maybeSingle();
    if (error) throw error;
    return data;
  },

  async upsertAnalysis(form) {
    const sb = createSupabaseClient();
    if (!sb) throw new Error("Supabase não configurado");
    await db.ensureSession();
    const { data: { user } } = await sb.auth.getUser();
    if (!user) throw new Error("Não foi possível conectar ao Supabase");
    const row = formToRow(form, user.id);
    const { data, error } = await sb.from("opportunity_analyses").upsert(row).select().single();
    if (error) throw error;
    return data;
  },

  async updateAnalysisStatus(id, status, seller) {
    const row = await db.getAnalysis(id);
    if (!row) throw new Error("Análise não encontrada");
    const form = rowToForm(row);
    form.status = status;
    form.statusChangedAt = new Date().toISOString();
    if (seller) {
      form.sellerName = seller.name || "";
      form.sellerPhone = seller.phone || "";
      form.sellerCpf = seller.cpf || "";
      form.sellerEmail = seller.email || "";
    }
    return db.upsertAnalysis(form);
  },

  async listAcceptedAnalyses() {
    const sb = createSupabaseClient();
    if (!sb) return [];
    await db.ensureSession();
    const { data, error } = await sb.from("opportunity_analyses")
      .select("*")
      .eq("status", "approved")
      .order("status_changed_at", { ascending: false, nullsFirst: false });
    if (error) throw error;
    return data || [];
  },

  async deleteAnalysis(id) {
    const sb = createSupabaseClient();
    if (!sb) throw new Error("Supabase não configurado");
    await db.ensureSession();
    const { error } = await sb.from("opportunity_analyses").delete().eq("id", id);
    if (error) throw error;
  },

  async countPendingAnalyses(statuses) {
    const sb = createSupabaseClient();
    if (!sb) return 0;
    await db.ensureSession();
    const { count, error } = await sb.from("opportunity_analyses")
      .select("*", { count: "exact", head: true })
      .in("status", statuses || ["draft", "pending"]);
    if (error) throw error;
    return count || 0;
  },

  async listAcquisitions(filters) {
    const sb = createSupabaseClient();
    if (!sb) return [];
    await db.ensureSession();
    let q = sb.from("acquisitions").select("*").order("updated_at", { ascending: false });
    if (filters?.status && filters.status !== "all") q = q.eq("status", filters.status);
    if (filters?.analysisId) q = q.eq("analysis_id", filters.analysisId);
    if (filters?.bank && filters.bank !== "all") q = q.eq("bank", filters.bank);
    if (filters?.dateFrom) q = q.gte("acquired_at", filters.dateFrom);
    if (filters?.dateTo) q = q.lte("acquired_at", filters.dateTo + "T23:59:59");
    if (filters?.q) {
      const s = String(filters.q).trim().replace(/[%_,]/g, "");
      if (s) q = q.or(`plate.ilike.%${s}%,brand.ilike.%${s}%,model.ilike.%${s}%,seller_name.ilike.%${s}%,seller_cpf.ilike.%${s}%,chassis.ilike.%${s}%`);
    }
    const { data, error } = await q;
    if (error) throw error;
    return data || [];
  },

  async getAcquisition(id) {
    const sb = createSupabaseClient();
    if (!sb || !id) return null;
    await db.ensureSession();
    const { data, error } = await sb.from("acquisitions").select("*").eq("id", id).maybeSingle();
    if (error) throw error;
    return data;
  },

  async upsertAcquisition(vehicle) {
    const sb = createSupabaseClient();
    if (!sb) throw new Error("Supabase não configurado");
    await db.ensureSession();
    const { data: { user } } = await sb.auth.getUser();
    if (!user) throw new Error("Não foi possível conectar ao Supabase");
    const row = vehicleToAcquisitionRow(vehicle, user.id);
    const { data, error } = await sb.from("acquisitions").upsert(row).select().single();
    if (error) throw error;
    return data;
  },

  async saveAcquisition(vehicle) {
    return db.upsertAcquisition(vehicle);
  },

  async updateAcquisitionStatus(id, status, meta) {
    const row = await db.getAcquisition(id);
    if (!row) throw new Error("Aquisição não encontrada");
    const vehicle = acquisitionRowToVehicle(row);
    if (vehicle.status !== status) {
      const check = await db.validateAcquisitionStatusChange(id, status, vehicle.vehType, meta?.lang);
      if (!check.ok) throw new Error(check.message);
    }
    vehicle.status = status;
    if (meta) {
      if (meta.soldBy != null) vehicle.soldBy = meta.soldBy;
      if (meta.salePrice != null) vehicle.salePrice = Number(meta.salePrice);
      if (meta.soldAt != null) vehicle.soldAt = meta.soldAt;
      if (meta.trackerStatus != null) vehicle.trackerStatus = meta.trackerStatus;
      if (meta.notes != null) vehicle.notes = meta.notes;
      Object.assign(vehicle, meta);
    }
    if (status === "sold" && !vehicle.soldAt) {
      vehicle.soldAt = new Date().toLocaleDateString("pt-BR");
    }
    return db.upsertAcquisition(vehicle);
  },

  async deleteAcquisition(id) {
    const sb = createSupabaseClient();
    if (!sb) throw new Error("Supabase não configurado");
    await db.ensureSession();
    const { error } = await sb.from("acquisitions").delete().eq("id", id);
    if (error) throw error;
  },

  async createAcquisitionFromAnalysis(analysisId, options) {
    const row = await db.getAnalysis(analysisId);
    if (!row) throw new Error("Análise não encontrada");
    if (!["approved", "converted"].includes(row.status)) {
      throw new Error("Somente oportunidades aceitas ou convertidas podem virar aquisição.");
    }
    const existing = await db.listAcquisitions({ analysisId });
    if (existing.length) return existing[0];
    const draft = analysisToAcquisitionDraft(row);
    if (options?.crmDealId) draft.crmDealId = options.crmDealId;
    draft.createdBy = "analysis";
    const saved = await db.upsertAcquisition(draft);
    if (saved?.id) {
      await db.ensureAcquisitionDocumentPlaceholders(saved.id, draft.vehType || "car");
      await db.ensureMaintenancePlaceholders(saved.id, draft.vehType || "car", draft.extras);
    }
    if (row.status !== "converted") {
      await db.updateAnalysisStatus(analysisId, "converted");
    }
    window.dispatchEvent(new Event("na:acquisitions-changed"));
    window.dispatchEvent(new Event("na:analyses-changed"));
    return saved;
  },

  async getAcquisitionByAnalysisId(analysisId) {
    const rows = await db.listAcquisitions({ analysisId });
    return rows[0] || null;
  },

  async countAcquisitionsByStatus(statuses) {
    const sb = createSupabaseClient();
    if (!sb) return 0;
    await db.ensureSession();
    let q = sb.from("acquisitions").select("*", { count: "exact", head: true });
    if (statuses?.length) q = q.in("status", statuses);
    const { count, error } = await q;
    if (error) throw error;
    return count || 0;
  },

  async listAcquisitionDocuments(acquisitionId) {
    const sb = createSupabaseClient();
    if (!sb || !acquisitionId) return [];
    await db.ensureSession();
    const { data, error } = await sb.from("acquisition_documents")
      .select("*")
      .eq("acquisition_id", acquisitionId)
      .order("created_at", { ascending: false });
    if (error) throw error;
    return data || [];
  },

  async listAllAcquisitionDocuments() {
    const sb = createSupabaseClient();
    if (!sb) return [];
    await db.ensureSession();
    const { data, error } = await sb.from("acquisition_documents")
      .select("*")
      .order("updated_at", { ascending: false });
    if (error) throw error;
    return data || [];
  },

  async findAcquisitionDocumentByType(acquisitionId, docType) {
    const sb = createSupabaseClient();
    if (!sb || !acquisitionId || !docType) return null;
    await db.ensureSession();
    const { data, error } = await sb.from("acquisition_documents")
      .select("*")
      .eq("acquisition_id", acquisitionId)
      .eq("doc_type", docType)
      .maybeSingle();
    if (error && error.code !== "PGRST116") throw error;
    return data || null;
  },

  async ensureAcquisitionDocumentPlaceholders(acquisitionId, vehType) {
    const sb = createSupabaseClient();
    if (!sb || !acquisitionId) return [];
    await db.ensureSession();
    const { data: { user } } = await sb.auth.getUser();
    if (!user) return [];
    const cfg = window.NA?.AcquisitionDocs?.getChecklistConfig(vehType || "car");
    if (!cfg) return [];
    const existing = await db.listAcquisitionDocuments(acquisitionId);
    const have = new Set(existing.map(d => d.doc_type));
    const created = [];
    for (const docType of cfg.all) {
      if (have.has(docType)) continue;
      const row = await db.upsertAcquisitionDocument({
        acquisitionId,
        docType,
        status: "pending",
      });
      created.push(row);
    }
    return created;
  },

  async refreshDocumentPreviewUrl(storagePath) {
    const sb = createSupabaseClient();
    if (!sb || !storagePath) return null;
    await db.ensureSession();
    const bucket = _cfg.acquisitionDocsBucket || "acquisition-documents";
    const { data, error } = await sb.storage.from(bucket).createSignedUrl(storagePath, 60 * 60);
    if (error) throw error;
    return data?.signedUrl || null;
  },

  async updateAcquisitionDocumentStatus(docId, status) {
    const sb = createSupabaseClient();
    if (!sb || !docId) throw new Error("Documento inválido");
    await db.ensureSession();
    const { data: existing, error: fetchErr } = await sb.from("acquisition_documents")
      .select("*").eq("id", docId).maybeSingle();
    if (fetchErr) throw fetchErr;
    if (!existing) throw new Error("Documento não encontrado");
    const AD = window.NA?.AcquisitionDocs;
    if (AD && !AD.canAdvanceDocStatus(existing.status, status)) {
      throw new Error("Transição de status de documento inválida.");
    }
    const { data, error } = await sb.from("acquisition_documents")
      .update({ status })
      .eq("id", docId)
      .select()
      .single();
    if (error) throw error;
    return data;
  },

  async validateAcquisitionStatusChange(acquisitionId, newStatus, vehType, lang) {
    const docs = await db.listAcquisitionDocuments(acquisitionId);
    const AD = window.NA?.AcquisitionDocs;
    if (!AD) return { ok: true, missing: [] };
    return AD.checkStatusGate(newStatus, vehType || "car", docs, lang || "pt");
  },

  async upsertAcquisitionDocument(doc) {
    const sb = createSupabaseClient();
    if (!sb) throw new Error("Supabase não configurado");
    await db.ensureSession();
    const { data: { user } } = await sb.auth.getUser();
    if (!user) throw new Error("Não foi possível conectar ao Supabase");
    const row = {
      id: doc.id || undefined,
      acquisition_id: doc.acquisitionId,
      user_id: user.id,
      doc_type: doc.docType,
      storage_path: doc.storagePath || null,
      file_url: doc.fileUrl || null,
      status: doc.status || "pending",
      uploaded_at: doc.uploadedAt || null,
    };
    const { data, error } = await sb.from("acquisition_documents").upsert(row).select().single();
    if (error) throw error;
    return data;
  },

  async uploadAcquisitionDocument(acquisitionId, docType, file) {
    const sb = createSupabaseClient();
    if (!sb) throw new Error("Supabase não configurado");
    if (!acquisitionId || !docType || !file) throw new Error("Aquisição, tipo e arquivo são obrigatórios");
    await db.ensureSession();
    const { data: { user } } = await sb.auth.getUser();
    if (!user) throw new Error("Não foi possível conectar ao Supabase");

    const row = await db.getAcquisition(acquisitionId);
    if (!row) throw new Error("Aquisição não encontrada");

    const bucket = _cfg.acquisitionDocsBucket || "acquisition-documents";
    const ext = (file.name || "file").split(".").pop() || "bin";
    const safeType = String(docType).replace(/[^a-z0-9_-]/gi, "_").toLowerCase();
    const storagePath = `${user.id}/${acquisitionId}/${safeType}_${Date.now()}.${ext}`;

    const { error: uploadError } = await sb.storage.from(bucket).upload(storagePath, file, {
      upsert: true,
      contentType: file.type || undefined,
    });
    if (uploadError) throw uploadError;

    let fileUrl = null;
    const { data: signed, error: signError } = await sb.storage.from(bucket).createSignedUrl(storagePath, 60 * 60 * 24 * 7);
    if (!signError && signed?.signedUrl) fileUrl = signed.signedUrl;
    else {
      const { data: pub } = sb.storage.from(bucket).getPublicUrl(storagePath);
      fileUrl = pub?.publicUrl || null;
    }

    const existing = await db.findAcquisitionDocumentByType(acquisitionId, docType);

    return db.upsertAcquisitionDocument({
      id: existing?.id,
      acquisitionId,
      docType,
      storagePath,
      fileUrl,
      status: "uploaded",
      uploadedAt: new Date().toISOString(),
    });
  },

  async listAcquisitionEvents(acquisitionId) {
    const sb = createSupabaseClient();
    if (!sb || !acquisitionId) return [];
    await db.ensureSession();
    const { data, error } = await sb.from("acquisition_events")
      .select("*")
      .eq("acquisition_id", acquisitionId)
      .order("created_at", { ascending: false });
    if (error) throw error;
    return data || [];
  },

  async listAcquisitionCosts(acquisitionId) {
    const sb = createSupabaseClient();
    if (!sb || !acquisitionId) return [];
    await db.ensureSession();
    const { data, error } = await sb.from("acquisition_costs")
      .select("*")
      .eq("acquisition_id", acquisitionId)
      .order("incurred_at", { ascending: false, nullsFirst: false });
    if (error) throw error;
    return data || [];
  },

  async upsertAcquisitionCost(cost) {
    const sb = createSupabaseClient();
    if (!sb) throw new Error("Supabase não configurado");
    await db.ensureSession();
    const { data: { user } } = await sb.auth.getUser();
    if (!user) throw new Error("Não foi possível conectar ao Supabase");
    const row = {
      id: cost.id || undefined,
      acquisition_id: cost.acquisitionId,
      user_id: user.id,
      cost_type: cost.costType,
      amount: Number(cost.amount || 0),
      description: cost.description || null,
      incurred_at: cost.incurredAt || null,
      cashbook_ref: cost.cashbookRef || null,
    };
    const { data, error } = await sb.from("acquisition_costs").upsert(row).select().single();
    if (error) throw error;

    const acqRow = await db.getAcquisition(cost.acquisitionId);
    if (acqRow && !cost.cashbookRef && !cost.id) {
      const vehicle = acquisitionRowToVehicle(acqRow);
      const AF = window.NA?.AcquisitionFinance;
      const lang = cost.lang || "pt";
      const cat = AF?.costCategoryLabel(cost.costType, lang) || cost.costType;
      const cb = await db.addCashbookEntry({
        type: "out",
        category: cat,
        description: `${cat}${cost.description ? " — " + cost.description : ""} — ${AF?.vehicleLabel(vehicle) || vehicle.plate}`,
        amount: Number(cost.amount || 0),
        acquisitionId: cost.acquisitionId,
        origin: "auto",
        sourceRef: `cost:${data.id}`,
        entryDate: cost.incurredAt || new Date().toISOString().slice(0, 10),
      });
      if (cb?.id) {
        await sb.from("acquisition_costs").update({ cashbook_ref: cb.id }).eq("id", data.id);
      }
    }
    await db.recalculateAcquisitionFinance(cost.acquisitionId);
    window.dispatchEvent(new Event("na:cashbook-changed"));
    return data;
  },

  maintenanceItemRowToItem(row) {
    const AM = window.NA?.AcquisitionMaintenance;
    return AM?.normalizeMaintenanceItem(row) || {
      id: row.id,
      acquisitionId: row.acquisition_id,
      label: row.label,
      category: row.category || "geral",
      done: !!row.done,
      doneAt: row.done_at || null,
      sortOrder: row.sort_order || 0,
      source: row.source || "manual",
    };
  },

  _localMaintMap() {
    const AM = window.NA?.AcquisitionMaintenance;
    return AM?.loadLocalMaintenanceMap?.() || {};
  },

  _saveLocalMaintMap(map) {
    const AM = window.NA?.AcquisitionMaintenance;
    AM?.saveLocalMaintenanceMap?.(map);
  },

  async listMaintenanceItems(acquisitionId) {
    const sb = createSupabaseClient();
    if (!sb) {
      const map = db._localMaintMap();
      return (map[acquisitionId] || []).map(r => db.maintenanceItemRowToItem(r));
    }
    await db.ensureSession();
    try {
      const { data, error } = await sb.from("acquisition_maintenance_items")
        .select("*")
        .eq("acquisition_id", acquisitionId)
        .order("sort_order", { ascending: true })
        .order("created_at", { ascending: true });
      if (error) throw error;
      return (data || []).map(db.maintenanceItemRowToItem);
    } catch (e) {
      console.warn("listMaintenanceItems:", e.message || e);
      return [];
    }
  },

  async listAllMaintenanceItems() {
    const sb = createSupabaseClient();
    if (!sb) {
      const map = db._localMaintMap();
      const out = [];
      Object.entries(map).forEach(([acqId, rows]) => {
        (rows || []).forEach(r => out.push(db.maintenanceItemRowToItem({ ...r, acquisition_id: acqId })));
      });
      return out;
    }
    await db.ensureSession();
    try {
      const { data, error } = await sb.from("acquisition_maintenance_items")
        .select("*")
        .order("acquisition_id")
        .order("sort_order", { ascending: true });
      if (error) throw error;
      return (data || []).map(db.maintenanceItemRowToItem);
    } catch (e) {
      console.warn("listAllMaintenanceItems:", e.message || e);
      return [];
    }
  },

  async upsertMaintenanceItem(item) {
    const sb = createSupabaseClient();
    if (!sb) {
      const map = db._localMaintMap();
      const acqId = item.acquisitionId;
      const list = map[acqId] || [];
      const row = {
        id: item.id || ("mi_" + Date.now() + "_" + Math.random().toString(36).slice(2, 6)),
        acquisition_id: acqId,
        label: item.label,
        category: item.category || "geral",
        done: !!item.done,
        done_at: item.done ? (item.doneAt || new Date().toISOString()) : null,
        sort_order: Number(item.sortOrder ?? list.length),
        source: item.source || "manual",
      };
      const idx = list.findIndex(x => x.id === row.id);
      if (idx >= 0) list[idx] = row;
      else list.push(row);
      map[acqId] = list;
      db._saveLocalMaintMap(map);
      return row;
    }
    await db.ensureSession();
    const { data: { user } } = await sb.auth.getUser();
    if (!user) throw new Error("Não foi possível conectar ao Supabase");
    const row = {
      id: item.id && String(item.id).length > 10 ? item.id : undefined,
      acquisition_id: item.acquisitionId,
      user_id: user.id,
      label: item.label,
      category: item.category || "geral",
      done: !!item.done,
      done_at: item.done ? (item.doneAt || new Date().toISOString()) : null,
      sort_order: Number(item.sortOrder || 0),
      source: item.source || "manual",
    };
    const { data, error } = await sb.from("acquisition_maintenance_items").upsert(row).select().single();
    if (error) throw error;
    return data;
  },

  async toggleMaintenanceItem(itemId, done) {
    const sb = createSupabaseClient();
    if (!sb) {
      const map = db._localMaintMap();
      let found = null;
      Object.keys(map).forEach(acqId => {
        map[acqId] = (map[acqId] || []).map(r => {
          if (r.id === itemId) {
            found = { ...r, done: !!done, done_at: done ? new Date().toISOString() : null };
            return found;
          }
          return r;
        });
      });
      if (!found) throw new Error("Item não encontrado");
      db._saveLocalMaintMap(map);
      return found;
    }
    await db.ensureSession();
    const { data, error } = await sb.from("acquisition_maintenance_items")
      .update({ done: !!done, done_at: done ? new Date().toISOString() : null })
      .eq("id", itemId)
      .select()
      .single();
    if (error) throw error;
    return data;
  },

  async deleteMaintenanceItem(itemId) {
    const sb = createSupabaseClient();
    if (!sb) {
      const map = db._localMaintMap();
      Object.keys(map).forEach(acqId => {
        map[acqId] = (map[acqId] || []).filter(r => r.id !== itemId);
      });
      db._saveLocalMaintMap(map);
      return;
    }
    await db.ensureSession();
    const { error } = await sb.from("acquisition_maintenance_items").delete().eq("id", itemId);
    if (error) throw error;
  },

  async updateMaintenanceFlags(acquisitionId, flags) {
    const row = await db.getAcquisition(acquisitionId);
    const sb = createSupabaseClient();
    if (!row && !sb) {
      const veh = (window.NA.vehicles || []).find(v => v.id === acquisitionId);
      if (!veh) throw new Error("Aquisição não encontrada");
      if (flags.maintenanceReady != null) veh.maintenanceReady = !!flags.maintenanceReady;
      if (flags.trackerOwnerRemoved != null) veh.trackerOwnerRemoved = !!flags.trackerOwnerRemoved;
      if (flags.trackerOursInstalled != null) veh.trackerOursInstalled = !!flags.trackerOursInstalled;
      if (flags.trackerStatus != null) veh.trackerStatus = flags.trackerStatus;
      window.dispatchEvent(new Event("na:acquisitions-changed"));
      return veh;
    }
    if (!row) throw new Error("Aquisição não encontrada");
    const vehicle = acquisitionRowToVehicle(row);
    if (flags.maintenanceReady != null) vehicle.maintenanceReady = !!flags.maintenanceReady;
    if (flags.trackerOwnerRemoved != null) vehicle.trackerOwnerRemoved = !!flags.trackerOwnerRemoved;
    if (flags.trackerOursInstalled != null) vehicle.trackerOursInstalled = !!flags.trackerOursInstalled;
    if (flags.trackerStatus != null) vehicle.trackerStatus = flags.trackerStatus;
    if (flags.trackerOursInstalled && !flags.trackerStatus) vehicle.trackerStatus = "active";
    return db.upsertAcquisition(vehicle);
  },

  async migrateLegacyMaintenance(acquisitionId) {
    const row = await db.getAcquisition(acquisitionId);
    if (!row) return { migrated: 0 };
    const legacy = Array.isArray(row.maintenance) ? row.maintenance : [];
    if (!legacy.length) return { migrated: 0 };
    const existing = await db.listMaintenanceItems(acquisitionId);
    if (existing.length) return { migrated: 0, skipped: true };
    let migrated = 0;
    for (let i = 0; i < legacy.length; i++) {
      const label = typeof legacy[i] === "string" ? legacy[i] : legacy[i]?.label;
      if (!label) continue;
      await db.upsertMaintenanceItem({
        acquisitionId,
        label,
        category: "geral",
        source: "legacy",
        sortOrder: i,
      });
      migrated++;
    }
    return { migrated };
  },

  async ensureMaintenancePlaceholders(acquisitionId, vehType, extras) {
    const AM = window.NA?.AcquisitionMaintenance;
    if (!acquisitionId) return [];
    const existing = await db.listMaintenanceItems(acquisitionId);
    const have = new Set(existing.map(i => i.label.toLowerCase()));
    const created = [];

    const fromExtras = AM?.extrasToMaintenanceItems(extras) || [];
    for (const item of fromExtras) {
      if (have.has(item.label.toLowerCase())) continue;
      const row = await db.upsertMaintenanceItem({
        acquisitionId,
        label: item.label,
        category: item.category,
        source: item.source || "analysis",
        sortOrder: created.length + existing.length,
      });
      created.push(row);
      have.add(item.label.toLowerCase());
    }

    const presets = AM?.MAINTENANCE_PRESETS?.[vehType || "car"] || [];
    for (const preset of presets) {
      if (have.has(preset.label.toLowerCase())) continue;
      const row = await db.upsertMaintenanceItem({
        acquisitionId,
        label: preset.label,
        category: preset.category,
        source: "preset",
        sortOrder: created.length + existing.length,
      });
      created.push(row);
      have.add(preset.label.toLowerCase());
    }
    return created;
  },

  async migrateAllLegacyMaintenance() {
    try {
      if (localStorage.getItem("nau_maint_migrated") === "1") return { migrated: 0 };
    } catch (e) {}
    let rows = [];
    try {
      rows = await db.listAcquisitions();
    } catch (e) {
      return { migrated: 0 };
    }
    let total = 0;
    for (const row of rows) {
      try {
        const res = await db.migrateLegacyMaintenance(row.id);
        total += res.migrated || 0;
      } catch (e) {
        console.warn("migrateLegacyMaintenance", row.id, e.message || e);
      }
    }
    try { localStorage.setItem("nau_maint_migrated", "1"); } catch (e) {}
    return { migrated: total };
  },

  async listCashbookEntries(filters) {
    const sb = createSupabaseClient();
    if (!sb) return [];
    await db.ensureSession();
    let q = sb.from("cashbook_entries").select("*").order("entry_date", { ascending: false });
    if (filters?.acquisitionId) q = q.eq("acquisition_id", filters.acquisitionId);
    const { data, error } = await q;
    if (error) throw error;
    return data || [];
  },

  async addCashbookEntry(entry) {
    const sb = createSupabaseClient();
    if (!sb) throw new Error("Supabase não configurado");
    await db.ensureSession();
    const { data: { user } } = await sb.auth.getUser();
    if (!user) throw new Error("Não foi possível conectar ao Supabase");
    if (entry.sourceRef) {
      const { data: existing } = await sb.from("cashbook_entries")
        .select("*").eq("user_id", user.id).eq("source_ref", entry.sourceRef).maybeSingle();
      if (existing) return existing;
    }
    const type = entry.type || entry.entryType || "out";
    const row = {
      user_id: user.id,
      acquisition_id: entry.acquisitionId || null,
      entry_type: type,
      category: entry.category || "Outros",
      description: entry.description || "",
      amount: Math.abs(Number(entry.amount || 0)),
      entry_date: entry.entryDate || new Date().toISOString().slice(0, 10),
      origin: entry.origin || "manual",
      source_ref: entry.sourceRef || null,
    };
    const { data, error } = await sb.from("cashbook_entries").insert(row).select().single();
    if (error) throw error;
    return data;
  },

  async recalculateAcquisitionFinance(acquisitionId) {
    const sb = createSupabaseClient();
    if (!sb || !acquisitionId) return null;
    await db.ensureSession();
    const row = await db.getAcquisition(acquisitionId);
    if (!row) return null;
    const vehicle = acquisitionRowToVehicle(row);
    const costs = await db.listAcquisitionCosts(acquisitionId);
    const AF = window.NA?.AcquisitionFinance;
    const fin = AF?.computeRealFinance(vehicle, costs) || {};
    vehicle.realInvestimento = fin.realInvest;
    vehicle.realRoi = fin.realRoi;
    await db.upsertAcquisition(vehicle);
    return fin;
  },

  async registerInstallmentPayment(acquisitionId, lang) {
    const row = await db.getAcquisition(acquisitionId);
    if (!row) throw new Error("Aquisição não encontrada");
    const vehicle = acquisitionRowToVehicle(row);
    const paid = Number(vehicle.parcels?.paid || 0);
    const total = Number(vehicle.parcels?.total || 0);
    if (total > 0 && paid >= total) throw new Error(lang === "en" ? "All installments already paid." : "Todas as parcelas já foram pagas.");
    const AF = window.NA?.AcquisitionFinance;
    const amount = AF?.installmentAmount(vehicle) || 0;
    const nextPaid = paid + 1;

    await db.addCashbookEntry({
      type: "out",
      category: lang === "en" ? "Bank settlement" : "Quitação bancária",
      description: `${lang === "en" ? "Installment" : "Parcela"} ${nextPaid}/${total || "—"} — ${AF?.vehicleLabel(vehicle) || vehicle.plate}`,
      amount,
      acquisitionId,
      origin: "auto",
      sourceRef: `installment:${acquisitionId}:${nextPaid}`,
    });

    const next = {
      ...vehicle,
      parcels: {
        ...vehicle.parcels,
        paid: nextPaid,
        overdue: Math.max(0, Number(vehicle.parcels?.overdue || 0) - 1),
      },
      nextInstallmentDue: AF?.advanceDueDate(vehicle, 1) || null,
    };

    if (total > 0 && next.parcels.paid >= total) {
      await db.updateAcquisitionStatus(acquisitionId, "settled", { lang });
    } else {
      if (next.parcels.overdue === 0 && next.status === "overdue") next.status = "in_settlement";
      await db.saveAcquisition(next);
    }
    await db.recalculateAcquisitionFinance(acquisitionId);
    window.dispatchEvent(new Event("na:acquisitions-changed"));
    window.dispatchEvent(new Event("na:cashbook-changed"));
    return next;
  },

  async registerAcquisitionSale(acquisitionId, salePrice, soldBy, lang) {
    const row = await db.getAcquisition(acquisitionId);
    if (!row) throw new Error("Aquisição não encontrada");
    const vehicle = acquisitionRowToVehicle(row);
    const price = Number(salePrice || 0);
    if (price <= 0) throw new Error(lang === "en" ? "Invalid sale value." : "Valor de venda inválido.");
    const AF = window.NA?.AcquisitionFinance;

    await db.addCashbookEntry({
      type: "in",
      category: lang === "en" ? "Vehicle sale" : "Venda de veículo",
      description: `${lang === "en" ? "Sale" : "Venda"} — ${AF?.vehicleLabel(vehicle) || vehicle.plate}`,
      amount: price,
      acquisitionId,
      origin: "auto",
      sourceRef: `sale:${acquisitionId}`,
    });

    await db.updateAcquisitionStatus(acquisitionId, "sold", {
      lang,
      salePrice: price,
      soldBy: soldBy || null,
      soldAt: new Date().toLocaleDateString("pt-BR"),
    });
    await db.recalculateAcquisitionFinance(acquisitionId);
    window.dispatchEvent(new Event("na:acquisitions-changed"));
    window.dispatchEvent(new Event("na:cashbook-changed"));
    return acquisitionRowToVehicle(await db.getAcquisition(acquisitionId));
  },

  async importLocalVehicles() {
    const sb = createSupabaseClient();
    if (!sb) return { imported: 0 };
    await db.ensureSession();
    const { data: { user } } = await sb.auth.getUser();
    if (!user) throw new Error("Não foi possível conectar ao Supabase");

    try {
      if (localStorage.getItem("nau_vehicles_migrated") === "1") {
        return { imported: 0, skipped: true };
      }
    } catch (e) {}

    const mockVehicles = window.NA?.vehiclesMock || [];
    if (!mockVehicles.length) return { imported: 0 };

    const existing = await db.listAcquisitions();
    if (existing.length) {
      try { localStorage.setItem("nau_vehicles_migrated", "1"); } catch (e) {}
      return { imported: 0, skipped: true, reason: "already_has_data" };
    }

    let imported = 0;
    for (const v of mockVehicles) {
      await db.upsertAcquisition({ ...v, id: undefined, createdBy: "import_mock" });
      imported++;
    }
    if (imported) {
      try { localStorage.setItem("nau_vehicles_migrated", "1"); } catch (e) {}
    }
    return { imported };
  },

  async refreshVehicles() {
    if (!db.isConfigured()) return null;
    await db.ensureSession();
    await db.migrateAllLegacyMaintenance();
    const rows = await db.listAcquisitions();
    return rows.map(acquisitionRowToVehicle);
  },

  async refreshMaintenanceItemsMap() {
    const sb = createSupabaseClient();
    if (!sb) {
      const AM = window.NA?.AcquisitionMaintenance;
      const map = AM?.loadLocalMaintenanceMap?.() || {};
      const veh = window.NA.vehicles || window.NA.vehiclesMock || [];
      veh.forEach(v => {
        if (map[v.id]?.length) return;
        const legacy = (v.maintenance || []).filter(x => typeof x === "string" && x);
        if (legacy.length) {
          map[v.id] = legacy.map((label, i) => ({
            id: "legacy_" + v.id + "_" + i,
            acquisition_id: v.id,
            label,
            done: false,
            source: "legacy",
          }));
        }
      });
      AM?.saveLocalMaintenanceMap?.(map);
      const out = {};
      Object.entries(map).forEach(([acqId, rows]) => {
        out[acqId] = (rows || []).map(r => db.maintenanceItemRowToItem({ ...r, acquisition_id: acqId }));
      });
      window.NA.maintenanceItemsByAcq = out;
      return out;
    }
    const items = await db.listAllMaintenanceItems();
    const map = {};
    items.forEach(it => {
      const id = it.acquisitionId;
      if (!map[id]) map[id] = [];
      map[id].push(it);
    });
    if (!items.length) {
      (window.NA.vehicles || []).forEach(v => {
        const legacy = (v.maintenance || []).filter(x => typeof x === "string" && x);
        if (legacy.length && !map[v.id]?.length) {
          map[v.id] = legacy.map((label, i) => db.maintenanceItemRowToItem({
            id: "legacy_" + v.id + "_" + i,
            acquisition_id: v.id,
            label,
            done: false,
            source: "legacy",
          }));
        }
      });
    }
    window.NA.maintenanceItemsByAcq = map;
    return map;
  },

  needsVehicleImport() {
    try { return localStorage.getItem("nau_vehicles_migrated") !== "1"; } catch (e) { return true; }
  },

  acquisitionRowToVehicle,
  vehicleToAcquisitionRow,
  analysisToAcquisitionDraft,

  async lookupPlate(plate) {
    const sb = createSupabaseClient();
    if (!sb) throw new Error("Supabase não configurado");
    const session = await db.ensureSession();
    if (!session) throw new Error("Não foi possível conectar ao Supabase");
    const res = await fetch(_cfg.supabaseUrl + "/functions/v1/lookup-plate", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: "Bearer " + session.access_token,
        apikey: _cfg.supabaseAnonKey,
      },
      body: JSON.stringify({ plate }),
    });
    const body = await res.json().catch(() => ({}));
    if (!res.ok) {
      const msg = body.error || body.message || "Erro na consulta de placa";
      throw new Error(body.hint ? `${msg} — ${body.hint}` : msg);
    }
    return body;
  },

  async importLocalAnalyses() {
    const sb = createSupabaseClient();
    if (!sb) return { imported: 0 };
    await db.ensureSession();
    const { data: { user } } = await sb.auth.getUser();
    if (!user) throw new Error("Não foi possível conectar ao Supabase");
    let local = [];
    try {
      local = JSON.parse(localStorage.getItem("nau_analyses") || "[]");
    } catch (e) { local = []; }
    if (!local.length) return { imported: 0 };
    let imported = 0;
    for (const item of local) {
      const form = {
        plate: item.plate,
        vehType: item.brand || "car",
        bank: item.bank,
        valCliente: item.valCliente,
        fipe: item.fipe,
        notes: item.label,
        status: item.pending ? "pending" : "pending",
        parcelasTot: 0,
        parcelasPagas: 0,
        valParcela: item.totalQuit && item.totalQuit > 0 ? item.totalQuit : 0,
        extras: {},
        margin: 50,
      };
      await db.upsertAnalysis(form);
      imported++;
    }
    if (imported) localStorage.removeItem("nau_analyses");
    return { imported };
  },

  computeAnalysisMetrics,
  rowToForm,
  rowToLegacyListItem,
  analysisRowToCrmCard(row, stageKey) {
    const item = rowToLegacyListItem(row);
    const vehicle = [item.brand, item.model, item.year].filter(x => x && x !== "—").join(" ");
    const client = item.sellerName || vehicle || item.plate || "Análise";
    return {
      id: "a_" + row.id,
      analysisId: row.id,
      kind: "analysis",
      stage: stageKey,
      analysisStatus: row.status,
      client,
      phone: item.sellerPhone || "",
      vehicle: vehicle || "—",
      plate: item.plate || "—",
      value: Number(row.lucro || row.fipe || 0),
      owner: "ops",
      priority: row.verdict === "excellent" || row.verdict === "good" ? "high"
        : row.verdict === "loss" || row.verdict === "marginal" ? "low" : "medium",
      updatedAt: item.savedAt,
      notes: row.notes || "",
      roi: Number(row.roi || 0),
      sellerName: item.sellerName,
      sellerPhone: item.sellerPhone,
      expectedProfit: Number(row.lucro || 0),
      fipeMax: Number(row.fipe || 0),
    };
  },
};

window.NA.db = db;
window.NA.computeAnalysisMetrics = computeAnalysisMetrics;
