import { useState, useRef } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { Plus, Edit, Trash2, Gift, Banknote, Package, Upload, Eye, X, Check, FileText } from 'lucide-react';
import toast from 'react-hot-toast';
import { formatDate } from '../../utils/dateFormat';
import { fileUrl } from '../../utils/fileUrl';
import Modal from '../ui/Modal';
import Button from '../ui/Button';
import Input from '../ui/Input';
import Select from '../ui/Select';
import Badge from '../ui/Badge';
import { creditNoteApi } from '../../services/api';
import type { CreditNote, CreditNoteType, CreditNoteCustomerType, CreditNoteAmountBasis, CreditNotePayoutBankCard } from '../../types';

const round2 = (n: number) => Math.round((n + Number.EPSILON) * 100) / 100;

function formatEuro(n: number, currency = 'EUR') {
  return new Intl.NumberFormat('de-DE', { style: 'currency', currency }).format(n || 0);
}

// Client-Vorschau der Beträge (der Server rechnet autoritativ nach).
function calcAmounts(amount: number, vatRelevant: boolean, basis: CreditNoteAmountBasis, rate: number) {
  const a = round2(amount || 0);
  if (!vatRelevant || rate <= 0) return { net: a, vat: 0, gross: a };
  const r = rate / 100;
  if (basis === 'NETTO') {
    const net = a;
    const vat = round2(net * r);
    return { net, vat, gross: round2(net + vat) };
  }
  const gross = a;
  const net = round2(gross / (1 + r));
  return { net, vat: round2(gross - net), gross };
}

const todayIso = () => new Date().toISOString().split('T')[0];

// Betragsloser Sachwert = Lieferschein → zeigt die Lieferscheinnummer,
// sonst die Gutschriftsnummer.
function displayNumber(cn: CreditNote): string {
  const nonMonetary = cn.type === 'SACHWERT' && cn.amountGross === 0;
  return (nonMonetary ? cn.deliveryNoteNumber : cn.number) ?? `#${cn.id}`;
}

interface FormDefaults {
  customerType: CreditNoteCustomerType;
  vatRelevant: boolean;
  bankCards: CreditNotePayoutBankCard[];
  contractBankCardId: number | null;
}

interface FormState {
  type: CreditNoteType;
  sachwertDescription: string;
  customerType: CreditNoteCustomerType;
  vatRelevant: boolean;
  amountBasis: CreditNoteAmountBasis;
  vatRate: string;
  amount: string;
  creditDate: string;
  place: string;
  signedAt: string;
  goodsReceived: boolean;
  payoutBankCardId: string;
  notes: string;
}

function emptyForm(defaults?: FormDefaults): FormState {
  return {
    type: 'GELD',
    sachwertDescription: '',
    customerType: defaults?.customerType ?? 'PRIVAT',
    vatRelevant: defaults?.vatRelevant ?? false,
    amountBasis: 'BRUTTO',
    vatRate: '19',
    amount: '',
    creditDate: todayIso(),
    place: '',
    signedAt: '',
    goodsReceived: false,
    // Vorschlag: das Abbuchkonto des Vertrags (kann umgestellt werden).
    payoutBankCardId: defaults?.contractBankCardId ? String(defaults.contractBankCardId) : '',
    notes: '',
  };
}

function formFromCreditNote(cn: CreditNote): FormState {
  return {
    type: cn.type,
    sachwertDescription: cn.sachwertDescription ?? '',
    customerType: cn.customerType,
    vatRelevant: cn.vatRelevant,
    amountBasis: cn.amountBasis,
    vatRate: String(cn.vatRate),
    // Beim Bearbeiten den Betrag auf der ursprünglichen Basis anzeigen.
    amount: String(cn.amountBasis === 'NETTO' ? cn.amountNet : cn.amountGross),
    creditDate: cn.creditDate ? cn.creditDate.split('T')[0] : todayIso(),
    place: cn.place ?? '',
    signedAt: cn.signedAt ? cn.signedAt.split('T')[0] : '',
    goodsReceived: cn.goodsReceived,
    payoutBankCardId: cn.payoutBankCardId ? String(cn.payoutBankCardId) : '',
    notes: cn.notes ?? '',
  };
}

