'use client';

import Link from 'next/link';
import { useParams } from 'next/navigation';
import { useCallback, useEffect, useMemo, useState } from 'react';
import Swal from 'sweetalert2';
import { RequireRole, useAuth } from '@/lib/auth-context';
import {
  addPlanItem,
  completePlanItem,
  getTreatmentPlan,
  ITEM_STATUS_LABELS,
  listProcedures,
  planAction,
  PLAN_STATUS_BADGES,
  PLAN_STATUS_LABELS,
  Procedure,
  removePlanItem,
  TreatmentPlan,
  updateTreatmentPlan,
} from '@/lib/services/treatments';
import { Charge, CHARGE_STATUS_BADGES, CHARGE_STATUS_LABELS, listCharges } from '@/lib/services/finance';
import { getMyDentist } from '@/lib/services/dentists';
import {
  BackLink,
  ErrorAlert,
  Loading,
  Modal,
  PageHeader,
  formatDate,
  formatDateTime,
} from '@/components/app/ui';
import { extractApiError } from '@/lib/api-client';
import { centsToInput, formatCents, parseMoneyToCents } from '@/lib/money';

export default function PlanoPage() {
  return (
    <RequireRole roles={['admin', 'receptionist', 'dentist']}>
      <PlanEditor />
    </RequireRole>
  );
}

const FDI = /^([1-4][1-8]|[5-8][1-5])$/;

