/**
 * MandateInfoPanel — inline-editable mandate + billing summary (left expand panel).
 */

import React, { useState, useEffect, useMemo, useCallback } from 'react';
import type { Mandate } from '../../hooks/useMandates';
import { useMandateFormAttributes } from '../../hooks/useMandates';
import { useApiRequest } from '../../hooks/useApi';
import { fetchSettingsAdmin, updateSettingsAdmin, type BillingSettingsUpdate } from '../../api/billingApi';
import {
  mergeBillingIntoMandateFormData,
  getMandateBillingFormAttributes,
  MANDATE_INVOICE_FIELD_NAMES,
  formatMandateInvoiceAddress,
  isMandateBillingField,
  mandateBillingFieldNames,
} from '../../utils/mandateBillingFormMerge';
import { InlineEditableField, type InlineFieldType } from './InlineEditableField';
import { useToast } from '../../contexts/ToastContext';
import styles from './MandateInfoPanel.module.css';

import { useLanguage } from '../../providers/language/LanguageContext';
import { mandateDisplayLabel } from '../../utils/mandateDisplayUtils';
import { getUserDataCache } from '../../utils/userCache';

const STAMMDATEN_FIELDS = ['name', 'label', 'enabled', 'isSystem', 'mfaRequired'] as const;

const FIELD_TYPES: Record<string, InlineFieldType> = {
  name: 'text',
  label: 'text',
  enabled: 'boolean',
  isSystem: 'boolean',
  mfaRequired: 'boolean',
  warningThresholdPercent: 'number',
  notifyOnWarning: 'boolean',
  notifyEmails: 'textarea',
  invoiceEmail: 'email',
};

const MANDATE_ADMIN_EDITABLE = new Set(['label', 'warningThresholdPercent', 'notifyOnWarning', 'notifyEmails']);

export interface MandateInfoPanelProps {
  mandateId: string;
  mandateLabel?: string;
  canUpdate: boolean;
  fetchMandateById: (id: string) => Promise<Mandate | null>;
  handleUpdate: (mandateId: string, updateData: Partial<Mandate>) => Promise<boolean>;
  onMandateUpdated?: () => void;
  refreshKey?: number;
}

function isFieldEditable(
  fieldName: string,
  canUpdate: boolean,
  isPlatformAdmin: boolean,
  isSystemMandate: boolean,
): boolean {
  if (!canUpdate) return false;
  if (fieldName === 'isSystem') return false;
  if (isSystemMandate && fieldName === 'name') return false;
  if (!isPlatformAdmin) {
    return MANDATE_ADMIN_EDITABLE.has(fieldName);
  }
  return fieldName !== 'isSystem' && fieldName !== 'id' && fieldName !== 'deletedAt';
}

function InfoSection({
  title,
  children,
}: {
  title: string;
  children: React.ReactNode;
}) {
  return (
    <section className={styles.section}>
      <h4 className={styles.sectionTitle}>{title}</h4>
      {children}
    </section>
  );
}