// ---------- Formular-Modal ----------
function CreditNoteFormModal({
  contractId,
  editing,
  defaults,
  onClose,
  onSaved,
}: {
  contractId: number;
  editing: CreditNote | null;
  defaults?: FormDefaults;
  onClose: () => void;
  onSaved: () => void;
}) {
  const [form, setForm] = useState<FormState>(editing ? formFromCreditNote(editing) : emptyForm(defaults));
  const bankCards = defaults?.bankCards ?? [];
  const set = <K extends keyof FormState>(key: K, value: FormState[K]) => setForm((f) => ({ ...f, [key]: value }));

  const preview = calcAmounts(parseFloat(form.amount), form.vatRelevant, form.amountBasis, parseFloat(form.vatRate) || 0);

  const saveMutation = useMutation({
    mutationFn: () => {
      const payload = {
        type: form.type,
        sachwertDescription: form.type === 'SACHWERT' ? form.sachwertDescription : null,
        customerType: form.customerType,
        vatRelevant: form.vatRelevant,
        amountBasis: form.amountBasis,
        vatRate: Number(form.vatRate) || 0,
        amount: Number(form.amount) || 0,
        creditDate: form.creditDate,
        place: form.place || null,
        signedAt: form.signedAt || null,
        goodsReceived: form.type === 'SACHWERT' ? form.goodsReceived : false,
        payoutBankCardId: form.type === 'GELD' && form.payoutBankCardId ? Number(form.payoutBankCardId) : null,
        notes: form.notes || null,
      };
      return editing ? creditNoteApi.update(editing.id, payload) : creditNoteApi.create(contractId, payload);
    },
    onSuccess: () => {
      toast.success(editing ? 'Gutschrift gespeichert' : 'Gutschrift angelegt');
      onSaved();
    },
    onError: (err: Error) => toast.error(err.message || 'Speichern fehlgeschlagen'),
  });

  const amountNum = Number(form.amount) || 0;
  // Sachwert darf betragslos sein (reine Übergabe → keine Rechnung).
  const isSachwert = form.type === 'SACHWERT';
  const nonMonetary = isSachwert && amountNum <= 0;

  const amountLabel = isSachwert
    ? 'Wert (optional)'
    : form.vatRelevant
      ? `Betrag (${form.amountBasis === 'NETTO' ? 'netto' : 'brutto'})`
      : 'Betrag';

  const canSave = isSachwert
    ? form.sachwertDescription.trim().length > 0 // Betrag optional
    : amountNum > 0; // Geld: Betrag > 0 Pflicht

  return (
    <Modal isOpen onClose={onClose} title={editing ? `Beleg ${displayNumber(editing)} bearbeiten` : 'Gutschrift anlegen'} size="lg">
      <div className="space-y-4">
        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          <Select
            label="Art"
            value={form.type}
            onChange={(e) => set('type', e.target.value as CreditNoteType)}
            options={[
              { value: 'GELD', label: 'Geld (Überweisung, EUR)' },
              { value: 'SACHWERT', label: 'Sachwert (Smartphone, Elektro …)' },
            ]}
          />
          <Select
            label="Kundentyp"
            value={form.customerType}
            onChange={(e) => set('customerType', e.target.value as CreditNoteCustomerType)}
            options={[
              { value: 'PRIVAT', label: 'Privatkunde' },
              { value: 'FIRMA', label: 'Firmenkunde' },
            ]}
          />
        </div>

        {form.type === 'SACHWERT' && (
          <Input
            label="Was wird gewährt? (Sachwert)"
            value={form.sachwertDescription}
            onChange={(e) => set('sachwertDescription', e.target.value)}
            placeholder="z.B. Smartphone Samsung Galaxy A55"
          />
        )}

        {/* Betrag + USt-Block */}
        <div className="rounded-lg border border-gray-200 p-3 space-y-3 bg-gray-50">
          <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
            <Input
              label={amountLabel}
              type="number"
              step="0.01"
              value={form.amount}
              onChange={(e) => set('amount', e.target.value)}
              placeholder="0,00"
            />
            {amountNum > 0 && form.vatRelevant && (
              <>
                <Select
                  label="Basis"
                  value={form.amountBasis}
                  onChange={(e) => set('amountBasis', e.target.value as CreditNoteAmountBasis)}
                  options={[
                    { value: 'BRUTTO', label: 'Brutto (USt herausrechnen)' },
                    { value: 'NETTO', label: 'Netto (USt aufschlagen)' },
                  ]}
                />
                <Input
                  label="USt-Satz (%)"
                  type="number"
                  step="0.1"
                  value={form.vatRate}
                  onChange={(e) => set('vatRate', e.target.value)}
                />
              </>
            )}
          </div>

          {nonMonetary ? (
            <p className="text-sm text-gray-600">
              Ohne Betrag: reine Sachwert-Übergabe – <strong>keine Rechnung, keine USt</strong>. Es wird nur der Empfang des Gegenstands als Subvention dokumentiert.
            </p>
          ) : (
            <>
              <label className="flex items-center gap-2 text-sm font-medium">
                <input
                  type="checkbox"
                  checked={form.vatRelevant}
                  onChange={(e) => set('vatRelevant', e.target.checked)}
                  className="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500"
                />
                USt-relevant (mit Umsatzsteuer ausweisen)
              </label>
              <div className="flex flex-wrap gap-x-6 gap-y-1 text-sm">
                <span>Netto: <strong>{formatEuro(preview.net)}</strong></span>
                <span>USt: <strong>{formatEuro(preview.vat)}</strong></span>
                <span>Brutto: <strong>{formatEuro(preview.gross)}</strong></span>
              </div>
            </>
          )}
        </div>

        {form.type === 'GELD' && (
          bankCards.length > 0 ? (
            <Select
              label="Auszahlungskonto (Bankkonto des Kunden)"
              value={form.payoutBankCardId}
              onChange={(e) => set('payoutBankCardId', e.target.value)}
              options={bankCards.map((bc) => ({
                value: String(bc.id),
                label: `${bc.iban} (${bc.accountHolder})${bc.description ? ` – ${bc.description}` : ''}`,
              }))}
              placeholder="Kein Konto angeben"
            />
          ) : (
            <p className="text-xs text-gray-500">
              Für diesen Kunden sind keine Bankkonten hinterlegt – Auszahlungskonto kann daher nicht gewählt werden.
            </p>
          )
        )}

        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          <Input
            label="Datum der Gutschrift"
            type="date"
            value={form.creditDate}
            onChange={(e) => set('creditDate', e.target.value)}
          />
          {/* Ort/Unterschrift nur bei Sachwert – Überweisung wird nicht unterschrieben. */}
          {isSachwert && (
            <Input
              label="Ort (Unterschrift)"
              value={form.place}
              onChange={(e) => set('place', e.target.value)}
              placeholder="z.B. Oldenburg"
            />
          )}
        </div>

        {isSachwert && (
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <Input
              label="Unterschrift am (optional)"
              type="date"
              value={form.signedAt}
              onChange={(e) => set('signedAt', e.target.value)}
            />
            <label className="flex items-center gap-2 text-sm mt-7">
              <input
                type="checkbox"
                checked={form.goodsReceived}
                onChange={(e) => set('goodsReceived', e.target.checked)}
                className="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500"
              />
              Ware erhalten (Empfang bestätigt)
            </label>
          </div>
        )}

        <div>
          <label className="block text-sm font-medium text-gray-700 mb-1">Notiz (optional)</label>
          <textarea
            value={form.notes}
            onChange={(e) => set('notes', e.target.value)}
            rows={2}
            className="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
          />
        </div>

        {!editing && (
          <p className="text-xs text-gray-500">
            {isSachwert
              ? 'Das unterschriebene Dokument kann nach dem Speichern in der Liste hochgeladen werden.'
              : 'Der Überweisungsbeleg kann nach dem Speichern in der Liste hochgeladen werden.'}
          </p>
        )}

        <div className="flex justify-end gap-3 pt-2">
          <Button variant="secondary" onClick={onClose}>Abbrechen</Button>
          <Button onClick={() => saveMutation.mutate()} disabled={!canSave || saveMutation.isPending}>
            {saveMutation.isPending ? 'Speichern …' : 'Speichern'}
          </Button>
        </div>
      </div>
    </Modal>
  );
}

