import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

export function currency(value: number | string | { s?: number; e?: number; d?: number[] } | unknown): string {
  if (value === null || value === undefined) return "R$ 0,00";
  let num = 0;
  if (typeof value === "number") {
    num = isNaN(value) ? 0 : value;
  } else if (typeof value === "string") {
    num = Number(value) || 0;
  } else if (typeof value === "object" && value !== null) {
    if ("s" in value && "e" in value && "d" in value) {
      num = Number((value as any).toString()) || 0;
    } else if ("toNumber" in value && typeof (value as any).toNumber === "function") {
      num = (value as any).toNumber();
    } else {
      num = Number(value.toString()) || 0;
    }
  }
  return new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(num);
}

export function formatDate(value: string | Date | null | undefined): string {
  if (!value) return "-";
  try {
    if (typeof value === "string") {
      const datePart = value.split("T")[0];
      if (/^\d{4}-\d{2}-\d{2}$/.test(datePart)) {
        const [year, month, day] = datePart.split("-").map(Number);
        const utcDate = new Date(Date.UTC(year, month - 1, day));
        return new Intl.DateTimeFormat("pt-BR", { timeZone: "UTC" }).format(utcDate);
      }
    }
    const dateObj = typeof value === "string" ? new Date(value) : value;
    if (isNaN(dateObj.getTime())) return "-";
    return new Intl.DateTimeFormat("pt-BR").format(dateObj);
  } catch {
    return "-";
  }
}

export function formatDateTime(value: string | Date | null | undefined): string {
  if (!value) return "-";
  try {
    const dateObj = typeof value === "string" ? new Date(value) : value;
    if (isNaN(dateObj.getTime())) return "-";
    return new Intl.DateTimeFormat("pt-BR", {
      day: "2-digit",
      month: "2-digit",
      year: "numeric",
      hour: "2-digit",
      minute: "2-digit",
    }).format(dateObj);
  } catch {
    return "-";
  }
}

export interface RateCalculationResult {
  totalItem: number;
  rateApplied: string;
  effectiveDailyRate: number;
}

/**
 * Tarifador Inteligente Degressivo para Locadoras:
 * Aplica automaticamente a melhor tarifa (Diária, Semanal ou Mensal)
 * com base no período de locação em dias.
 */
export function calculateEquipmentRate(
  days: number,
  rates?: { dailyRate?: number; weeklyRate?: number; monthlyRate?: number } | null
): RateCalculationResult {
  if (!rates) return { totalItem: 0, rateApplied: "Diária", effectiveDailyRate: 0 };

  const daily = Number(rates.dailyRate) || 0;
  const weekly = Number(rates.weeklyRate) || 0;
  const monthly = Number(rates.monthlyRate) || 0;

  if (days <= 0) return { totalItem: 0, rateApplied: "Diária", effectiveDailyRate: daily };

  // 1. Período mensal (>= 30 dias)
  if (days >= 30 && monthly > 0) {
    const fullMonths = Math.floor(days / 30);
    const remDays = days % 30;

    let remTotal = 0;
    if (remDays > 0) {
      if (weekly > 0 && remDays >= 7) {
        const remWeeks = Math.floor(remDays / 7);
        const remWeekDays = remDays % 7;
        remTotal = Math.min(remDays * daily, remWeeks * weekly + remWeekDays * daily, monthly);
      } else {
        remTotal = Math.min(remDays * daily, monthly);
      }
    }

    const totalItem = fullMonths * monthly + remTotal;
    const effectiveDailyRate = Number((totalItem / days).toFixed(2));
    const rateApplied = days === 30 ? "Mensal (Tabela)" : `Mensal (${fullMonths}m ${remDays}d)`;

    return { totalItem, rateApplied, effectiveDailyRate };
  }

  // 2. Período semanal (>= 7 dias e < 30 dias)
  if (days >= 7 && weekly > 0) {
    const fullWeeks = Math.floor(days / 7);
    const remDays = days % 7;

    const calculatedWeeklyTotal = fullWeeks * weekly + remDays * daily;
    const pureDailyTotal = days * daily;
    const capMonthly = monthly > 0 ? monthly : Infinity;

    const totalItem = Math.min(pureDailyTotal, calculatedWeeklyTotal, capMonthly);
    const effectiveDailyRate = Number((totalItem / days).toFixed(2));
    const rateApplied = totalItem === capMonthly ? "Mensal (Teto)" : "Semanal (Tabela)";

    return { totalItem, rateApplied, effectiveDailyRate };
  }

  // 3. Período por diária simples (< 7 dias)
  const pureDailyTotal = days * daily;
  const capWeekly = weekly > 0 ? weekly : Infinity;
  const capMonthly = monthly > 0 ? monthly : Infinity;

  const totalItem = Math.min(pureDailyTotal, capWeekly, capMonthly);
  const effectiveDailyRate = Number((totalItem / days).toFixed(2));
  let rateApplied = "Diária";
  if (totalItem === capWeekly) rateApplied = "Semanal (Teto)";
  if (totalItem === capMonthly) rateApplied = "Mensal (Teto)";

  return { totalItem, rateApplied, effectiveDailyRate };
}