export const MandateInfoPanel: React.FC<MandateInfoPanelProps> = ({
  mandateId,
  mandateLabel,
  canUpdate,
  fetchMandateById,
  handleUpdate,
  onMandateUpdated,
  refreshKey = 0,
}) => {
  const { t } = useLanguage();
  const { request } = useApiRequest();
  const { showError, showWarning } = useToast();
  const { formAttributes } = useMandateFormAttributes();
  const isPlatformAdmin = getUserDataCache()?.isPlatformAdmin === true;

  const [data, setData] = useState<Record<string, unknown> | null>(null);
  const [loading, setLoading] = useState(true);
  const [billingWarning, setBillingWarning] = useState<string | null>(null);
  const [savingField, setSavingField] = useState<string | null>(null);
  const [editingAddress, setEditingAddress] = useState(false);

  const labelMap = useMemo(() => {
    const map = new Map<string, string>();
    for (const attr of formAttributes) {
      map.set(attr.name, attr.label || attr.name);
    }
    for (const attr of getMandateBillingFormAttributes()) {
      map.set(attr.name, attr.label || attr.name);
    }
    return map;
  }, [formAttributes]);

  const loadDetail = useCallback(async () => {
    setLoading(true);
    setBillingWarning(null);
    try {
      const fullMandate = await fetchMandateById(mandateId);
      if (!fullMandate) {
        setData(null);
        return;
      }
      try {
        const settings = await fetchSettingsAdmin(request, mandateId);
        setData(mergeBillingIntoMandateFormData(fullMandate as Record<string, unknown>, settings));
      } catch {
        setData(mergeBillingIntoMandateFormData(fullMandate as Record<string, unknown>, null));
        setBillingWarning(t('Abrechnungseinstellungen konnten nicht geladen werden.'));
      }
    } finally {
      setLoading(false);
    }
  }, [mandateId, fetchMandateById, request, t]);

  useEffect(() => {
    void loadDetail();
  }, [loadDetail, refreshKey]);

  const isSystemMandate = Boolean(data?.isSystem);

  const canEditInvoice = isPlatformAdmin && canUpdate;

  const saveField = useCallback(
    async (fieldName: string, newValue: unknown) => {
      setSavingField(fieldName);
      try {
        if (isMandateBillingField(fieldName)) {
          const billingUpdate: BillingSettingsUpdate = {};
          if (fieldName === 'warningThresholdPercent') {
            const n = Number(newValue);
            if (Number.isNaN(n)) {
              showError(t('Fehler'), t('Ungültiger Wert'));
              return;
            }
            billingUpdate.warningThresholdPercent = n;
          } else if (fieldName === 'notifyOnWarning') {
            billingUpdate.notifyOnWarning = Boolean(newValue);
          } else if (fieldName === 'notifyEmails') {
            const emails =
              typeof newValue === 'string'
                ? newValue.split(/[\n,;]+/).map((s) => s.trim()).filter(Boolean)
                : [];
            billingUpdate.notifyEmails = emails;
          }
          await updateSettingsAdmin(request, mandateId, billingUpdate);
        } else {
          const ok = await handleUpdate(mandateId, { [fieldName]: newValue } as Partial<Mandate>);
          if (!ok) {
            showWarning(t('Fehler'), t('Speichern fehlgeschlagen.'));
            await loadDetail();
            return;
          }
        }
        setData((prev) => (prev ? { ...prev, [fieldName]: newValue } : prev));
        onMandateUpdated?.();
      } catch (e: unknown) {
        console.error(e);
        showError(t('Fehler'), t('Speichern fehlgeschlagen.'));
        await loadDetail();
      } finally {
        setSavingField(null);
      }
    },
    [mandateId, request, handleUpdate, loadDetail, onMandateUpdated, showError, showWarning, t],
  );

  const displayTitle =
    mandateLabel ||
    (data
      ? mandateDisplayLabel({
          label: data.label as string | undefined,
          name: data.name as string | undefined,
          id: mandateId,
        })
      : mandateId);

  const formattedAddress = data ? formatMandateInvoiceAddress(data) : null;

  if (loading) {
    return (
      <div className={styles.loadingWrap}>
        <div className={styles.spinner} />
        <span>{t('Laden…')}</span>
      </div>
    );
  }

  if (!data) {
    return (
      <div className={styles.loadingWrap}>
        <span>{t('Mandant konnte nicht geladen werden.')}</span>
      </div>
    );
  }

  return (
    <div className={styles.panelInner}>
      <div className={styles.header}>
        <div>
          <h3 className={styles.headerTitle}>{t('Mandant')}</h3>
          <p className={styles.headerSubtitle}>{displayTitle}</p>
        </div>
      </div>

      {billingWarning && <div className={styles.billingWarning}>{billingWarning}</div>}

      {Boolean(data.isSystem) && (
        <div className={styles.systemHint}>
          <strong>{t('System-Mandant')}</strong> — {t('Kurzzeichen ist schreibgeschützt.')}
        </div>
      )}

      <InfoSection title={t('Stammdaten')}>
        <dl className={styles.fieldGrid}>
          {STAMMDATEN_FIELDS.map((fieldName) => (
            <InlineEditableField
              key={fieldName}
              t={t}
              label={labelMap.get(fieldName) || fieldName}
              value={data[fieldName]}
              fieldKey={fieldName}
              type={FIELD_TYPES[fieldName] ?? 'text'}
              editable={isFieldEditable(fieldName, canUpdate, isPlatformAdmin, isSystemMandate)}
              saving={savingField === fieldName}
              onSave={saveField}
            />
          ))}
        </dl>
      </InfoSection>

      <InfoSection title={t('Rechnungsadresse')}>
        {editingAddress && canEditInvoice ? (
          <div className={styles.addressEditBox}>
            <dl className={styles.fieldGrid}>
              {MANDATE_INVOICE_FIELD_NAMES.map((fieldName) => (
                <InlineEditableField
                  key={fieldName}
                  t={t}
                  label={labelMap.get(fieldName) || fieldName}
                  value={data[fieldName]}
                  fieldKey={fieldName}
                  type={FIELD_TYPES[fieldName] ?? 'text'}
                  editable
                  saving={savingField === fieldName}
                  onSave={saveField}
                />
              ))}
            </dl>
            <button
              type="button"
              className={styles.addressDoneBtn}
              onClick={(e) => {
                e.stopPropagation();
                setEditingAddress(false);
              }}
            >
              {t('Fertig')}
            </button>
          </div>
        ) : (
          <div
            role={canEditInvoice ? 'button' : undefined}
            tabIndex={canEditInvoice ? 0 : undefined}
            className={`${styles.addressBlock} ${canEditInvoice ? styles.editableValue : ''}`}
            onClick={(e) => {
              e.stopPropagation();
              if (canEditInvoice) setEditingAddress(true);
            }}
            onKeyDown={(e) => {
              if (canEditInvoice && (e.key === 'Enter' || e.key === ' ')) {
                e.preventDefault();
                setEditingAddress(true);
              }
            }}
            title={canEditInvoice ? t('Klicken zum Bearbeiten') : undefined}
          >
            {formattedAddress ? (
              <pre className={styles.addressPre}>{formattedAddress}</pre>
            ) : (
              <span className={styles.fieldValueMuted}>
                {canEditInvoice ? t('Klicken, um Adresse zu erfassen') : '—'}
              </span>
            )}
          </div>
        )}
      </InfoSection>

      <InfoSection title={t('Abrechnung')}>
        <dl className={styles.fieldGrid}>
          {mandateBillingFieldNames.map((fieldName) => (
            <InlineEditableField
              key={fieldName}
              t={t}
              label={labelMap.get(fieldName) || fieldName}
              value={data[fieldName]}
              fieldKey={fieldName}
              type={FIELD_TYPES[fieldName] ?? 'text'}
              editable={isFieldEditable(fieldName, canUpdate, isPlatformAdmin, isSystemMandate)}
              saving={savingField === fieldName}
              onSave={saveField}
            />
          ))}
        </dl>
      </InfoSection>
    </div>
  );
};

export default MandateInfoPanel;
