'use client';

import Link from 'next/link';
import { useCallback, useEffect, useState } from 'react';
import Swal from 'sweetalert2';
import { Modal, formatDate, formatDateTime } from '@/components/app/ui';
import { extractApiError } from '@/lib/api-client';
import { centsToInput, formatCents, parseMoneyToCents } from '@/lib/money';
import {
  cancelCharge,
  Charge,
  CHARGE_STATUS_BADGES,
  CHARGE_STATUS_LABELS,
  getCharge,
  ONLINE_METHODS,
  PAYMENT_METHOD_LABELS,
  PAYMENT_STATUS_LABELS,
  PaymentMethod,
  refundPayment,
  registerPayment,
} from '@/lib/services/finance';

/** Detalhe da cobrança: pagamentos, recibos, baixa manual/online e estorno. */
export default function ChargeModal({
  chargeId,
  isAdmin,
  onClose,
  onChanged,
}: {
  chargeId: number | null;
  isAdmin: boolean;
  onClose: () => void;
  onChanged: () => void;
}) {
  const [charge, setCharge] = useState<Charge | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [busy, setBusy] = useState(false);
  const [amount, setAmount] = useState('');
  const [method, setMethod] = useState<PaymentMethod>('pix');
  const [provider, setProvider] = useState<'manual' | 'sandbox'>('manual');

  const load = useCallback(async () => {
    if (!chargeId) return;
    setError(null);
    try {
      const loaded = await getCharge(chargeId);
      setCharge(loaded);
      const pending = (loaded.payments ?? [])
        .filter((p) => p.status === 'pending')
        .reduce((sum, p) => sum + p.amountCents, 0);
      setAmount(centsToInput(Math.max(0, loaded.balanceCents - pending)));
    } catch (err) {
      setError(extractApiError(err));
    }
  }, [chargeId]);

  useEffect(() => {
    setCharge(null);
    setProvider('manual');
    load();
  }, [load]);

  async function act(fn: () => Promise<unknown>, success: string) {
    setBusy(true);
    try {
      await fn();
      await load();
      onChanged();
      Swal.fire({ icon: 'success', title: success, timer: 1200, showConfirmButton: false });
    } catch (err) {
      Swal.fire({ icon: 'error', title: 'Erro', text: extractApiError(err) });
    } finally {
      setBusy(false);
    }
  }

  async function handlePay(e: React.FormEvent) {
    e.preventDefault();
    if (!charge) return;
    const amountCents = parseMoneyToCents(amount);
    if (!amountCents) {
      Swal.fire({ icon: 'warning', title: 'Informe um valor válido' });
      return;
    }
    await act(
      () => registerPayment(charge.id, { amountCents, method, provider }),
      provider === 'manual' ? 'Pagamento registrado' : 'Link de pagamento gerado',
    );
  }

  async function handleRefund(paymentId: number, value: number) {
    const result = await Swal.fire<string>({
      icon: 'warning',
      title: `Estornar ${formatCents(value)}?`,
      text: 'O recibo será cancelado e o valor volta para o saldo da cobrança.',
      input: 'text',
      inputLabel: 'Motivo do estorno',
      inputValidator: (v) => (!v?.trim() ? 'Informe o motivo' : undefined),
      showCancelButton: true,
      confirmButtonText: 'Estornar',
      cancelButtonText: 'Voltar',
      confirmButtonColor: '#dc3545',
    });
    if (!result.isConfirmed || !result.value) return;
    await act(() => refundPayment(paymentId, result.value!.trim()), 'Pagamento estornado');
  }

  async function handleCancel() {
    if (!charge) return;
    const result = await Swal.fire<string>({
      icon: 'warning',
      title: 'Cancelar cobrança?',
      input: 'text',
      inputLabel: 'Motivo (opcional)',
      showCancelButton: true,
      confirmButtonText: 'Cancelar cobrança',
      cancelButtonText: 'Voltar',
      confirmButtonColor: '#dc3545',
    });
    if (!result.isConfirmed) return;
    await act(() => cancelCharge(charge.id, result.value || undefined), 'Cobrança cancelada');
  }

  const open = Boolean(chargeId);
  const isOpenCharge = charge && (charge.status === 'pending' || charge.status === 'partially_paid');
  const availableMethods =
    provider === 'sandbox' ? ONLINE_METHODS : (Object.keys(PAYMENT_METHOD_LABELS) as PaymentMethod[]);

  return (
    <Modal open={open} title={charge?.description ?? 'Cobrança'} onClose={onClose} size="lg" busy={busy}>
      {error && <div className="alert alert-danger">{error}</div>}
      {!charge && !error && (
        <div className="text-center py-4">
          <span className="spinner-border text-primary" />
        </div>
      )}
      {charge && (
        <>
          <div className="row g-3 mb-3">
            <div className="col-sm-6">
              <div className="small text-muted">Paciente</div>
              <div className="fw-semibold">{charge.patient?.fullName}</div>
              {charge.treatmentPlanId && (
                <Link href={`/painel/tratamentos/${charge.treatmentPlanId}`} className="small">
                  Plano de tratamento nº {charge.treatmentPlanId}
                </Link>
              )}
            </div>
            <div className="col-sm-6 text-sm-end">
              <span className={`badge ${CHARGE_STATUS_BADGES[charge.status]}`}>
                {CHARGE_STATUS_LABELS[charge.status]}
              </span>
              {charge.isOverdue && <span className="badge text-bg-danger ms-1">Vencida</span>}
              <div className="small text-muted mt-1">
                Vencimento {formatDate(`${charge.dueDate}T12:00:00`)}
              </div>
            </div>
          </div>

          <div className="row g-2 text-center mb-4">
            {[
              ['Valor', charge.amountCents],
              ['Pago', charge.paidCents],
              ['Saldo', charge.balanceCents],
            ].map(([label, value]) => (
              <div className="col-4" key={label as string}>
                <div className="border rounded py-2">
                  <div className="small text-muted">{label}</div>
                  <div className="fw-bold">{formatCents(value as number)}</div>
                </div>
              </div>
            ))}
          </div>

          <h3 className="h6 fw-semibold">Pagamentos</h3>
          {(charge.payments ?? []).length === 0 ? (
            <p className="text-muted small">Nenhum pagamento registrado.</p>
          ) : (
            <div className="table-responsive mb-3">
              <table className="table table-sm align-middle">
                <thead>
                  <tr>
                    <th scope="col">Data</th>
                    <th scope="col">Forma</th>
                    <th scope="col" className="text-end">Valor</th>
                    <th scope="col">Situação</th>
                    <th scope="col" className="text-end" aria-label="Ações" />
                  </tr>
                </thead>
                <tbody>
                  {charge.payments!.map((p) => (
                    <tr key={p.id}>
                      <td className="small">{formatDateTime(p.paidAt ?? p.refundedAt ?? null)}</td>
                      <td className="small">
                        {PAYMENT_METHOD_LABELS[p.method]}
                        {p.provider === 'sandbox' && <span className="badge text-bg-light border ms-1">online</span>}
                      </td>
                      <td className="text-end table-nowrap">{formatCents(p.amountCents)}</td>
                      <td className="small">
                        {PAYMENT_STATUS_LABELS[p.status]}
                        {p.refundReason && <div className="text-muted">{p.refundReason}</div>}
                      </td>
                      <td className="text-end table-nowrap">
                        {p.receipt && (
                          <Link
                            href={`/painel/financeiro/recibos/${p.receipt.id}`}
                            className="btn btn-sm btn-outline-secondary me-1"
                            target="_blank"
                          >
                            Recibo {p.receipt.number}
                          </Link>
                        )}
                        {p.status === 'pending' && p.checkoutUrl && (
                          <a href={p.checkoutUrl} target="_blank" rel="noreferrer" className="btn btn-sm btn-outline-primary me-1">
                            Link de pagamento
                          </a>
                        )}
                        {isAdmin && p.status === 'confirmed' && (
                          <button
                            className="btn btn-sm btn-outline-danger"
                            onClick={() => handleRefund(p.id, p.amountCents)}
                            disabled={busy}
                          >
                            Estornar
                          </button>
                        )}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}

          {isOpenCharge && (
            <form className="border rounded p-3 bg-light" onSubmit={handlePay} noValidate>
              <h3 className="h6 fw-semibold">Registrar recebimento</h3>
              <div className="row g-2 align-items-end">
                <div className="col-12 col-md-4">
                  <label htmlFor="pay-provider" className="form-label small">Como</label>
                  <select
                    id="pay-provider"
                    className="form-select"
                    value={provider}
                    onChange={(e) => {
                      const next = e.target.value as 'manual' | 'sandbox';
                      setProvider(next);
                      if (next === 'sandbox' && !ONLINE_METHODS.includes(method)) setMethod('pix');
                    }}
                  >
                    <option value="manual">Recebido na clínica</option>
                    <option value="sandbox">Gerar link online (sandbox)</option>
                  </select>
                </div>
                <div className="col-6 col-md-4">
                  <label htmlFor="pay-method" className="form-label small">Forma</label>
                  <select
                    id="pay-method"
                    className="form-select"
                    value={method}
                    onChange={(e) => setMethod(e.target.value as PaymentMethod)}
                  >
                    {availableMethods.map((m) => (
                      <option key={m} value={m}>
                        {PAYMENT_METHOD_LABELS[m]}
                      </option>
                    ))}
                  </select>
                </div>
                <div className="col-6 col-md-2">
                  <label htmlFor="pay-amount" className="form-label small">Valor (R$)</label>
                  <input
                    id="pay-amount"
                    inputMode="decimal"
                    className="form-control"
                    value={amount}
                    onChange={(e) => setAmount(e.target.value)}
                  />
                </div>
                <div className="col-12 col-md-2">
                  <button type="submit" className="btn btn-success w-100" disabled={busy}>
                    {provider === 'manual' ? 'Receber' : 'Gerar'}
                  </button>
                </div>
              </div>
              <div className="form-text">
                {provider === 'manual'
                  ? 'Use para dinheiro, PIX na conta da clínica ou maquininha. O recibo é emitido na hora.'
                  : 'Gera um link do provedor simulado; a baixa acontece quando o pagamento é aprovado.'}
              </div>
            </form>
          )}

          {isOpenCharge && charge.paidCents === 0 && (
            <div className="text-end mt-3">
              <button className="btn btn-link text-danger" onClick={handleCancel} disabled={busy}>
                Cancelar cobrança
              </button>
            </div>
          )}
          {charge.status === 'cancelled' && charge.cancelReason && (
            <p className="small text-muted mt-3 mb-0">Cancelada: {charge.cancelReason}</p>
          )}
        </>
      )}
    </Modal>
  );
}
