'use client'

import { useCallback, useEffect, useMemo, useState } from 'react'
import Link from 'next/link'
import { formatCurrency, SupportedCurrency } from '@rentaldrivego/types'
import { apiFetch } from '@/lib/api'
import { useDashboardI18n } from '@/components/I18nProvider'

type BillingPaymentType = 'CHARGE' | 'DEPOSIT'
type ManualPaymentMethod = 'CASH' | 'CHECK' | 'BANK_TRANSFER' | 'CARD' | 'PAYPAL' | 'OTHER'

type BillingPayment = {
  id: string
  amountMinor: number
  currency: SupportedCurrency
  type: BillingPaymentType
  channel: 'ONLINE' | 'OFFLINE' | 'TERMINAL'
  provider: string
  method: string | null
  status: string
  reference: string | null
  receivedAt: string
  createdAt: string
  recordedBy: { name: string; email: string } | null
}

type BillingInvoice = {
  id: string
  reservationId: string
  invoiceNumber: string | null
  contractNumber: string | null
  customer: { firstName: string; lastName: string; email: string }
  vehicle: { make: string; model: string; licensePlate: string }
  rentalPeriod: { startDate: string; endDate: string }
  currency: SupportedCurrency
  paymentStatus: 'UNPAID' | 'PARTIAL' | 'PAID'
  invoiceTotal: number
  invoicePaid: number
  invoiceBalanceDue: number
  depositRequired: number
  depositCollected: number
  depositHeld: number
  depositOutstanding: number
  depositStatus: string
  paymentCount: number
  latestPayment: BillingPayment | null
}

type BillingSummary = {
  currency: SupportedCurrency
  totalInvoiced: number
  totalCollected: number
  totalRefunded: number
  totalOutstanding: number
  depositsHeld: number
  openInvoiceCount: number
  overdueInvoiceCount: number
}

type BillingInvoiceResponse = {
  items: BillingInvoice[]
  page: number
  pageSize: number
  totalItems: number
  totalPages: number
}

const STATUS_BADGE: Record<string, string> = {
  UNPAID: 'bg-rose-100 text-rose-700',
  PARTIAL: 'bg-orange-100 text-orange-700',
  PAID: 'bg-emerald-100 text-emerald-700',
  OUTSTANDING: 'bg-rose-100 text-rose-700',
  PARTIALLY_COLLECTED: 'bg-orange-100 text-orange-700',
  HELD: 'bg-emerald-100 text-emerald-700',
  NOT_REQUIRED: 'bg-slate-100 text-slate-700',
}