// ---------- Beleg-Upload (nur GELD) ----------
function ReceiptControls({ cn, canEdit, onChanged, label = 'Beleg' }: { cn: CreditNote; canEdit: boolean; onChanged: () => void; label?: string }) {
  const fileRef = useRef<HTMLInputElement>(null);
  const uploadMutation = useMutation({
    mutationFn: (file: File) => creditNoteApi.uploadReceipt(cn.id, file),
    onSuccess: () => { toast.success('Beleg hochgeladen'); onChanged(); },
    onError: (err: Error) => toast.error(err.message || 'Upload fehlgeschlagen'),
  });
  const removeMutation = useMutation({
    mutationFn: () => creditNoteApi.deleteReceipt(cn.id),
    onSuccess: () => { toast.success('Beleg entfernt'); onChanged(); },
    onError: (err: Error) => toast.error(err.message || 'Löschen fehlgeschlagen'),
  });

  if (cn.receiptPath) {
    return (
      <span className="inline-flex items-center gap-2 text-xs">
        <a href={fileUrl(cn.receiptPath, { inline: true })} target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:underline inline-flex items-center gap-1">
          <Eye className="w-3.5 h-3.5" /> {label}
        </a>
        {canEdit && (
          <button onClick={() => removeMutation.mutate()} className="text-gray-400 hover:text-red-600" title={`${label} entfernen`}>
            <X className="w-3.5 h-3.5" />
          </button>
        )}
      </span>
    );
  }
  if (!canEdit) return <span className="text-xs text-gray-400">kein {label}</span>;
  return (
    <>
      <input
        ref={fileRef}
        type="file"
        accept=".pdf,.jpg,.jpeg,.png"
        className="hidden"
        onChange={(e) => { const f = e.target.files?.[0]; if (f) uploadMutation.mutate(f); e.target.value = ''; }}
      />
      <button
        onClick={() => fileRef.current?.click()}
        disabled={uploadMutation.isPending}
        className="inline-flex items-center gap-1 text-xs text-blue-600 hover:text-blue-800"
      >
        <Upload className="w-3.5 h-3.5" /> {uploadMutation.isPending ? 'lädt …' : label}
      </button>
    </>
  );
}

