import { useEffect, useMemo, useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { Loader2 } from 'lucide-react';
import toast from 'react-hot-toast';
import Modal from '../ui/Modal';
import Button from '../ui/Button';
import { contractApi, EmailAttachment } from '../../services/api';
import { formatDate } from '../../utils/dateFormat';
import {
  bankCardAttachmentName,
  identityDocAttachmentName,
  serverFileToAttachment,
  totalAttachmentBytes,
} from './composeAttachmentHelpers';
import type { Contract, Address, BankCard, IdentityDocument } from '../../types';

interface Props {
  isOpen: boolean;
  onClose: () => void;
  contractId: number;
  /**
   * E-Mail-Adresse des Postfachs, von dem die Mail abgeschickt wird.
   * Wird in der "Anrede & Name"-Section als Alternative zur Stammdaten-
   * E-Mail angeboten – User-Wunsch 2026-06-21: bei Kundendaten wählen,
   * ob die Customer-Email oder die Stressfrei-Wechseln-Absender-Adresse
   * eingefügt wird.
   */
  senderEmail: string;
  currentBody: string;
  currentAttachments: EmailAttachment[];
  onResult: (newBody: string, addedAttachments: EmailAttachment[]) => void;
}

type EmailChoice = 'master' | 'sender' | 'none';

const MAX_TOTAL_SIZE = 25 * 1024 * 1024;

type SectionKey =
  | 'customer'
  | 'deliveryAddress'
  | 'billingAddress'
  | 'contract';

export default function InsertCustomerDataModal({
  isOpen,
  onClose,
  contractId,
  senderEmail,
  currentBody,
  currentAttachments,
  onResult,
}: Props) {
  const { data, isLoading } = useQuery({
    queryKey: ['contract', contractId, 'for-insert-data'],
    queryFn: () => contractApi.getById(contractId),
    enabled: isOpen,
  });

  const contract = data?.data;
  const customer = contract?.customer;
  const deliveryAddress = contract?.address;
  // Rechnungsadresse nur eigenständig zeigen, wenn sie sich tatsächlich
  // von der Lieferadresse unterscheidet – sonst doppelt im Text.
  const billingAddress = useMemo(() => {
    if (!contract?.billingAddress) return undefined;
    if (!deliveryAddress) return contract.billingAddress;
    return contract.billingAddress.id !== deliveryAddress.id ? contract.billingAddress : undefined;
  }, [contract?.billingAddress, deliveryAddress]);

  const bankCard = contract?.bankCard;
  const identityDocument = contract?.identityDocument;

  // Sections die default-an sind: Anrede + Vertragsdaten. Anhang-/Text-
  // Schalter für Bank + Ausweis bleiben default-aus (User-Intent: bewusst
  // entscheiden, was vertraulich verschickt wird).
  const [checked, setChecked] = useState<Record<SectionKey, boolean>>({
    customer: true,
    deliveryAddress: true,
    billingAddress: false,
    contract: true,
  });
  // Bank: zwei unabhängige Schalter. Text fügt nur die letzten 4 IBAN-
  // Stellen ein (kein vollständiger IBAN-Versand per Mail = Default-Hygiene).
  const [insertBankText, setInsertBankText] = useState(false);
  const [attachBankPdf, setAttachBankPdf] = useState(false);
  // Ausweis: Text-Schalter fügt nur die Ausweisnummer ein, kein Geburtsdatum
  // / keine Ausstellungsdaten – falls der Empfänger nur die Nummer braucht.
  const [insertIdentityText, setInsertIdentityText] = useState(false);
  const [attachIdentityPdf, setAttachIdentityPdf] = useState(false);
  // Welche E-Mail-Adresse in der Customer-Section steht:
  // - 'master' = Stammdaten-E-Mail (customer.email)
  // - 'sender' = Postfach-Adresse, von der die Mail abgeht (Stressfrei)
  // - 'none'   = E-Mail-Zeile weglassen
  const [emailChoice, setEmailChoice] = useState<EmailChoice>('master');
  const [busy, setBusy] = useState(false);

  // Bei jedem Öffnen sinnvoll vorbelegen (sonst bleiben "checked" stale
  // wenn das Modal mal mit anderen Daten wieder aufgeht).
  useEffect(() => {
    if (isOpen && contract) {
      setChecked({
        customer: !!customer,
        deliveryAddress: !!deliveryAddress,
        billingAddress: false, // nur wenn vorhanden, aber default aus
        contract: true,
      });
      setInsertBankText(false);
      setAttachBankPdf(false);
      setInsertIdentityText(false);
      setAttachIdentityPdf(false);
      // Default: Stammdaten-E-Mail wenn vorhanden, sonst Absender-Adresse.
      setEmailChoice(customer?.email ? 'master' : 'sender');
    }
  }, [isOpen, contract, customer, deliveryAddress]);

  const toggle = (key: SectionKey) => {
    setChecked((prev) => ({ ...prev, [key]: !prev[key] }));
  };

  const handleClose = () => {
    if (busy) return;
    onClose();
  };

  const handleConfirm = async () => {
    if (!contract) return;
    setBusy(true);
    try {
      const blocks: string[] = [];

      if (checked.customer && customer) {
        const chosenEmail =
          emailChoice === 'master'
            ? customer.email || ''
            : emailChoice === 'sender'
              ? senderEmail
              : '';
        blocks.push(formatCustomerBlock(customer, contract, chosenEmail));
      }
      if (checked.deliveryAddress && deliveryAddress) {
        blocks.push(formatAddressBlock('Lieferadresse', deliveryAddress));
      }
      if (checked.billingAddress && billingAddress) {
        blocks.push(formatAddressBlock('Rechnungsadresse', billingAddress));
      }
      if (checked.contract) {
        blocks.push(formatContractBlock(contract));
      }
      if (insertBankText && bankCard) {
        blocks.push(formatBankBlock(bankCard));
      }
      if (insertIdentityText && identityDocument) {
        blocks.push(formatIdentityBlock(identityDocument));
      }

      const textToInsert = blocks
        .filter((b) => b.trim().length > 0)
        .join('\n\n');

      // Anhänge sammeln
      const newAttachments: EmailAttachment[] = [];
      let runningSize = totalAttachmentBytes(currentAttachments);

      const tryAttach = async (
        documentPath: string | undefined,
        filename: string,
      ): Promise<boolean> => {
        if (!documentPath) return false;
        try {
          const att = await serverFileToAttachment(documentPath, filename);
          const approxBytes = Math.ceil(att.content.length * 0.75);
          if (runningSize + approxBytes > MAX_TOTAL_SIZE) {
            toast.error(`"${filename}" gesprengt das 25-MB-Anhang-Limit.`);
            return false;
          }
          newAttachments.push(att);
          runningSize += approxBytes;
          return true;
        } catch (err: any) {
          toast.error(err?.message || `Fehler beim Anhängen von "${filename}"`);
          return false;
        }
      };

      if (attachBankPdf && bankCard?.documentPath) {
        await tryAttach(
          bankCard.documentPath,
          bankCardAttachmentName(bankCard.iban),
        );
      }
      if (attachIdentityPdf && identityDocument?.documentPath) {
        await tryAttach(
          identityDocument.documentPath,
          identityDocAttachmentName(
            identityDocument.type,
            identityDocument.documentNumber,
          ),
        );
      }

      const separator = currentBody && !currentBody.endsWith('\n') ? '\n\n' : '';
      const newBody = textToInsert
        ? currentBody + separator + textToInsert
        : currentBody;

      onResult(newBody, newAttachments);
      onClose();
    } finally {
      setBusy(false);
    }
  };

  const nothingSelected =
    !checked.customer &&
    !checked.deliveryAddress &&
    !checked.billingAddress &&
    !checked.contract &&
    !insertBankText &&
    !attachBankPdf &&
    !insertIdentityText &&
    !attachIdentityPdf;

  return (
    <Modal
      isOpen={isOpen}
      onClose={handleClose}
      title="Kundendaten einfügen"
      size="lg"
    >
      <div className="space-y-4">
        {isLoading || !contract ? (
          <div className="flex items-center justify-center py-8 text-gray-500">
            <Loader2 className="w-5 h-5 mr-2 animate-spin" />
            Daten werden geladen…
          </div>
        ) : (
          <div className="space-y-3 max-h-96 overflow-y-auto">
            {customer && (
              <SectionRow
                title="Anrede & Name"
                checked={checked.customer}
                onToggle={() => toggle('customer')}
                preview={previewCustomer(customer, contract)}
                extra={
                  checked.customer && (
                    <div className="mt-2 ml-6 space-y-1">
                      <div className="text-xs font-medium text-gray-600">
                        E-Mail im Text:
                      </div>
                      <label className="flex items-center gap-2 text-xs text-gray-700 cursor-pointer">
                        <input
                          type="radio"
                          name="emailChoice"
                          checked={emailChoice === 'master'}
                          onChange={() => setEmailChoice('master')}
                          disabled={!customer.email}
                          className="text-blue-600"
                        />
                        <span>
                          Stammdaten-E-Mail
                          {customer.email ? (
                            <span className="text-gray-400"> ({customer.email})</span>
                          ) : (
                            <span className="text-gray-400"> (nicht hinterlegt)</span>
                          )}
                        </span>
                      </label>
                      <label className="flex items-center gap-2 text-xs text-gray-700 cursor-pointer">
                        <input
                          type="radio"
                          name="emailChoice"
                          checked={emailChoice === 'sender'}
                          onChange={() => setEmailChoice('sender')}
                          className="text-blue-600"
                        />
                        <span>
                          Absender-Adresse
                          <span className="text-gray-400"> ({senderEmail})</span>
                        </span>
                      </label>
                      <label className="flex items-center gap-2 text-xs text-gray-700 cursor-pointer">
                        <input
                          type="radio"
                          name="emailChoice"
                          checked={emailChoice === 'none'}
                          onChange={() => setEmailChoice('none')}
                          className="text-blue-600"
                        />
                        <span>Keine E-Mail einfügen</span>
                      </label>
                    </div>
                  )
                }
              />
            )}
            {deliveryAddress && (
              <SectionRow
                title="Lieferadresse"
                checked={checked.deliveryAddress}
                onToggle={() => toggle('deliveryAddress')}
                preview={previewAddress(deliveryAddress)}
              />
            )}
            {billingAddress && (
              <SectionRow
                title="Rechnungsadresse"
                checked={checked.billingAddress}
                onToggle={() => toggle('billingAddress')}
                preview={previewAddress(billingAddress)}
              />
            )}
            <SectionRow
              title="Vertragsdaten"
              checked={checked.contract}
              onToggle={() => toggle('contract')}
              preview={previewContract(contract)}
            />
            {bankCard && (
              <DualChoiceRow
                title="Bankverbindung"
                preview={previewBank(bankCard)}
                textChecked={insertBankText}
                onToggleText={() => setInsertBankText((v) => !v)}
                textLabel="Letzte 4 IBAN-Stellen einfügen"
                textDisabled={!lastFourIban(bankCard.iban)}
                pdfChecked={attachBankPdf}
                onTogglePdf={() => setAttachBankPdf((v) => !v)}
                pdfLabel="Bankkarte als PDF anhängen"
                pdfDisabled={!bankCard.documentPath}
              />
            )}
            {identityDocument && (
              <DualChoiceRow
                title={identityTypeLabel(identityDocument.type)}
                preview={previewIdentity(identityDocument)}
                textChecked={insertIdentityText}
                onToggleText={() => setInsertIdentityText((v) => !v)}
                textLabel={`${identityTypeLabel(identityDocument.type)}-Nummer einfügen`}
                textDisabled={!identityDocument.documentNumber}
                pdfChecked={attachIdentityPdf}
                onTogglePdf={() => setAttachIdentityPdf((v) => !v)}
                pdfLabel={`${identityTypeLabel(identityDocument.type)} als PDF anhängen`}
                pdfDisabled={!identityDocument.documentPath}
              />
            )}

            {/* Falls weder Customer noch Address etc. da sind */}
            {!customer && !deliveryAddress && !bankCard && !identityDocument && (
              <p className="text-sm text-gray-500 text-center py-4">
                Keine weiteren Daten am Kunden hinterlegt.
              </p>
            )}
          </div>
        )}

        <div className="flex justify-between items-center pt-4 border-t border-gray-200">
          <span className="text-xs text-gray-500">
            Text wird ans Ende der Nachricht angehängt.
          </span>
          <div className="flex gap-3">
            <Button variant="secondary" onClick={handleClose} disabled={busy}>
              Abbrechen
            </Button>
            <Button
              onClick={handleConfirm}
              disabled={busy || isLoading || nothingSelected}
            >
              {busy ? (
                <>
                  <Loader2 className="w-4 h-4 mr-2 animate-spin" />
                  Einfügen…
                </>
              ) : (
                'Einfügen'
              )}
            </Button>
          </div>
        </div>
      </div>
    </Modal>
  );
}

// ==================== UI-Helper ====================

interface SectionRowProps {
  title: string;
  checked: boolean;
  onToggle: () => void;
  preview: string;
  extra?: React.ReactNode;
}

interface DualChoiceRowProps {
  title: string;
  preview: string;
  textChecked: boolean;
  onToggleText: () => void;
  textLabel: string;
  textDisabled?: boolean;
  pdfChecked: boolean;
  onTogglePdf: () => void;
  pdfLabel: string;
  pdfDisabled?: boolean;
}

/**
 * Sections, die unabhängig Text und PDF anbieten (Bank, Ausweis).
 * Keine primäre Checkbox – beide Schalter wirken einzeln, deshalb
 * kein "alle-ein/alle-aus" auf Section-Ebene nötig.
 */
function DualChoiceRow({
  title,
  preview,
  textChecked,
  onToggleText,
  textLabel,
  textDisabled,
  pdfChecked,
  onTogglePdf,
  pdfLabel,
  pdfDisabled,
}: DualChoiceRowProps) {
  return (
    <div className="border border-gray-200 rounded-lg p-3">
      <div className="text-sm font-medium text-gray-700">{title}</div>
      <div className="text-xs text-gray-500 mt-1">{preview}</div>
      <div className="mt-2 space-y-1">
        <label className={`flex items-center gap-2 text-xs cursor-pointer ${textDisabled ? 'text-gray-400 cursor-not-allowed' : 'text-gray-700'}`}>
          <input
            type="checkbox"
            checked={textChecked}
            onChange={onToggleText}
            disabled={textDisabled}
            className="rounded"
          />
          <span>{textLabel}</span>
        </label>
        <label className={`flex items-center gap-2 text-xs cursor-pointer ${pdfDisabled ? 'text-gray-400 cursor-not-allowed' : 'text-gray-700'}`}>
          <input
            type="checkbox"
            checked={pdfChecked}
            onChange={onTogglePdf}
            disabled={pdfDisabled}
            className="rounded"
          />
          <span>
            {pdfLabel}
            {pdfDisabled && <span className="ml-1">(keine PDF hinterlegt)</span>}
          </span>
        </label>
      </div>
    </div>
  );
}

function SectionRow({ title, checked, onToggle, preview, extra }: SectionRowProps) {
  return (
    <div className="border border-gray-200 rounded-lg p-3">
      <label className="flex items-start gap-2 cursor-pointer">
        <input
          type="checkbox"
          checked={checked}
          onChange={onToggle}
          className="mt-1 rounded"
        />
        <div className="flex-1 min-w-0">
          <div className="text-sm font-medium text-gray-700">{title}</div>
          <pre className="text-xs text-gray-500 mt-1 whitespace-pre-wrap font-sans">
            {preview}
          </pre>
        </div>
      </label>
      {extra}
    </div>
  );
}

// ==================== Text-Block-Formatierung ====================

function fullName(
  customer: { salutation?: string; firstName: string; lastName: string; companyName?: string },
  contractType: string,
): string {
  if (contractType === 'BUSINESS' && customer.companyName) {
    return customer.companyName;
  }
  const parts: string[] = [];
  if (customer.salutation) parts.push(customer.salutation);
  parts.push(customer.firstName);
  parts.push(customer.lastName);
  return parts.filter(Boolean).join(' ');
}

// User-Wunsch 2026-06-21: das Modal ist für Mails AN den Anbieter gedacht.
// Die interne CRM-Kundennummer / -Vertragsnummer interessiert dort
// niemanden – relevant ist nur, was der Anbieter selbst vergeben hat
// (`customerNumberAtProvider`, `contractNumberAtProvider`). Wir blenden
// die internen Nummern komplett aus.
function formatCustomerBlock(
  customer: NonNullable<Contract['customer']>,
  contract: Contract,
  email: string,
): string {
  const lines: string[] = ['Kundendaten:'];
  lines.push(fullName(customer, contract.type));
  if (contract.customerNumberAtProvider) {
    lines.push(`Kundennummer beim Anbieter: ${contract.customerNumberAtProvider}`);
  }
  if (customer.birthDate) lines.push(`Geburtsdatum: ${formatDate(customer.birthDate)}`);
  if (email) lines.push(`E-Mail: ${email}`);
  if (customer.phone) lines.push(`Telefon: ${customer.phone}`);
  if (customer.mobile) lines.push(`Mobil: ${customer.mobile}`);
  return lines.join('\n');
}

function previewCustomer(customer: NonNullable<Contract['customer']>, contract: Contract): string {
  return [
    fullName(customer, contract.type),
    contract.customerNumberAtProvider
      ? `Anbieter-Kdnr.: ${contract.customerNumberAtProvider}`
      : '',
  ]
    .filter(Boolean)
    .join(' · ');
}

function formatAddressBlock(label: string, addr: Address): string {
  const lines: string[] = [`${label}:`];
  lines.push(`${addr.street} ${addr.houseNumber}`);
  lines.push(`${addr.postalCode} ${addr.city}`);
  if (addr.country && addr.country.toLowerCase() !== 'deutschland' && addr.country !== 'DE') {
    lines.push(addr.country);
  }
  return lines.join('\n');
}

function previewAddress(addr: Address): string {
  return `${addr.street} ${addr.houseNumber}, ${addr.postalCode} ${addr.city}`;
}

// Interne `contractNumber` raus (User-Wunsch 2026-06-21): für eine Mail
// an den Provider zählt nur die Vertragsnummer, die der Provider selbst
// vergeben hat. Vertriebsplattform-Nummern bleiben drin – die nutzt der
// CRM-Mitarbeiter teilweise auch für die Plattform-Korrespondenz.
function formatContractBlock(c: Contract): string {
  const lines: string[] = ['Vertragsdaten:'];
  if (c.provider?.name) lines.push(`Anbieter: ${c.provider.name}`);
  if (c.tariff?.name) lines.push(`Tarif: ${c.tariff.name}`);
  if (c.customerNumberAtProvider) lines.push(`Kundennummer beim Anbieter: ${c.customerNumberAtProvider}`);
  if (c.contractNumberAtProvider) lines.push(`Vertragsnummer beim Anbieter: ${c.contractNumberAtProvider}`);
  if (c.orderNumberAtSalesPlatform) lines.push(`Auftragsnummer Vertriebsplattform: ${c.orderNumberAtSalesPlatform}`);
  if (c.customerNumberAtSalesPlatform) lines.push(`Kundennummer Vertriebsplattform: ${c.customerNumberAtSalesPlatform}`);
  if (c.contractNumberAtSalesPlatform) lines.push(`Vertragsnummer Vertriebsplattform: ${c.contractNumberAtSalesPlatform}`);
  if (c.startDate) lines.push(`Vertragsbeginn: ${formatDate(c.startDate)}`);
  if (c.endDate) lines.push(`Vertragsende: ${formatDate(c.endDate)}`);
  return lines.join('\n');
}

function previewContract(c: Contract): string {
  const parts: string[] = [];
  if (c.contractNumberAtProvider) {
    parts.push(`Anbieter-Vtr.: ${c.contractNumberAtProvider}`);
  } else if (c.provider?.name) {
    parts.push('(keine Anbieter-Vertragsnummer hinterlegt)');
  }
  if (c.provider?.name) parts.push(c.provider.name);
  if (c.tariff?.name) parts.push(c.tariff.name);
  return parts.join(' · ');
}

// User-Wunsch 2026-06-21: nur die letzten 4 IBAN-Stellen einfügen, nicht
// die komplette IBAN/BIC/Bank-Liste. Vollständige Kontonummern per Mail
// versenden ist sowieso heikel – der Empfänger kann sich mit den letzten
// 4 Stellen für Identifikationszwecke ausweisen, ohne dass die ganze
// IBAN im Mail-Verlauf hängenbleibt.
function lastFourIban(iban: string | undefined | null): string {
  if (!iban) return '';
  return iban.replace(/\s+/g, '').slice(-4);
}

function formatBankBlock(b: BankCard): string {
  const last4 = lastFourIban(b.iban);
  if (!last4) return '';
  return `Bankverbindung:\nIBAN endet auf: ${last4}`;
}

function previewBank(b: BankCard): string {
  const last4 = lastFourIban(b.iban);
  return last4 ? `IBAN …${last4}` : 'IBAN nicht hinterlegt';
}

function identityTypeLabel(type: IdentityDocument['type']): string {
  switch (type) {
    case 'PASSPORT': return 'Reisepass';
    case 'DRIVERS_LICENSE': return 'Führerschein';
    case 'OTHER': return 'Ausweisdokument';
    case 'ID_CARD':
    default: return 'Personalausweis';
  }
}

// User-Wunsch 2026-06-21: nur die Ausweisnummer einfügen, keine
// Behörde / Daten – wenn der Empfänger mehr Details braucht, soll er
// die beigefügte PDF benutzen.
function formatIdentityBlock(d: IdentityDocument): string {
  if (!d.documentNumber) return '';
  return `${identityTypeLabel(d.type)}-Nummer: ${d.documentNumber}`;
}

function previewIdentity(d: IdentityDocument): string {
  return d.documentNumber ? `Nr. ${d.documentNumber}` : 'Keine Nummer hinterlegt';
}