function PlanEditor() {
  const params = useParams<{ id: string }>();
  const planId = Number(params.id);
  const { user } = useAuth();

  const [plan, setPlan] = useState<TreatmentPlan | null>(null);
  const [charges, setCharges] = useState<Charge[]>([]);
  const [procedures, setProcedures] = useState<Procedure[]>([]);
  const [ownDentistId, setOwnDentistId] = useState<number | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [busy, setBusy] = useState(false);

  // Formulário de novo item
  const [procedureId, setProcedureId] = useState<number | ''>('');
  const [tooth, setTooth] = useState('');
  const [surfaces, setSurfaces] = useState('');
  const [quantity, setQuantity] = useState(1);
  const [price, setPrice] = useState('');
  const [itemError, setItemError] = useState<string | null>(null);

  // Modal de dados do plano
  const [editOpen, setEditOpen] = useState(false);
  const [form, setForm] = useState({ title: '', notes: '', discount: '', installments: 1, validUntil: '' });
  const [formError, setFormError] = useState<string | null>(null);

  const isAdmin = user?.role === 'admin';
  const canSeeFinance = isAdmin || user?.role === 'receptionist';
  const canEdit =
    !!plan && (isAdmin || (user?.role === 'dentist' && ownDentistId === Number(plan.dentistId)));
  const canDecide = !!plan && (canEdit || user?.role === 'receptionist');

  const load = useCallback(async () => {
    setError(null);
    try {
      const loaded = await getTreatmentPlan(planId);
      setPlan(loaded);
      if (canSeeFinance && loaded.approvedAt) {
        setCharges((await listCharges({ treatmentPlanId: planId, limit: 100 })).data);
      }
    } catch (err) {
      setError(extractApiError(err));
    }
  }, [planId, canSeeFinance]);

  useEffect(() => {
    load();
  }, [load]);

  useEffect(() => {
    listProcedures({ activeOnly: true })
      .then((r) => setProcedures(r.data))
      .catch(() => setProcedures([]));
    if (user?.role === 'dentist') {
      getMyDentist()
        .then((d) => setOwnDentistId(Number(d.id)))
        .catch(() => setOwnDentistId(null));
    }
  }, [user?.role]);

  const selectedProcedure = useMemo(
    () => procedures.find((p) => p.id === procedureId) ?? null,
    [procedures, procedureId],
  );

  async function run(action: () => Promise<TreatmentPlan | void>, success?: string) {
    setBusy(true);
    try {
      const result = await action();
      if (result) setPlan(result);
      await load();
      if (success) {
        Swal.fire({ icon: 'success', title: success, timer: 1300, showConfirmButton: false });
      }
    } catch (err) {
      Swal.fire({ icon: 'error', title: 'Erro', text: extractApiError(err) });
    } finally {
      setBusy(false);
    }
  }

  async function handleAddItem(e: React.FormEvent) {
    e.preventDefault();
    if (!procedureId) return setItemError('Escolha o procedimento.');
    if (tooth && !FDI.test(tooth)) return setItemError('Dente inválido (numeração FDI: 11–48, 51–85).');
    if (selectedProcedure?.requiresTooth && !tooth) {
      return setItemError('Este procedimento exige indicar o dente.');
    }
    const unitPriceCents = price ? parseMoneyToCents(price) : undefined;
    if (unitPriceCents === null) return setItemError('Preço inválido.');

    setItemError(null);
    setBusy(true);
    try {
      setPlan(
        await addPlanItem(planId, {
          procedureId,
          tooth: tooth || undefined,
          surfaces: surfaces || undefined,
          quantity,
          unitPriceCents,
        }),
      );
      setProcedureId('');
      setTooth('');
      setSurfaces('');
      setQuantity(1);
      setPrice('');
    } catch (err) {
      setItemError(extractApiError(err));
    } finally {
      setBusy(false);
    }
  }

  function openEdit() {
    if (!plan) return;
    setForm({
      title: plan.title,
      notes: plan.notes ?? '',
      discount: centsToInput(plan.discountCents),
      installments: plan.installments,
      validUntil: plan.validUntil ?? '',
    });
    setFormError(null);
    setEditOpen(true);
  }

  async function saveEdit(e: React.FormEvent) {
    e.preventDefault();
    const discountCents = parseMoneyToCents(form.discount || '0');
    if (discountCents === null) return setFormError('Desconto inválido.');
    setBusy(true);
    try {
      setPlan(
        await updateTreatmentPlan(planId, {
          title: form.title.trim(),
          notes: form.notes,
          discountCents,
          installments: form.installments,
          validUntil: form.validUntil || undefined,
        }),
      );
      setEditOpen(false);
    } catch (err) {
      setFormError(extractApiError(err));
    } finally {
      setBusy(false);
    }
  }

  async function confirmAction(
    action: 'propose' | 'approve' | 'reject' | 'cancel' | 'draft',
  ) {
    if (!plan) return;
    const texts = {
      propose: {
        title: 'Enviar orçamento?',
        text: 'O paciente recebe um e-mail e pode aprovar pelo portal. O plano não poderá ser editado enquanto estiver aguardando.',
        confirm: 'Enviar',
        done: 'Orçamento enviado',
      },
      approve: {
        title: 'Registrar aprovação presencial?',
        text: `Serão geradas ${plan.installments === 1 ? '1 cobrança' : `${plan.installments} parcelas`} totalizando ${formatCents(plan.totalCents)}.`,
        confirm: 'Aprovar',
        done: 'Orçamento aprovado',
      },
      reject: { title: 'Registrar recusa do orçamento?', text: '', confirm: 'Recusar', done: 'Orçamento recusado' },
      cancel: {
        title: 'Cancelar o plano?',
        text: 'Procedimentos não realizados e parcelas sem pagamento serão cancelados.',
        confirm: 'Cancelar plano',
        done: 'Plano cancelado',
      },
      draft: { title: 'Voltar para rascunho?', text: 'O orçamento deixa de estar disponível para aprovação.', confirm: 'Voltar', done: '' },
    }[action];

    const askReason = action === 'reject' || action === 'cancel';
    const result = await Swal.fire<string>({
      icon: action === 'cancel' || action === 'reject' ? 'warning' : 'question',
      title: texts.title,
      text: texts.text || undefined,
      input: askReason ? 'text' : undefined,
      inputLabel: askReason ? 'Motivo (opcional)' : undefined,
      showCancelButton: true,
      confirmButtonText: texts.confirm,
      cancelButtonText: 'Voltar',
      confirmButtonColor: action === 'cancel' ? '#dc3545' : undefined,
    });
    if (!result.isConfirmed) return;

    await run(async () => {
      const updated = await planAction(planId, action, result.value || undefined);
      if (action === 'cancel' && updated.openChargesKept) {
        await Swal.fire({
          icon: 'info',
          title: 'Plano cancelado',
          text: `${updated.openChargesKept} parcela(s) com pagamento parcial continuam em aberto no Financeiro.`,
        });
      }
      return updated;
    }, action === 'cancel' ? undefined : texts.done || undefined);
  }

  async function handleComplete(itemId: number, label: string) {
    const result = await Swal.fire<string>({
      icon: 'question',
      title: 'Registrar como realizado?',
      text: label,
      input: 'text',
      inputLabel: 'Observação (opcional)',
      showCancelButton: true,
      confirmButtonText: 'Realizado',
      cancelButtonText: 'Voltar',
    });
    if (!result.isConfirmed) return;
    await run(() => completePlanItem(planId, itemId, { notes: result.value || undefined }));
  }

  if (error) return <ErrorAlert message={error} onRetry={load} />;
  if (!plan) return <Loading />;

  const isDraft = plan.status === 'draft';
  const isActive = plan.status === 'approved' || plan.status === 'in_progress';
  const isOpen = ['draft', 'proposed', 'approved', 'in_progress'].includes(plan.status);
  const doneCount = plan.items.filter((i) => i.status === 'done').length;
  const activeItems = plan.items.filter((i) => i.status !== 'cancelled').length;

  return (
    <>
      <BackLink href="/painel/tratamentos" label="Tratamentos" />
      <PageHeader
        title={plan.title}
        subtitle={`${plan.patient?.fullName ?? ''} · ${plan.dentist?.fullName ?? ''}`}
        action={
          <div className="d-flex flex-wrap gap-2">
            <Link href={`/painel/tratamentos/${plan.id}/orcamento`} className="btn btn-outline-secondary">
              <i className="bi bi-printer me-1" />
              Orçamento
            </Link>
            {isDraft && canEdit && (
              <>
                <button className="btn btn-outline-primary" onClick={openEdit} disabled={busy}>
                  <i className="bi bi-pencil me-1" />
                  Dados do plano
                </button>
                <button className="btn btn-primary" onClick={() => confirmAction('propose')} disabled={busy}>
                  <i className="bi bi-send me-1" />
                  Enviar orçamento
                </button>
              </>
            )}
            {plan.status === 'proposed' && canDecide && (
              <>
                <button className="btn btn-success" onClick={() => confirmAction('approve')} disabled={busy}>
                  <i className="bi bi-check2-circle me-1" />
                  Aprovação presencial
                </button>
                <button className="btn btn-outline-secondary" onClick={() => confirmAction('reject')} disabled={busy}>
                  Recusado
                </button>
              </>
            )}
            {(plan.status === 'proposed' || plan.status === 'rejected') && canEdit && (
              <button className="btn btn-outline-primary" onClick={() => confirmAction('draft')} disabled={busy}>
                <i className="bi bi-arrow-counterclockwise me-1" />
                Voltar para rascunho
              </button>
            )}
            {isOpen && canEdit && (
              <button className="btn btn-outline-danger" onClick={() => confirmAction('cancel')} disabled={busy}>
                Cancelar plano
              </button>
            )}
          </div>
        }
      />

      <div className="d-flex flex-wrap align-items-center gap-3 mb-3">
        <span className={`badge fs-6 ${PLAN_STATUS_BADGES[plan.status]}`}>
          {PLAN_STATUS_LABELS[plan.status]}
        </span>
        {plan.approvedAt && (
          <small className="text-muted">
            Aprovado em {formatDateTime(plan.approvedAt)}{' '}
            {plan.approvalChannel === 'portal' ? 'pelo paciente (portal)' : 'presencialmente'}
          </small>
        )}
        {plan.status === 'rejected' && plan.rejectionReason && (
          <small className="text-muted">Motivo da recusa: {plan.rejectionReason}</small>
        )}
        {isActive && (
          <small className="text-muted">
            {doneCount} de {activeItems} procedimento(s) realizados
          </small>
        )}
      </div>

      <div className="row g-4">
        <div className="col-lg-8">
          <div className="card border-0 shadow-sm">
            <div className="card-header bg-white fw-semibold">Procedimentos</div>
            <div className="table-responsive">
              <table className="table align-middle mb-0">
                <thead className="table-light">
                  <tr>
                    <th scope="col">Procedimento</th>
                    <th scope="col">Dente</th>
                    <th scope="col" className="text-end">Qtd.</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>
                  {plan.items.length === 0 && (
                    <tr>
                      <td colSpan={6} className="text-center text-muted py-4">
                        Nenhum procedimento adicionado.
                      </td>
                    </tr>
                  )}
                  {plan.items.map((item) => (
                    <tr key={item.id} className={item.status === 'cancelled' ? 'text-muted text-decoration-line-through' : ''}>
                      <td className="fw-semibold">
                        {item.description}
                        {item.notes && <small className="d-block text-muted fw-normal">{item.notes}</small>}
                      </td>
                      <td>
                        {item.tooth ?? '—'}
                        {item.surfaces && <small className="text-muted"> ({item.surfaces})</small>}
                      </td>
                      <td className="text-end">{item.quantity}</td>
                      <td className="text-end table-nowrap">{formatCents(item.totalCents)}</td>
                      <td>
                        <span className={`badge ${item.status === 'done' ? 'text-bg-success' : 'text-bg-light border'}`}>
                          {ITEM_STATUS_LABELS[item.status]}
                        </span>
                        {item.performedAt && (
                          <small className="d-block text-muted">
                            {formatDate(item.performedAt)} · {item.performedByDentist?.fullName}
                          </small>
                        )}
                      </td>
                      <td className="text-end table-nowrap">
                        {isDraft && canEdit && (
                          <button
                            className="btn btn-sm btn-outline-danger"
                            aria-label={`Remover ${item.description}`}
                            onClick={() => run(() => removePlanItem(planId, item.id))}
                            disabled={busy}
                          >
                            <i className="bi bi-trash" />
                          </button>
                        )}
                        {isActive && canEdit && item.status === 'planned' && (
                          <button
                            className="btn btn-sm btn-outline-success"
                            onClick={() => handleComplete(item.id, item.description)}
                            disabled={busy}
                          >
                            <i className="bi bi-check2 me-1" />
                            Realizado
                          </button>
                        )}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>

            {isDraft && canEdit && (
              <form className="card-body border-top" onSubmit={handleAddItem} noValidate>
                <h2 className="h6 fw-semibold">Adicionar procedimento</h2>
                {itemError && <div className="alert alert-danger py-2">{itemError}</div>}
                <div className="row g-2 align-items-end">
                  <div className="col-12 col-md-5">
                    <label htmlFor="item-proc" className="form-label small">Procedimento</label>
                    <select
                      id="item-proc"
                      className="form-select"
                      value={procedureId}
                      onChange={(e) => {
                        const id = e.target.value ? Number(e.target.value) : '';
                        setProcedureId(id);
                        const proc = procedures.find((p) => p.id === id);
                        setPrice(proc ? centsToInput(proc.defaultPriceCents) : '');
                      }}
                    >
                      <option value="">Selecione</option>
                      {procedures.map((p) => (
                        <option key={p.id} value={p.id}>
                          {p.code} — {p.name}
                        </option>
                      ))}
                    </select>
                  </div>
                  <div className="col-4 col-md-2">
                    <label htmlFor="item-tooth" className="form-label small">
                      Dente{selectedProcedure?.requiresTooth ? ' *' : ''}
                    </label>
                    <input
                      id="item-tooth"
                      className="form-control"
                      inputMode="numeric"
                      maxLength={2}
                      placeholder="16"
                      value={tooth}
                      onChange={(e) => setTooth(e.target.value.replace(/\D/g, ''))}
                    />
                  </div>
                  <div className="col-4 col-md-2">
                    <label htmlFor="item-surfaces" className="form-label small">Faces</label>
                    <input
                      id="item-surfaces"
                      className="form-control text-uppercase"
                      maxLength={7}
                      placeholder="MOD"
                      value={surfaces}
                      onChange={(e) => setSurfaces(e.target.value.replace(/[^mdovlipMDOVLIP]/g, ''))}
                    />
                  </div>
                  <div className="col-4 col-md-1">
                    <label htmlFor="item-qty" className="form-label small">Qtd.</label>
                    <input
                      id="item-qty"
                      type="number"
                      min={1}
                      max={99}
                      className="form-control"
                      value={quantity}
                      onChange={(e) => setQuantity(Math.max(1, Number(e.target.value) || 1))}
                    />
                  </div>
                  <div className="col-8 col-md-2">
                    <label htmlFor="item-price" className="form-label small">Valor unit. (R$)</label>
                    <input
                      id="item-price"
                      inputMode="decimal"
                      className="form-control"
                      value={price}
                      onChange={(e) => setPrice(e.target.value)}
                    />
                  </div>
                  <div className="col-4 col-md-12 text-md-end">
                    <button type="submit" className="btn btn-primary" disabled={busy}>
                      <i className="bi bi-plus-lg me-1" />
                      Adicionar
                    </button>
                  </div>
                </div>
                <div className="form-text">
                  Dentes pela numeração FDI (11–48 permanentes, 51–85 decíduos). Faces: M, O, D, V, L, I, P.
                </div>
              </form>
            )}
          </div>
        </div>

        <div className="col-lg-4">
          <div className="card border-0 shadow-sm mb-4">
            <div className="card-body">
              <dl className="row mb-0">
                <dt className="col-6 fw-normal text-muted">Subtotal</dt>
                <dd className="col-6 text-end">{formatCents(plan.subtotalCents)}</dd>
                <dt className="col-6 fw-normal text-muted">Desconto</dt>
                <dd className="col-6 text-end">− {formatCents(plan.discountCents)}</dd>
                <dt className="col-6 fs-5">Total</dt>
                <dd className="col-6 text-end fs-5 fw-bold">{formatCents(plan.totalCents)}</dd>
                <dt className="col-6 fw-normal text-muted">Pagamento</dt>
                <dd className="col-6 text-end">
                  {plan.installments === 1 ? 'À vista' : `${plan.installments}x`}
                </dd>
                <dt className="col-6 fw-normal text-muted">Validade</dt>
                <dd className="col-6 text-end mb-0">{plan.validUntil ? formatDate(`${plan.validUntil}T12:00:00`) : '—'}</dd>
              </dl>
              {plan.notes && <p className="small text-muted border-top pt-3 mt-3 mb-0">{plan.notes}</p>}
            </div>
          </div>

          {canSeeFinance && plan.approvedAt && (
            <div className="card border-0 shadow-sm">
              <div className="card-header bg-white fw-semibold d-flex justify-content-between">
                Parcelas
                <Link href={`/painel/financeiro?patientId=${plan.patientId}`} className="small">
                  Abrir no financeiro
                </Link>
              </div>
              <ul className="list-group list-group-flush">
                {charges.map((charge) => (
                  <li key={charge.id} className="list-group-item d-flex justify-content-between align-items-center">
                    <div>
                      <div className="small fw-semibold">
                        {charge.installmentNumber}/{charge.installmentCount} · {formatDate(`${charge.dueDate}T12:00:00`)}
                      </div>
                      <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>
                    <span className="fw-semibold">{formatCents(charge.amountCents)}</span>
                  </li>
                ))}
              </ul>
            </div>
          )}
        </div>
      </div>

      <Modal
        open={editOpen}
        title="Dados do plano"
        onClose={() => setEditOpen(false)}
        busy={busy}
        footer={
          <>
            <button className="btn btn-outline-secondary" onClick={() => setEditOpen(false)} disabled={busy}>
              Cancelar
            </button>
            <button type="submit" form="plan-edit-form" className="btn btn-primary" disabled={busy}>
              Salvar
            </button>
          </>
        }
      >
        <form id="plan-edit-form" onSubmit={saveEdit} noValidate>
          {formError && <div className="alert alert-danger py-2">{formError}</div>}
          <div className="mb-3">
            <label htmlFor="edit-title" className="form-label">Título</label>
            <input
              id="edit-title"
              className="form-control"
              value={form.title}
              onChange={(e) => setForm({ ...form, title: e.target.value })}
            />
          </div>
          <div className="row g-3 mb-3">
            <div className="col-4">
              <label htmlFor="edit-discount" className="form-label">Desconto (R$)</label>
              <input
                id="edit-discount"
                inputMode="decimal"
                className="form-control"
                value={form.discount}
                onChange={(e) => setForm({ ...form, discount: e.target.value })}
              />
            </div>
            <div className="col-4">
              <label htmlFor="edit-installments" className="form-label">Parcelas</label>
              <select
                id="edit-installments"
                className="form-select"
                value={form.installments}
                onChange={(e) => setForm({ ...form, installments: Number(e.target.value) })}
              >
                {Array.from({ length: 12 }, (_, i) => i + 1).map((n) => (
                  <option key={n} value={n}>
                    {n === 1 ? 'À vista' : `${n}x`}
                  </option>
                ))}
              </select>
            </div>
            <div className="col-4">
              <label htmlFor="edit-valid" className="form-label">Validade</label>
              <input
                id="edit-valid"
                type="date"
                className="form-control"
                value={form.validUntil}
                onChange={(e) => setForm({ ...form, validUntil: e.target.value })}
              />
            </div>
          </div>
          <label htmlFor="edit-notes" className="form-label">Observações para o paciente</label>
          <textarea
            id="edit-notes"
            className="form-control"
            rows={3}
            value={form.notes}
            onChange={(e) => setForm({ ...form, notes: e.target.value })}
          />
        </form>
      </Modal>
    </>
  );
}
