import type { SupabaseClient, User } from "@supabase/supabase-js";
import { canCompany, getCompanyContext } from "@/lib/company-context";
import { ApiV1Error } from "@/lib/api-v1/errors";

export type CustomerSummary = {
  id: string;
  name: string;
  company_name: string | null;
  type: string | null;
  email: string | null;
  phone: string | null;
  whatsapp: string | null;
  notes: string | null;
  tags: string[];
  active: boolean;
  created_at: string | null;
  updated_at: string | null;
};

type CustomerRow = {
  id: string;
  name: string | null;
  company_name: string | null;
  type: string | null;
  email: string | null;
  phone: string | null;
  whatsapp: string | null;
  notes: string | null;
  tags: string[] | null;
  active: boolean | null;
  created_at: string | null;
  updated_at: string | null;
  is_deleted?: boolean | null;
  is_system_placeholder?: boolean | null;
};

export function normalizePhoneDigits(input: string) {
  const digits = String(input || "").replace(/\D/g, "");
  if (!digits) return "";
  if (digits.startsWith("55")) return digits;
  if (digits.length === 10 || digits.length === 11) return `55${digits}`;
  return digits;
}

function buildPhoneCandidates(phone: string) {
  const normalized = normalizePhoneDigits(phone);
  if (!normalized) return [];

  const candidates = new Set<string>([normalized]);
  if (normalized.startsWith("55")) {
    candidates.add(normalized.slice(2));
  } else if (normalized.length === 10 || normalized.length === 11) {
    candidates.add(`55${normalized}`);
  }

  return Array.from(candidates).filter(Boolean);
}

function isQuickPlaceholderClient(row: CustomerRow) {
  if (row.is_system_placeholder) return true;
  const name = String(row.name || "").trim().toLowerCase();
  const company = String(row.company_name || "").trim().toLowerCase();
  return name === "cliente pendente" && company === "orcamento rapido" && row.active === false;
}

function mapCustomer(row: CustomerRow): CustomerSummary {
  return {
    id: String(row.id),
    name: String(row.name || ""),
    company_name: row.company_name ? String(row.company_name) : null,
    type: row.type ? String(row.type) : null,
    email: row.email ? String(row.email) : null,
    phone: row.phone ? String(row.phone) : null,
    whatsapp: row.whatsapp ? String(row.whatsapp) : null,
    notes: row.notes ? String(row.notes) : null,
    tags: Array.isArray(row.tags) ? row.tags.map((tag) => String(tag)) : [],
    active: row.active !== false,
    created_at: row.created_at || null,
    updated_at: row.updated_at || null,
  };
}

function scorePhoneMatch(target: string, row: CustomerRow) {
  const targetCandidates = new Set(buildPhoneCandidates(target));
  const whatsappDigits = normalizePhoneDigits(String(row.whatsapp || ""));
  const phoneDigits = normalizePhoneDigits(String(row.phone || ""));

  if (whatsappDigits && targetCandidates.has(whatsappDigits)) return 3;
  if (phoneDigits && targetCandidates.has(phoneDigits)) return 2;

  const targetTail = target.slice(-8);
  if (whatsappDigits && targetTail && whatsappDigits.endsWith(targetTail)) return 1;
  if (phoneDigits && targetTail && phoneDigits.endsWith(targetTail)) return 1;

  return 0;
}

export async function findCustomerByPhone(params: {
  supabase: SupabaseClient;
  user: User;
  phone: string;
}) {
  const ctx = await getCompanyContext(params.supabase, params.user);
  if (!canCompany(ctx, params.user.id, "clients.read")) {
    throw new ApiV1Error(403, "forbidden", "Sem permissao para visualizar clientes.");
  }

  const normalizedPhone = normalizePhoneDigits(params.phone);
  if (!normalizedPhone) {
    throw new ApiV1Error(400, "invalid_phone", "Telefone invalido.");
  }

  const tenantIds = ctx.tenantIds?.length ? ctx.tenantIds : [params.user.id];
  const searchTail = normalizedPhone.slice(-4);

  let query = params.supabase
    .from("clients")
    .select("id,name,company_name,type,email,phone,whatsapp,notes,tags,active,created_at,updated_at,is_deleted,is_system_placeholder")
    .in("user_id", tenantIds)
    .order("updated_at", { ascending: false })
    .limit(200);

  if (searchTail) {
    query = query.or(`phone.ilike.%${searchTail}%,whatsapp.ilike.%${searchTail}%`);
  }

  const { data, error } = await query;
  if (error) {
    throw new ApiV1Error(400, "customer_lookup_failed", error.message);
  }

  const rows = ((data || []) as CustomerRow[])
    .filter((row) => !row.is_deleted)
    .filter((row) => !isQuickPlaceholderClient(row));

  const bestMatch = rows
    .map((row) => ({ row, score: scorePhoneMatch(normalizedPhone, row) }))
    .filter((entry) => entry.score > 0)
    .sort((a, b) => {
      if (b.score !== a.score) return b.score - a.score;
      if ((a.row.active !== false) !== (b.row.active !== false)) {
        return a.row.active === false ? 1 : -1;
      }
      return new Date(String(b.row.updated_at || b.row.created_at || 0)).getTime() - new Date(String(a.row.updated_at || a.row.created_at || 0)).getTime();
    })[0];

  return {
    ok: true as const,
    normalized_phone: normalizedPhone,
    found: Boolean(bestMatch),
    customer: bestMatch ? mapCustomer(bestMatch.row) : null,
  };
}