// ---------- Section ----------
export default function CreditNotesSection({ contractId, canEdit }: { contractId: number; canEdit: boolean }) {
  const queryClient = useQueryClient();
  const [showForm, setShowForm] = useState(false);
  const [showNoAddress, setShowNoAddress] = useState(false);
  const [editing, setEditing] = useState<CreditNote | null>(null);

  const { data: listRes } = useQuery({
    queryKey: ['credit-notes', contractId],
    queryFn: () => creditNoteApi.listByContract(contractId),
  });
  const { data: defaultsRes } = useQuery({
    queryKey: ['credit-notes-defaults', contractId],
    queryFn: () => creditNoteApi.getDefaults(contractId),
  });

  const creditNotes = listRes?.data ?? [];
  const defaults = defaultsRes?.data;

  const refresh = () => queryClient.invalidateQueries({ queryKey: ['credit-notes', contractId] });

  const deleteMutation = useMutation({
    mutationFn: (id: number) => creditNoteApi.remove(id),
    onSuccess: () => { toast.success('Gutschrift gelöscht'); refresh(); },
    onError: (err: Error) => toast.error(err.message || 'Löschen fehlgeschlagen'),
  });

  const pdfMutation = useMutation({
    mutationFn: (id: number) => creditNoteApi.generatePdf(id),
    onSuccess: (res) => {
      toast.success('PDF erzeugt');
      refresh();
      if (res.data?.pdfPath) window.open(fileUrl(res.data.pdfPath, { inline: true }), '_blank', 'noopener');
    },
    onError: (err: Error) => toast.error(err.message || 'PDF fehlgeschlagen'),
  });

  const openCreate = () => {
    // Ohne Empfängeradresse (Rechnungs- ODER Lieferadresse) kein Beleg möglich.
    if (defaults && !defaults.hasRecipientAddress) {
      setShowNoAddress(true);
      return;
    }
    setEditing(null);
    setShowForm(true);
  };
  const openEdit = (cn: CreditNote) => { setEditing(cn); setShowForm(true); };

  const totalGross = creditNotes.reduce((sum, cn) => sum + (cn.amountGross || 0), 0);

  return (
    <div className="bg-white rounded-lg shadow p-6 mb-6">
      <div className="flex items-center justify-between mb-4">
        <h2 className="text-lg font-semibold flex items-center gap-2">
          <Gift className="w-5 h-5 text-gray-500" />
          Gutschriften
          {creditNotes.length > 0 && (
            <span className="text-sm font-normal text-gray-500">
              ({creditNotes.length} · Summe {formatEuro(totalGross)})
            </span>
          )}
        </h2>
        {canEdit && (
          <Button size="sm" onClick={openCreate}>
            <Plus className="w-4 h-4 mr-2" /> Gutschrift anlegen
          </Button>
        )}
      </div>

      {creditNotes.length === 0 ? (
        <p className="text-sm text-gray-400 italic">Noch keine Gutschriften.</p>
      ) : (
        <div className="divide-y">
          {creditNotes.map((cn) => (
            <div key={cn.id} className="py-3 flex items-start gap-3">
              <div className="mt-0.5 text-gray-400">
                {cn.type === 'GELD' ? <Banknote className="w-5 h-5" /> : <Package className="w-5 h-5" />}
              </div>
              <div className="flex-1 min-w-0">
                <div className="flex flex-wrap items-center gap-2">
                  <span className="font-mono text-sm font-medium">{displayNumber(cn)}</span>
                  <Badge variant={cn.type === 'GELD' ? 'info' : 'default'}>
                    {cn.type === 'GELD' ? 'Geld' : 'Sachwert'}
                  </Badge>
                  {!(cn.type === 'SACHWERT' && cn.amountGross === 0) && (
                    cn.vatRelevant ? (
                      <Badge variant="default">USt {cn.vatRate}%</Badge>
                    ) : (
                      <Badge variant="default">ohne USt</Badge>
                    )
                  )}
                  <Badge variant="default">{cn.customerType === 'FIRMA' ? 'Firma' : 'Privat'}</Badge>
                  {cn.type === 'SACHWERT' && cn.goodsReceived && (
                    <span className="inline-flex items-center gap-1 text-xs text-green-700">
                      <Check className="w-3.5 h-3.5" /> Ware erhalten
                    </span>
                  )}
                </div>
                <div className="text-sm text-gray-700 mt-1">
                  {cn.type === 'SACHWERT' && cn.amountGross === 0 ? (
                    <span className="italic text-gray-600">Sachwert ohne Betrag (keine Rechnung)</span>
                  ) : (
                    <>
                      <strong>{formatEuro(cn.amountGross, cn.currency)}</strong>
                      {cn.vatRelevant && (
                        <span className="text-gray-500"> (netto {formatEuro(cn.amountNet, cn.currency)} + USt {formatEuro(cn.amountVat, cn.currency)})</span>
                      )}
                    </>
                  )}
                  <span className="text-gray-500"> · {formatDate(cn.creditDate)}</span>
                  {cn.place && <span className="text-gray-500"> · {cn.place}</span>}
                </div>
                {cn.type === 'SACHWERT' && cn.sachwertDescription && (
                  <div className="text-sm text-gray-600 mt-0.5">{cn.sachwertDescription}</div>
                )}
                {cn.notes && <div className="text-xs text-gray-500 mt-0.5 italic">{cn.notes}</div>}
                {cn.type === 'GELD' && cn.payoutBankCardId && (() => {
                  const card = defaults?.bankCards.find((bc) => bc.id === cn.payoutBankCardId);
                  return card ? (
                    <div className="text-xs text-gray-500 mt-0.5">an Bankkonto: <span className="font-mono">{card.iban}</span> ({card.accountHolder})</div>
                  ) : null;
                })()}
                <div className="mt-1">
                  <ReceiptControls
                    cn={cn}
                    canEdit={canEdit}
                    onChanged={refresh}
                    label={cn.type === 'GELD' ? 'Überweisungsbeleg' : 'Unterschr. Dokument'}
                  />
                </div>
              </div>
              {canEdit && (
                <div className="flex items-center gap-1">
                  {cn.pdfPath ? (
                    <a href={fileUrl(cn.pdfPath, { inline: true })} target="_blank" rel="noopener noreferrer" className="text-gray-400 hover:text-blue-600 p-1" title="PDF (ZUGFeRD) ansehen">
                      <FileText className="w-4 h-4" />
                    </a>
                  ) : (
                    <button onClick={() => pdfMutation.mutate(cn.id)} disabled={pdfMutation.isPending} className="text-gray-400 hover:text-blue-600 p-1" title="PDF (ZUGFeRD) erzeugen">
                      <FileText className="w-4 h-4" />
                    </button>
                  )}
                  <button onClick={() => openEdit(cn)} className="text-gray-400 hover:text-blue-600 p-1" title="Bearbeiten">
                    <Edit className="w-4 h-4" />
                  </button>
                  <button
                    onClick={() => { if (confirm(`Beleg ${displayNumber(cn)} wirklich löschen?`)) deleteMutation.mutate(cn.id); }}
                    className="text-gray-400 hover:text-red-600 p-1"
                    title="Löschen"
                  >
                    <Trash2 className="w-4 h-4" />
                  </button>
                </div>
              )}
            </div>
          ))}
        </div>
      )}

      {showForm && (
        <CreditNoteFormModal
          contractId={contractId}
          editing={editing}
          defaults={defaults}
          onClose={() => setShowForm(false)}
          onSaved={() => { setShowForm(false); refresh(); }}
        />
      )}

      {showNoAddress && (
        <Modal isOpen onClose={() => setShowNoAddress(false)} title="Keine Adresse hinterlegt" size="sm">
          <div className="space-y-4">
            <p className="text-sm text-gray-700">
              Für diesen Vertrag ist weder eine Rechnungs- noch eine Lieferadresse hinterlegt.
              Ohne Empfängeradresse kann keine Gutschrift/kein Lieferschein erstellt werden.
              Bitte ordne dem Vertrag zuerst eine Adresse zu.
            </p>
            <div className="flex justify-end">
              <Button onClick={() => setShowNoAddress(false)}>OK</Button>
            </div>
          </div>
        </Modal>
      )}
    </div>
  );
}