export default function BillingPage() {
  const { language } = useDashboardI18n()
  const localeCode = language === 'fr' ? 'fr-FR' : language === 'ar' ? 'ar-MA' : 'en-US'
  const [summary, setSummary] = useState<BillingSummary | null>(null)
  const [invoices, setInvoices] = useState<BillingInvoiceResponse | null>(null)
  const [search, setSearch] = useState('')
  const [submittedSearch, setSubmittedSearch] = useState('')
  const [paymentStatus, setPaymentStatus] = useState<'ALL' | 'UNPAID' | 'PARTIAL' | 'PAID'>('ALL')
  const [outstandingOnly, setOutstandingOnly] = useState(false)
  const [page, setPage] = useState(1)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [paymentInvoice, setPaymentInvoice] = useState<BillingInvoice | null>(null)
  const [paymentType, setPaymentType] = useState<BillingPaymentType>('CHARGE')
  const [paymentMethod, setPaymentMethod] = useState<ManualPaymentMethod>('CASH')
  const [paymentAmount, setPaymentAmount] = useState('')
  const [receivedAt, setReceivedAt] = useState('')
  const [reference, setReference] = useState('')
  const [note, setNote] = useState('')
  const [submittingPayment, setSubmittingPayment] = useState(false)
  const [paymentError, setPaymentError] = useState<string | null>(null)

  const copy = useMemo(() => ({
    en: {
      heading: 'Customer Billing',
      subtitle: 'Customer invoices, rental payments, deposits, and balances. Subscription billing is managed separately.',
      search: 'Search customer, invoice, contract, vehicle, or plate',
      applySearch: 'Search',
      allStatuses: 'All statuses',
      outstandingOnly: 'Outstanding only',
      totalInvoiced: 'Total invoiced',
      collected: 'Collected',
      outstanding: 'Outstanding',
      depositsHeld: 'Deposits held',
      openInvoices: 'Open invoices',
      invoiceCustomer: 'Invoice and customer',
      vehicle: 'Vehicle',
      period: 'Rental period',
      invoiceTotal: 'Invoice total',
      paid: 'Paid',
      balance: 'Balance',
      deposit: 'Deposit',
      status: 'Status',
      actions: 'Actions',
      recordPayment: 'Record payment',
      noPaymentDue: 'No payment due',
      openContract: 'Open contract',
      openBooking: 'Open booking',
      loading: 'Loading customer billing...',
      failed: 'Failed to load customer billing.',
      retry: 'Retry',
      empty: 'No customer billing records found.',
      previous: 'Previous',
      next: 'Next',
      pageLabel: (current: number, total: number) => `Page ${current} of ${total}`,
      unknownInvoice: 'Draft invoice',
      none: '-',
      paymentDialogTitle: 'Record manual payment',
      paymentDialogDescription: 'Record an offline payment against the correct invoice or security-deposit balance.',
      paymentTarget: 'Payment target',
      charge: 'Invoice charge',
      securityDeposit: 'Security deposit',
      remaining: 'Remaining',
      paymentMethod: 'Payment method',
      amount: 'Amount',
      currency: 'Currency',
      receivedAt: 'Received at',
      reference: 'Reference',
      note: 'Internal note',
      cancel: 'Cancel',
      save: 'Save payment',
      saving: 'Saving...',
      invalidAmount: 'Enter a valid amount within the selected remaining balance.',
      paymentStatusLabels: { ALL: 'All', UNPAID: 'Unpaid', PARTIAL: 'Partial', PAID: 'Paid' } as Record<string, string>,
      depositStatusLabels: { NOT_REQUIRED: 'Not required', OUTSTANDING: 'Outstanding', PARTIALLY_COLLECTED: 'Partially collected', HELD: 'Held' } as Record<string, string>,
      paymentMethodLabels: { CASH: 'Cash', CHECK: 'Check', BANK_TRANSFER: 'Bank transfer', CARD: 'Card', PAYPAL: 'PayPal', OTHER: 'Other' } as Record<string, string>,
    },
    fr: {
      heading: 'Facturation clients',
      subtitle: 'Factures clients, paiements de location, dépôts et soldes. La facturation d’abonnement est séparée.',
      search: 'Rechercher client, facture, contrat, véhicule ou plaque',
      applySearch: 'Rechercher',
      allStatuses: 'Tous les statuts',
      outstandingOnly: 'Soldes uniquement',
      totalInvoiced: 'Total facturé',
      collected: 'Encaissé',
      outstanding: 'Solde restant',
      depositsHeld: 'Dépôts détenus',
      openInvoices: 'Factures ouvertes',
      invoiceCustomer: 'Facture et client',
      vehicle: 'Véhicule',
      period: 'Période',
      invoiceTotal: 'Total facture',
      paid: 'Payé',
      balance: 'Solde',
      deposit: 'Dépôt',
      status: 'Statut',
      actions: 'Actions',
      recordPayment: 'Encaisser',
      noPaymentDue: 'Aucun montant dû',
      openContract: 'Ouvrir contrat',
      openBooking: 'Ouvrir réservation',
      loading: 'Chargement de la facturation client...',
      failed: 'Échec du chargement de la facturation client.',
      retry: 'Réessayer',
      empty: 'Aucune facture client trouvée.',
      previous: 'Précédent',
      next: 'Suivant',
      pageLabel: (current: number, total: number) => `Page ${current} sur ${total}`,
      unknownInvoice: 'Facture brouillon',
      none: '-',
      paymentDialogTitle: 'Enregistrer un paiement manuel',
      paymentDialogDescription: 'Enregistrez un paiement hors ligne sur le bon solde de facture ou de dépôt de garantie.',
      paymentTarget: 'Cible du paiement',
      charge: 'Facture',
      securityDeposit: 'Dépôt de garantie',
      remaining: 'Restant',
      paymentMethod: 'Mode de paiement',
      amount: 'Montant',
      currency: 'Devise',
      receivedAt: 'Reçu le',
      reference: 'Référence',
      note: 'Note interne',
      cancel: 'Annuler',
      save: 'Enregistrer',
      saving: 'Enregistrement...',
      invalidAmount: 'Saisissez un montant valide dans la limite du solde sélectionné.',
      paymentStatusLabels: { ALL: 'Tous', UNPAID: 'Non payé', PARTIAL: 'Partiel', PAID: 'Payé' } as Record<string, string>,
      depositStatusLabels: { NOT_REQUIRED: 'Non requis', OUTSTANDING: 'À collecter', PARTIALLY_COLLECTED: 'Partiellement collecté', HELD: 'Détenu' } as Record<string, string>,
      paymentMethodLabels: { CASH: 'Espèces', CHECK: 'Chèque', BANK_TRANSFER: 'Virement bancaire', CARD: 'Carte', PAYPAL: 'PayPal', OTHER: 'Autre' } as Record<string, string>,
    },
    ar: {
      heading: 'فوترة العملاء',
      subtitle: 'فواتير العملاء ودفعات الإيجار والضمانات والأرصدة. فوترة الاشتراك تدار بشكل منفصل.',
      search: 'ابحث بالعميل أو الفاتورة أو العقد أو السيارة أو اللوحة',
      applySearch: 'بحث',
      allStatuses: 'كل الحالات',
      outstandingOnly: 'المستحق فقط',
      totalInvoiced: 'إجمالي الفواتير',
      collected: 'المحصّل',
      outstanding: 'المتبقي',
      depositsHeld: 'الضمان المحتجز',
      openInvoices: 'الفواتير المفتوحة',
      invoiceCustomer: 'الفاتورة والعميل',
      vehicle: 'المركبة',
      period: 'الفترة',
      invoiceTotal: 'إجمالي الفاتورة',
      paid: 'المدفوع',
      balance: 'الرصيد',
      deposit: 'الضمان',
      status: 'الحالة',
      actions: 'الإجراءات',
      recordPayment: 'تسجيل دفعة',
      noPaymentDue: 'لا يوجد مبلغ مستحق',
      openContract: 'فتح العقد',
      openBooking: 'فتح الحجز',
      loading: 'جارٍ تحميل فوترة العملاء...',
      failed: 'فشل تحميل فوترة العملاء.',
      retry: 'إعادة المحاولة',
      empty: 'لم يتم العثور على سجلات فوترة.',
      previous: 'السابق',
      next: 'التالي',
      pageLabel: (current: number, total: number) => `الصفحة ${current} من ${total}`,
      unknownInvoice: 'فاتورة مسودة',
      none: '-',
      paymentDialogTitle: 'تسجيل دفعة يدوية',
      paymentDialogDescription: 'سجل دفعة خارجية على رصيد الفاتورة أو الضمان الصحيح.',
      paymentTarget: 'هدف الدفعة',
      charge: 'دفعة الفاتورة',
      securityDeposit: 'ضمان التأمين',
      remaining: 'المتبقي',
      paymentMethod: 'طريقة الدفع',
      amount: 'المبلغ',
      currency: 'العملة',
      receivedAt: 'وقت الاستلام',
      reference: 'المرجع',
      note: 'ملاحظة داخلية',
      cancel: 'إلغاء',
      save: 'حفظ الدفعة',
      saving: 'جارٍ الحفظ...',
      invalidAmount: 'أدخل مبلغاً صحيحاً ضمن الرصيد المحدد.',
      paymentStatusLabels: { ALL: 'الكل', UNPAID: 'غير مدفوع', PARTIAL: 'جزئي', PAID: 'مدفوع' } as Record<string, string>,
      depositStatusLabels: { NOT_REQUIRED: 'غير مطلوب', OUTSTANDING: 'مستحق', PARTIALLY_COLLECTED: 'محصل جزئياً', HELD: 'محتجز' } as Record<string, string>,
      paymentMethodLabels: { CASH: 'نقداً', CHECK: 'شيك', BANK_TRANSFER: 'تحويل بنكي', CARD: 'بطاقة', PAYPAL: 'PayPal', OTHER: 'أخرى' } as Record<string, string>,
    },
  }[language]), [language])

  const loadBilling = useCallback(async () => {
    setLoading(true)
    setError(null)
    const params = new URLSearchParams({
      page: String(page),
      pageSize: '10',
      search: submittedSearch,
      paymentStatus,
      outstandingOnly: String(outstandingOnly),
    })
    const summaryParams = new URLSearchParams({ search: submittedSearch })
    const [summaryRows, invoiceRows] = await Promise.all([
      apiFetch<BillingSummary>(`/billing/summary?${summaryParams.toString()}`),
      apiFetch<BillingInvoiceResponse>(`/billing/invoices?${params.toString()}`),
    ])
    setSummary(summaryRows)
    setInvoices(invoiceRows)
    setLoading(false)
  }, [outstandingOnly, page, paymentStatus, submittedSearch])

  useEffect(() => {
    loadBilling().catch((err) => {
      setError(err.message ?? copy.failed)
      setLoading(false)
    })
  }, [copy.failed, loadBilling])

  useEffect(() => {
    function handleKeyDown(event: KeyboardEvent) {
      if (event.key === 'Escape' && paymentInvoice && !submittingPayment) {
        setPaymentInvoice(null)
      }
    }
    window.addEventListener('keydown', handleKeyDown)
    return () => window.removeEventListener('keydown', handleKeyDown)
  }, [paymentInvoice, submittingPayment])

  const selectedRemaining = paymentInvoice
    ? paymentType === 'DEPOSIT'
      ? paymentInvoice.depositOutstanding
      : paymentInvoice.invoiceBalanceDue
    : 0

  function formatDate(value: string) {
    return new Date(value).toLocaleDateString(localeCode, {
      month: 'short',
      day: 'numeric',
      year: 'numeric',
    })
  }

  function formatMoney(amount: number, currency: SupportedCurrency = summary?.currency ?? 'MAD') {
    return formatCurrency(amount, currency)
  }

  function openPaymentDialog(invoice: BillingInvoice) {
    const nextType = invoice.invoiceBalanceDue > 0 ? 'CHARGE' : 'DEPOSIT'
    const remaining = nextType === 'DEPOSIT' ? invoice.depositOutstanding : invoice.invoiceBalanceDue
    setPaymentInvoice(invoice)
    setPaymentType(nextType)
    setPaymentMethod('CASH')
    setPaymentAmount((remaining / 100).toFixed(2))
    setReceivedAt(new Date().toISOString().slice(0, 16))
    setReference('')
    setNote('')
    setPaymentError(null)
  }

  function updatePaymentType(type: BillingPaymentType) {
    setPaymentType(type)
    if (!paymentInvoice) return
    const remaining = type === 'DEPOSIT' ? paymentInvoice.depositOutstanding : paymentInvoice.invoiceBalanceDue
    setPaymentAmount((remaining / 100).toFixed(2))
  }

  async function submitPayment() {
    if (!paymentInvoice) return
    const amountMinor = Math.round(Number(paymentAmount) * 100)
    if (!Number.isFinite(amountMinor) || amountMinor <= 0 || amountMinor > selectedRemaining) {
      setPaymentError(copy.invalidAmount)
      return
    }

    setSubmittingPayment(true)
    setPaymentError(null)
    try {
      await apiFetch(`/billing/invoices/${paymentInvoice.id}/payments/manual`, {
        method: 'POST',
        body: JSON.stringify({
          amountMinor,
          currency: paymentInvoice.currency,
          type: paymentType,
          method: paymentMethod,
          receivedAt: receivedAt ? new Date(receivedAt).toISOString() : undefined,
          reference: reference.trim() || undefined,
          note: note.trim() || undefined,
          idempotencyKey: crypto.randomUUID(),
        }),
      })
      setPaymentInvoice(null)
      await loadBilling()
    } catch (err: any) {
      setPaymentError(err.message ?? copy.failed)
    } finally {
      setSubmittingPayment(false)
    }
  }

  const rows = invoices?.items ?? []
  const currentPage = invoices?.page ?? page
  const totalPages = invoices?.totalPages ?? 1

  return (
    <div className="space-y-6">
      <div className="flex flex-col gap-4 xl:flex-row xl:items-end xl:justify-between">
        <div>
          <h2 className="text-xl font-semibold text-slate-900">{copy.heading}</h2>
          <p className="mt-1 max-w-3xl text-sm text-slate-500">{copy.subtitle}</p>
        </div>
        <form
          className="flex w-full flex-col gap-3 sm:flex-row xl:max-w-3xl"
          onSubmit={(event) => {
            event.preventDefault()
            setPage(1)
            setSubmittedSearch(search)
          }}
        >
          <input value={search} onChange={(event) => setSearch(event.target.value)} placeholder={copy.search} className="input-field min-w-0 flex-1" />
          <select value={paymentStatus} onChange={(event) => { setPage(1); setPaymentStatus(event.target.value as typeof paymentStatus) }} className="input-field sm:w-44">
            {(['ALL', 'UNPAID', 'PARTIAL', 'PAID'] as const).map((status) => (
              <option key={status} value={status}>{copy.paymentStatusLabels[status]}</option>
            ))}
          </select>
          <button type="submit" className="btn-primary justify-center">{copy.applySearch}</button>
        </form>
      </div>

      <label className="inline-flex items-center gap-2 text-sm font-medium text-slate-700">
        <input type="checkbox" checked={outstandingOnly} onChange={(event) => { setPage(1); setOutstandingOnly(event.target.checked) }} className="h-4 w-4 rounded border-slate-300 text-blue-600" />
        {copy.outstandingOnly}
      </label>

      <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-5">
        <MetricCard label={copy.totalInvoiced} value={formatMoney(summary?.totalInvoiced ?? 0)} />
        <MetricCard label={copy.collected} value={formatMoney(summary?.totalCollected ?? 0)} />
        <MetricCard label={copy.outstanding} value={formatMoney(summary?.totalOutstanding ?? 0)} />
        <MetricCard label={copy.depositsHeld} value={formatMoney(summary?.depositsHeld ?? 0)} />
        <MetricCard label={copy.openInvoices} value={(summary?.openInvoiceCount ?? 0).toLocaleString(localeCode)} />
      </div>

      {error ? (
        <div className="card p-6">
          <p className="text-sm font-semibold text-rose-700">{error}</p>
          <button type="button" onClick={() => loadBilling().catch((err) => setError(err.message ?? copy.failed))} className="mt-4 rounded-full border border-slate-200 px-4 py-2 text-sm font-semibold text-slate-700 hover:bg-slate-50">
            {copy.retry}
          </button>
        </div>
      ) : (
        <div className="card overflow-hidden">
          <div className="hidden overflow-x-auto lg:block">
            <table className="w-full">
              <thead>
                <tr className="border-b border-slate-200 bg-slate-50">
                  <th className="px-5 py-3 text-start text-xs font-medium uppercase text-slate-500">{copy.invoiceCustomer}</th>
                  <th className="px-5 py-3 text-start text-xs font-medium uppercase text-slate-500">{copy.vehicle}</th>
                  <th className="px-5 py-3 text-start text-xs font-medium uppercase text-slate-500">{copy.period}</th>
                  <th className="px-5 py-3 text-end text-xs font-medium uppercase text-slate-500">{copy.invoiceTotal}</th>
                  <th className="px-5 py-3 text-end text-xs font-medium uppercase text-slate-500">{copy.paid}</th>
                  <th className="px-5 py-3 text-end text-xs font-medium uppercase text-slate-500">{copy.balance}</th>
                  <th className="px-5 py-3 text-start text-xs font-medium uppercase text-slate-500">{copy.deposit}</th>
                  <th className="px-5 py-3 text-end text-xs font-medium uppercase text-slate-500">{copy.actions}</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-slate-100">
                {loading ? (
                  <tr><td colSpan={8} className="px-5 py-10 text-center text-sm text-slate-400">{copy.loading}</td></tr>
                ) : rows.length === 0 ? (
                  <tr><td colSpan={8} className="px-5 py-10 text-center text-sm text-slate-400">{copy.empty}</td></tr>
                ) : rows.map((invoice) => (
                  <tr key={invoice.id}>
                    <td className="px-5 py-4 text-sm">
                      <p dir="ltr" className="font-semibold text-slate-900">{invoice.invoiceNumber ?? copy.unknownInvoice}</p>
                      <p className="mt-1 font-medium text-slate-700">{invoice.customer.firstName} {invoice.customer.lastName}</p>
                      <p dir="ltr" className="text-xs text-slate-500">{invoice.customer.email}</p>
                    </td>
                    <td className="px-5 py-4 text-sm text-slate-700">
                      <p>{invoice.vehicle.make} {invoice.vehicle.model}</p>
                      <p dir="ltr" className="text-xs text-slate-500">{invoice.vehicle.licensePlate}</p>
                    </td>
                    <td className="px-5 py-4 text-sm text-slate-600">
                      <p>{formatDate(invoice.rentalPeriod.startDate)}</p>
                      <p>{formatDate(invoice.rentalPeriod.endDate)}</p>
                    </td>
                    <td dir="ltr" className="px-5 py-4 text-end text-sm font-semibold text-slate-900">{formatMoney(invoice.invoiceTotal, invoice.currency)}</td>
                    <td dir="ltr" className="px-5 py-4 text-end text-sm font-semibold text-emerald-700">{formatMoney(invoice.invoicePaid, invoice.currency)}</td>
                    <td dir="ltr" className="px-5 py-4 text-end text-sm font-semibold text-orange-700">{formatMoney(invoice.invoiceBalanceDue, invoice.currency)}</td>
                    <td className="px-5 py-4 text-sm">
                      <StatusBadge label={copy.depositStatusLabels[invoice.depositStatus] ?? invoice.depositStatus} status={invoice.depositStatus} />
                      <p dir="ltr" className="mt-2 text-xs text-slate-500">{formatMoney(invoice.depositOutstanding, invoice.currency)} {copy.remaining}</p>
                    </td>
                    <td className="px-5 py-4 text-end text-sm">
                      <InvoiceActions invoice={invoice} copy={copy} onRecordPayment={openPaymentDialog} />
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>

          <div className="divide-y divide-slate-100 lg:hidden">
            {loading ? (
              <p className="p-6 text-center text-sm text-slate-400">{copy.loading}</p>
            ) : rows.length === 0 ? (
              <p className="p-6 text-center text-sm text-slate-400">{copy.empty}</p>
            ) : rows.map((invoice) => (
              <div key={invoice.id} className="space-y-4 p-5">
                <div className="flex items-start justify-between gap-4">
                  <div>
                    <p dir="ltr" className="font-semibold text-slate-900">{invoice.invoiceNumber ?? copy.unknownInvoice}</p>
                    <p className="mt-1 text-sm text-slate-700">{invoice.customer.firstName} {invoice.customer.lastName}</p>
                    <p className="text-xs text-slate-500">{invoice.vehicle.make} {invoice.vehicle.model}</p>
                  </div>
                  <StatusBadge label={copy.paymentStatusLabels[invoice.paymentStatus]} status={invoice.paymentStatus} />
                </div>
                <div className="grid grid-cols-2 gap-3 text-sm">
                  <AmountBlock label={copy.invoiceTotal} value={formatMoney(invoice.invoiceTotal, invoice.currency)} />
                  <AmountBlock label={copy.balance} value={formatMoney(invoice.invoiceBalanceDue, invoice.currency)} />
                  <AmountBlock label={copy.paid} value={formatMoney(invoice.invoicePaid, invoice.currency)} />
                  <AmountBlock label={copy.deposit} value={formatMoney(invoice.depositOutstanding, invoice.currency)} />
                </div>
                <InvoiceActions invoice={invoice} copy={copy} onRecordPayment={openPaymentDialog} mobile />
              </div>
            ))}
          </div>

          <div className="flex items-center justify-between border-t border-slate-100 px-5 py-4 text-sm">
            <button type="button" disabled={currentPage <= 1 || loading} onClick={() => setPage((value) => Math.max(value - 1, 1))} className="rounded-full border border-slate-200 px-4 py-2 font-semibold text-slate-700 disabled:cursor-not-allowed disabled:opacity-50">
              {copy.previous}
            </button>
            <span className="text-slate-500">{copy.pageLabel(currentPage, totalPages)}</span>
            <button type="button" disabled={currentPage >= totalPages || loading} onClick={() => setPage((value) => value + 1)} className="rounded-full border border-slate-200 px-4 py-2 font-semibold text-slate-700 disabled:cursor-not-allowed disabled:opacity-50">
              {copy.next}
            </button>
          </div>
        </div>
      )}

      {paymentInvoice ? (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-blue-950/30 p-4 backdrop-blur-sm" onClick={(event) => {
          if (event.target === event.currentTarget && !submittingPayment) setPaymentInvoice(null)
        }}>
          <div role="dialog" aria-modal="true" aria-labelledby="manual-payment-title" aria-describedby="manual-payment-description" className="w-full max-w-xl rounded-2xl bg-white p-6 shadow-2xl">
            <div className="flex items-start justify-between gap-4">
              <div>
                <h3 id="manual-payment-title" className="text-lg font-semibold text-slate-900">{copy.paymentDialogTitle}</h3>
                <p id="manual-payment-description" className="mt-1 text-sm text-slate-500">{copy.paymentDialogDescription}</p>
              </div>
              <button type="button" aria-label={copy.cancel} onClick={() => setPaymentInvoice(null)} disabled={submittingPayment} className="rounded-full px-3 py-1 text-xl text-slate-400 hover:bg-slate-100 hover:text-slate-700">
                ×
              </button>
            </div>

            <div className="mt-5 rounded-lg border border-slate-200 bg-slate-50 p-4 text-sm">
              <p className="font-semibold text-slate-900">{paymentInvoice.customer.firstName} {paymentInvoice.customer.lastName}</p>
              <p dir="ltr" className="mt-1 text-slate-600">{paymentInvoice.invoiceNumber ?? copy.unknownInvoice}</p>
              <p dir="ltr" className="mt-2 font-semibold text-slate-900">{copy.remaining}: {formatMoney(selectedRemaining, paymentInvoice.currency)}</p>
            </div>

            {paymentError ? <div role="alert" className="mt-4 rounded-lg border border-rose-200 bg-rose-50 p-3 text-sm text-rose-700">{paymentError}</div> : null}

            <div className="mt-5 grid gap-4 sm:grid-cols-2">
              <label className="space-y-1 text-sm font-medium text-slate-700">
                <span>{copy.paymentTarget}</span>
                <select value={paymentType} onChange={(event) => updatePaymentType(event.target.value as BillingPaymentType)} disabled={submittingPayment} className="input-field">
                  <option value="CHARGE" disabled={paymentInvoice.invoiceBalanceDue <= 0}>{copy.charge}</option>
                  <option value="DEPOSIT" disabled={paymentInvoice.depositOutstanding <= 0}>{copy.securityDeposit}</option>
                </select>
              </label>
              <label className="space-y-1 text-sm font-medium text-slate-700">
                <span>{copy.paymentMethod}</span>
                <select value={paymentMethod} onChange={(event) => setPaymentMethod(event.target.value as ManualPaymentMethod)} disabled={submittingPayment} className="input-field">
                  {(Object.keys(copy.paymentMethodLabels) as ManualPaymentMethod[]).map((method) => (
                    <option key={method} value={method}>{copy.paymentMethodLabels[method]}</option>
                  ))}
                </select>
              </label>
              <label className="space-y-1 text-sm font-medium text-slate-700">
                <span>{copy.amount}</span>
                <input type="number" min="0" step="0.01" value={paymentAmount} onChange={(event) => setPaymentAmount(event.target.value)} disabled={submittingPayment} className="input-field" />
              </label>
              <label className="space-y-1 text-sm font-medium text-slate-700">
                <span>{copy.currency}</span>
                <input value={paymentInvoice.currency} readOnly className="input-field bg-slate-50" />
              </label>
              <label className="space-y-1 text-sm font-medium text-slate-700">
                <span>{copy.receivedAt}</span>
                <input type="datetime-local" value={receivedAt} onChange={(event) => setReceivedAt(event.target.value)} disabled={submittingPayment} className="input-field" />
              </label>
              <label className="space-y-1 text-sm font-medium text-slate-700">
                <span>{copy.reference}</span>
                <input value={reference} onChange={(event) => setReference(event.target.value)} disabled={submittingPayment} className="input-field" />
              </label>
              <label className="space-y-1 text-sm font-medium text-slate-700 sm:col-span-2">
                <span>{copy.note}</span>
                <textarea value={note} onChange={(event) => setNote(event.target.value)} disabled={submittingPayment} className="input-field min-h-24" />
              </label>
            </div>

            <div className="mt-6 flex flex-col-reverse gap-3 sm:flex-row">
              <button type="button" onClick={() => setPaymentInvoice(null)} disabled={submittingPayment} className="flex-1 rounded-full border border-slate-200 px-4 py-2 text-sm font-semibold text-slate-700 hover:bg-slate-50 disabled:opacity-60">
                {copy.cancel}
              </button>
              <button type="button" onClick={submitPayment} disabled={submittingPayment} className="btn-primary flex-1 justify-center disabled:cursor-not-allowed disabled:opacity-60">
                {submittingPayment ? copy.saving : copy.save}
              </button>
            </div>
          </div>
        </div>
      ) : null}
    </div>
  )
}

function MetricCard({ label, value }: { label: string; value: string }) {
  return (
    <div className="card p-5">
      <p className="text-sm font-medium text-slate-500">{label}</p>
      <p dir="ltr" className="mt-2 text-2xl font-semibold text-slate-900">{value}</p>
    </div>
  )
}

function StatusBadge({ label, status }: { label: string; status: string }) {
  return (
    <span className={`inline-flex rounded-full px-2.5 py-0.5 text-xs font-medium ${STATUS_BADGE[status] ?? 'bg-slate-100 text-slate-700'}`}>
      {label}
    </span>
  )
}

function AmountBlock({ label, value }: { label: string; value: string }) {
  return (
    <div className="rounded-lg bg-slate-50 p-3">
      <p className="text-xs font-medium uppercase text-slate-500">{label}</p>
      <p dir="ltr" className="mt-1 font-semibold text-slate-900">{value}</p>
    </div>
  )
}

function InvoiceActions({
  invoice,
  copy,
  onRecordPayment,
  mobile = false,
}: {
  invoice: BillingInvoice
  copy: any
  onRecordPayment: (invoice: BillingInvoice) => void
  mobile?: boolean
}) {
  const canRecord = invoice.invoiceBalanceDue > 0 || invoice.depositOutstanding > 0

  return (
    <div className={`flex ${mobile ? 'flex-row flex-wrap' : 'flex-col items-end'} gap-2`}>
      {canRecord ? (
        <button type="button" onClick={() => onRecordPayment(invoice)} className="font-semibold text-emerald-700 hover:underline">
          {copy.recordPayment}
        </button>
      ) : (
        <span className="text-xs text-slate-400">{copy.noPaymentDue}</span>
      )}
      <Link href={`/contracts/${invoice.reservationId}`} className="font-semibold text-blue-700 hover:underline">
        {copy.openContract}
      </Link>
      <Link href={`/reservations/${invoice.reservationId}`} className="text-slate-600 hover:text-slate-900 hover:underline">
        {copy.openBooking}
      </Link>
    </div>
  )
}
