'use client';

import { useCallback, useEffect, useMemo, useState } from 'react';
import { api } from '@/lib/api-client';

interface PosStore {
  id: string;
  name: string;
  active: boolean;
}
interface PosTerminal {
  id: string;
  storeId: string;
  name: string;
  bindingCode: string | null;
  boundAt: string | null;
  status: string;
  settings?: {
    touchNavigationEnabled?: boolean;
    quickProductVariantIds?: Array<string | null>;
    lineDiscountsEnabled?: boolean;
    selfpayMode?: boolean;
    closeSessionRequiresPin?: boolean;
    closeSessionPin?: string;
  };
}
interface CatalogOption {
  variantId: string;
  name: string;
  sku: string;
  ean?: string | null;
  priceCents?: number;
}
interface PaymentMethod {
  id: string;
  storeId: string;
  code: string;
  label: string;
  kind: 'cash' | 'card' | 'other';
  active: boolean;
  sortOrder: number;
}
interface PosCashier {
  id: string;
  email: string;
  role: 'pos_cashier';
  active: boolean;
  deactivatedAt: string | null;
  deletedAt: string | null;
  createdAt: string;
  status: 'active' | 'inactive' | 'deleted';
}
interface ReceiptSettings {
  storeId: string;
  name: string;
  address: string;
  taxId: string;
  contactEmail: string;
  contactPhone: string;
  receiptHeader: string;
  receiptFooter: string;
  logoUrl: string;
  prefix: string;
  nextNumber: number;
  padding: number;
  returnPolicy: string;
}

const emptyReceipt: ReceiptSettings = {
  storeId: '',
  name: '',
  address: '',
  taxId: '',
  contactEmail: '',
  contactPhone: '',
  receiptHeader: '',
  receiptFooter: '',
  logoUrl: '',
  prefix: 'TPV',
  nextNumber: 1,
  padding: 6,
  returnPolicy: 'Se admiten devoluciones durante 15 días con el ticket de compra.',
};

const QUICK_PRODUCTS_MAX = 8;

export default function PosAdminPage() {
  const [stores, setStores] = useState<PosStore[]>([]);
  const [terminals, setTerminals] = useState<PosTerminal[]>([]);
  const [catalogOptions, setCatalogOptions] = useState<CatalogOption[]>([]);
  const [quickSearch, setQuickSearch] = useState('');
  const [quickSearchResults, setQuickSearchResults] = useState<CatalogOption[]>([]);
  const [quickSearchLoading, setQuickSearchLoading] = useState(false);
  const [storeId, setStoreId] = useState('');
  const [terminalName, setTerminalName] = useState('');
  const [loading, setLoading] = useState(true);
  const [creating, setCreating] = useState(false);
  const [error, setError] = useState('');
  const [newCode, setNewCode] = useState('');
  const [copied, setCopied] = useState('');
  const [configuring, setConfiguring] = useState<PosTerminal | null>(null);
  const [touchEnabled, setTouchEnabled] = useState(true);
  const [discountsEnabled, setDiscountsEnabled] = useState(true);
  const [quickSlots, setQuickSlots] = useState<Array<string | null>>(
    Array.from({ length: QUICK_PRODUCTS_MAX }, () => null),
  );
  const [savingTouch, setSavingTouch] = useState(false);
  const [touchMessage, setTouchMessage] = useState('');
  // F-203: cash close security settings
  const [selfpayMode, setSelfpayMode] = useState(false);
  const [closePinRequired, setClosePinRequired] = useState(false);
  const [closePinValue, setClosePinValue] = useState('');
  const [savingSecurity, setSavingSecurity] = useState(false);
  const [securityMessage, setSecurityMessage] = useState('');
  const [paymentMethods, setPaymentMethods] = useState<PaymentMethod[]>([]);
  const [cashiers, setCashiers] = useState<PosCashier[]>([]);
  const [newCashier, setNewCashier] = useState({ email: '', password: '' });
  const [savingCashier, setSavingCashier] = useState(false);
  const [cashierMessage, setCashierMessage] = useState('');
  const [newMethod, setNewMethod] = useState({
    code: '',
    label: '',
    kind: 'other' as PaymentMethod['kind'],
  });
  const [savingMethod, setSavingMethod] = useState(false);
  const [paymentMessage, setPaymentMessage] = useState('');
  const [receipt, setReceipt] = useState<ReceiptSettings>(emptyReceipt);
  const [savingReceipt, setSavingReceipt] = useState(false);
  const [receiptMessage, setReceiptMessage] = useState('');

  const mergeCatalogOptions = useCallback((items: CatalogOption[]) => {
    setCatalogOptions((current) => {
      const merged = new Map(current.map((item) => [item.variantId, item]));
      items.forEach((item) => merged.set(item.variantId, item));
      return Array.from(merged.values());
    });
  }, []);

  const catalogById = useMemo(
    () => new Map(catalogOptions.map((item) => [item.variantId, item])),
    [catalogOptions],
  );

  const fetchCatalogOptions = useCallback(
    async (params: { q?: string; limit?: number; variantIds?: string[] } = {}) => {
      const qs = new URLSearchParams();
      if (params.q?.trim()) qs.set('q', params.q.trim());
      if (params.limit) qs.set('limit', String(params.limit));
      if (params.variantIds?.length) qs.set('variantIds', params.variantIds.join(','));
      const suffix = qs.toString();
      return api.get<{ items: CatalogOption[] }>(
        `/api/pos/admin/catalog-products${suffix ? `?${suffix}` : ''}`,
      );
    },
    [],
  );

  const loadStoreConfiguration = useCallback(async (selectedStoreId: string) => {
    if (!selectedStoreId) return;
    try {
      const [methodData, receiptData] = await Promise.all([
        api.get<{ items: PaymentMethod[] }>(
          `/api/pos/admin/payment-methods?storeId=${encodeURIComponent(selectedStoreId)}`,
        ),
        api.get<Partial<ReceiptSettings>>(
          `/api/pos/admin/receipt-settings?storeId=${encodeURIComponent(selectedStoreId)}`,
        ),
      ]);
      setPaymentMethods(methodData.items);
      setReceipt({ ...emptyReceipt, ...receiptData, storeId: selectedStoreId });
    } catch (err) {
      setError(err instanceof Error ? err.message : 'No se pudo cargar la configuración de cobro');
    }
  }, []);

  const load = useCallback(async () => {
    setLoading(true);
    setError('');
    try {
      const [storeData, terminalData, userData] = await Promise.all([
        api.get<{ stores: PosStore[] }>('/api/pos/admin/stores'),
        api.get<{ terminals: PosTerminal[] }>('/api/pos/admin/terminals'),
        api.get<{ items: Array<PosCashier | { role: string }> }>('/api/pos/users'),
      ]);
      setStores(storeData.stores);
      setTerminals(terminalData.terminals);
      setCashiers(userData.items.filter((item): item is PosCashier => item.role === 'pos_cashier'));
      const selected = storeId || storeData.stores.find((store) => store.active)?.id || '';
      setStoreId(selected);
      await loadStoreConfiguration(selected);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'No se pudo cargar la configuración TPV');
    } finally {
      setLoading(false);
    }
  }, [loadStoreConfiguration, storeId]);

  useEffect(() => {
    void load();
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  const changeStore = (nextStoreId: string) => {
    setStoreId(nextStoreId);
    setReceiptMessage('');
    setPaymentMessage('');
    void loadStoreConfiguration(nextStoreId);
  };

  const createTerminal = async (event: React.FormEvent) => {
    event.preventDefault();
    setCreating(true);
    setError('');
    setNewCode('');
    try {
      const terminal = await api.post<PosTerminal>('/api/pos/admin/terminals', {
        storeId,
        name: terminalName.trim(),
      });
      setTerminalName('');
      setNewCode(terminal.bindingCode ?? '');
      await load();
    } catch (err) {
      setError(err instanceof Error ? err.message : 'No se pudo crear el terminal');
    } finally {
      setCreating(false);
    }
  };

  const openTouchConfig = (terminal: PosTerminal) => {
    const configured = terminal.settings?.quickProductVariantIds ?? [];
    const selectedIds = configured.filter((value): value is string => typeof value === 'string');
    setConfiguring(terminal);
    setTouchEnabled(terminal.settings?.touchNavigationEnabled !== false);
    setDiscountsEnabled(terminal.settings?.lineDiscountsEnabled !== false);
    setQuickSlots(Array.from({ length: QUICK_PRODUCTS_MAX }, (_, slot) => configured[slot] ?? null));
    setQuickSearch('');
    setQuickSearchResults([]);
    setTouchMessage('');
    setSelfpayMode(terminal.settings?.selfpayMode ?? false);
    setClosePinRequired(terminal.settings?.closeSessionRequiresPin ?? false);
    setClosePinValue(terminal.settings?.closeSessionPin ?? '');
    setSecurityMessage('');
    if (selectedIds.length > 0) {
      void fetchCatalogOptions({ variantIds: selectedIds })
        .then((data) => mergeCatalogOptions(data.items))
        .catch((err) => {
          setTouchMessage(err instanceof Error ? err.message : 'No se pudo cargar la selección actual');
        });
    }
  };

  useEffect(() => {
    if (!configuring) return;
    let cancelled = false;
    const timer = setTimeout(() => {
      void (async () => {
        setQuickSearchLoading(true);
        try {
          const data = await fetchCatalogOptions({ q: quickSearch, limit: 12 });
          if (cancelled) return;
          mergeCatalogOptions(data.items);
          setQuickSearchResults(data.items);
        } catch (err) {
          if (!cancelled) {
            setTouchMessage(err instanceof Error ? err.message : 'No se pudo buscar productos');
          }
        } finally {
          if (!cancelled) setQuickSearchLoading(false);
        }
      })();
    }, 250);
    return () => {
      cancelled = true;
      clearTimeout(timer);
    };
  }, [configuring, fetchCatalogOptions, mergeCatalogOptions, quickSearch]);

  const addQuickProduct = (product: CatalogOption) => {
    if (quickSlots.includes(product.variantId)) {
      setTouchMessage('Ese producto ya está en accesos rápidos');
      return;
    }
    const emptySlot = quickSlots.findIndex((value) => value === null);
    if (emptySlot === -1) {
      setTouchMessage(`Solo puedes guardar ${QUICK_PRODUCTS_MAX} productos rápidos`);
      return;
    }
    setQuickSlots((current) => current.map((value, index) => (index === emptySlot ? product.variantId : value)));
    mergeCatalogOptions([product]);
    setTouchMessage('');
  };

  const removeQuickProduct = (slot: number) => {
    setQuickSlots((current) => current.map((value, index) => (index === slot ? null : value)));
    setTouchMessage('');
  };

  const moveQuickProduct = (slot: number, direction: -1 | 1) => {
    const target = slot + direction;
    if (target < 0 || target >= QUICK_PRODUCTS_MAX) return;
    setQuickSlots((current) => {
      const next = [...current];
      [next[slot], next[target]] = [next[target], next[slot]];
      return next;
    });
    setTouchMessage('');
  };

  const saveTouchConfig = async () => {
    if (!configuring) return;
    setSavingTouch(true);
    setTouchMessage('');
    try {
      await api.patch(`/api/pos/admin/terminals/${configuring.id}/touch-config`, {
        touchNavigationEnabled: touchEnabled,
        lineDiscountsEnabled: discountsEnabled,
        quickProductVariantIds: quickSlots,
      });
      setTouchMessage('Configuración del terminal guardada');
      await load();
    } catch (err) {
      setTouchMessage(err instanceof Error ? err.message : 'No se pudo guardar');
    } finally {
      setSavingTouch(false);
    }
  };

  // F-203: save selfpay + PIN settings via PATCH /pos/admin/terminals/:id
  const saveSecuritySettings = async () => {
    if (!configuring) return;
    setSavingSecurity(true);
    setSecurityMessage('');
    try {
      const settings: Record<string, unknown> = {
        selfpayMode,
        closeSessionRequiresPin: closePinRequired,
      };
      if (closePinValue) settings.closeSessionPin = closePinValue;
      await api.patch(`/api/pos/admin/terminals/${configuring.id}`, { settings });
      setSecurityMessage('Configuración de cierre guardada');
      setTerminals(prev =>
        prev.map(t =>
          t.id === configuring.id
            ? { ...t, settings: { ...t.settings, ...settings } }
            : t,
        ),
      );
    } catch (err) {
      setSecurityMessage('Error al guardar: ' + (err instanceof Error ? err.message : 'Error'));
    } finally {
      setSavingSecurity(false);
    }
  };

  const createPaymentMethod = async (event: React.FormEvent) => {
    event.preventDefault();
    setSavingMethod(true);
    setPaymentMessage('');
    try {
      await api.post('/api/pos/admin/payment-methods', {
        storeId,
        code: newMethod.code.trim().toLowerCase(),
        label: newMethod.label.trim(),
        kind: newMethod.kind,
        active: true,
        sortOrder: paymentMethods.length,
      });
      setNewMethod({ code: '', label: '', kind: 'other' });
      setPaymentMessage('Forma de pago creada');
      await loadStoreConfiguration(storeId);
    } catch (err) {
      setPaymentMessage(err instanceof Error ? err.message : 'No se pudo crear la forma de pago');
    } finally {
      setSavingMethod(false);
    }
  };

  const togglePaymentMethod = async (method: PaymentMethod) => {
    setPaymentMessage('');
    try {
      await api.patch(`/api/pos/admin/payment-methods/${method.id}`, { active: !method.active });
      setPaymentMessage(method.active ? 'Forma de pago desactivada' : 'Forma de pago activada');
      await loadStoreConfiguration(storeId);
    } catch (err) {
      setPaymentMessage(err instanceof Error ? err.message : 'No se pudo actualizar');
    }
  };

  const createCashier = async (event: React.FormEvent) => {
    event.preventDefault();
    setSavingCashier(true);
    setCashierMessage('');
    try {
      await api.post('/api/pos/users', {
        email: newCashier.email.trim().toLowerCase(),
        password: newCashier.password,
        role: 'pos_cashier',
      });
      setNewCashier({ email: '', password: '' });
      setCashierMessage('Cajero creado');
      await load();
    } catch (err) {
      setCashierMessage(err instanceof Error ? err.message : 'No se pudo crear el cajero');
    } finally {
      setSavingCashier(false);
    }
  };

  const toggleCashier = async (cashier: PosCashier) => {
    const nextActive = !cashier.active;
    const action = nextActive ? 'reactivar' : 'desactivar';
    if (!window.confirm(`¿Quieres ${action} a ${cashier.email}?`)) return;
    setCashierMessage('');
    try {
      await api.patch(`/api/pos/users/${cashier.id}/status`, { active: nextActive });
      setCashierMessage(nextActive ? 'Cajero reactivado' : 'Cajero desactivado');
      await load();
    } catch (err) {
      setCashierMessage(err instanceof Error ? err.message : `No se pudo ${action} el cajero`);
    }
  };

  const deleteCashier = async (cashier: PosCashier) => {
    if (
      !window.confirm(
        `¿Eliminar definitivamente a ${cashier.email}? No podrá reactivarse. Su historial de ventas y caja se conservará.`,
      )
    )
      return;
    setCashierMessage('');
    try {
      await api.delete(`/api/pos/users/${cashier.id}`);
      setCashierMessage('Cajero eliminado; su histórico se conserva');
      await load();
    } catch (err) {
      setCashierMessage(err instanceof Error ? err.message : 'No se pudo eliminar el cajero');
    }
  };

  const saveReceipt = async (event: React.FormEvent) => {
    event.preventDefault();
    setSavingReceipt(true);
    setReceiptMessage('');
    try {
      await api.patch('/api/pos/admin/receipt-settings', receipt);
      setReceiptMessage('Datos y numeración del ticket guardados');
      await loadStoreConfiguration(storeId);
    } catch (err) {
      setReceiptMessage(err instanceof Error ? err.message : 'No se pudo guardar el ticket');
    } finally {
      setSavingReceipt(false);
    }
  };

  const copyCode = async (code: string) => {
    await navigator.clipboard.writeText(code);
    setCopied(code);
    window.setTimeout(() => setCopied(''), 2000);
  };

  return (
    <div className="space-y-6">
      <header>
        <h1 className="text-2xl font-bold text-gray-900">TPV</h1>
        <p className="mt-0.5 text-sm text-gray-500">
          Configura terminales táctiles, formas de pago y contenido fiscal del ticket.
        </p>
      </header>

      <label className="block max-w-md text-sm font-medium text-gray-700">
        Tienda que estás configurando
        <select
          value={storeId}
          onChange={(event) => changeStore(event.target.value)}
          className="mt-1 w-full rounded-xl border border-gray-300 bg-white px-3 py-2.5"
        >
          {stores
            .filter((store) => store.active)
            .map((store) => (
              <option key={store.id} value={store.id}>
                {store.name}
              </option>
            ))}
        </select>
      </label>

      <form onSubmit={createTerminal} className="rounded-xl border border-gray-200 bg-white p-6">
        <h2 className="mb-4 font-bold text-gray-900">Crear y vincular terminal</h2>
        <div className="flex flex-wrap items-end gap-4">
          <label className="min-w-64 flex-1 text-sm font-medium text-gray-700">
            Nombre del terminal
            <input
              value={terminalName}
              onChange={(event) => setTerminalName(event.target.value)}
              required
              maxLength={100}
              placeholder="Caja principal"
              className="mt-1 w-full rounded-xl border border-gray-300 px-3 py-2.5"
            />
          </label>
          <button
            disabled={creating || !storeId || !terminalName.trim()}
            className="rounded-xl bg-[#2D6A4F] px-5 py-2.5 text-sm font-semibold text-white disabled:opacity-50"
          >
            {creating ? 'Creando…' : 'Crear terminal'}
          </button>
        </div>
        {newCode && (
          <p className="mt-4 rounded-lg bg-green-50 p-3 text-sm text-green-800">
            Código: <strong className="font-mono text-lg tracking-widest">{newCode}</strong>
          </p>
        )}
        {error && <p className="mt-4 text-sm text-red-600">{error}</p>}
      </form>

      <section className="overflow-hidden rounded-xl border border-gray-200 bg-white">
        <div className="border-b px-6 py-4">
          <h2 className="font-bold">Terminales</h2>
        </div>
        {loading ? (
          <p className="p-6 text-sm text-gray-500">Cargando…</p>
        ) : (
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead className="bg-gray-50 text-left text-xs uppercase text-gray-500">
                <tr>
                  <th className="px-4 py-3">Nombre</th>
                  <th className="px-4 py-3">Código</th>
                  <th className="px-4 py-3">Estado</th>
                  <th className="px-4 py-3">Vinculado</th>
                  <th className="px-4 py-3">Configuración</th>
                </tr>
              </thead>
              <tbody className="divide-y">
                {terminals
                  .filter((terminal) => terminal.storeId === storeId)
                  .map((terminal) => (
                    <tr key={terminal.id}>
                      <td className="px-4 py-3 font-medium">{terminal.name}</td>
                      <td className="px-4 py-3">
                        <button
                          type="button"
                          onClick={() =>
                            terminal.bindingCode && void copyCode(terminal.bindingCode)
                          }
                          disabled={!terminal.bindingCode}
                          className="rounded-lg bg-gray-100 px-3 py-1 font-mono"
                        >
                          {copied === terminal.bindingCode
                            ? 'Copiado'
                            : (terminal.bindingCode ?? '—')}
                        </button>
                      </td>
                      <td className="px-4 py-3">{terminal.status}</td>
                      <td className="px-4 py-3">{terminal.boundAt ? 'Sí' : 'No'}</td>
                      <td className="px-4 py-3">
                        <button
                          type="button"
                          onClick={() => openTouchConfig(terminal)}
                          className="rounded-lg border border-[#2D6A4F] px-3 py-1.5 text-xs font-semibold text-[#2D6A4F]"
                        >
                          Configurar terminal
                        </button>
                      </td>
                    </tr>
                  ))}
              </tbody>
            </table>
          </div>
        )}
      </section>

      <section className="rounded-xl border border-gray-200 bg-white p-6">
        <div>
          <h2 className="font-bold">Cajeros</h2>
          <p className="mt-1 text-sm text-gray-500">
            Desactivar corta el acceso y permite reactivarlo. Eliminar es irreversible, pero
            conserva la atribución histórica de ventas y sesiones de caja.
          </p>
        </div>
        <form
          onSubmit={createCashier}
          className="mt-5 grid gap-3 rounded-xl bg-gray-50 p-4 md:grid-cols-[1fr_1fr_auto] md:items-end"
        >
          <label className="text-sm font-medium">
            Email
            <input
              type="email"
              value={newCashier.email}
              onChange={(event) => setNewCashier({ ...newCashier, email: event.target.value })}
              required
              className="mt-1 w-full rounded-xl border px-3 py-2.5"
            />
          </label>
          <label className="text-sm font-medium">
            Contraseña inicial
            <input
              type="password"
              value={newCashier.password}
              onChange={(event) => setNewCashier({ ...newCashier, password: event.target.value })}
              required
              minLength={8}
              maxLength={200}
              className="mt-1 w-full rounded-xl border px-3 py-2.5"
            />
          </label>
          <button
            disabled={savingCashier}
            className="rounded-xl bg-[#2D6A4F] px-5 py-2.5 text-sm font-semibold text-white disabled:opacity-50"
          >
            {savingCashier ? 'Creando…' : 'Crear cajero'}
          </button>
        </form>
        <div className="mt-5 overflow-x-auto rounded-xl border">
          <table className="w-full text-sm">
            <thead className="bg-gray-50 text-left text-xs uppercase text-gray-500">
              <tr>
                <th className="px-4 py-3">Email</th>
                <th className="px-4 py-3">Estado</th>
                <th className="px-4 py-3">Creado</th>
                <th className="px-4 py-3 text-right">Acciones</th>
              </tr>
            </thead>
            <tbody className="divide-y">
              {cashiers.map((cashier) => (
                <tr key={cashier.id} className={cashier.status === 'deleted' ? 'opacity-60' : ''}>
                  <td className="px-4 py-3 font-medium">{cashier.email}</td>
                  <td className="px-4 py-3">
                    <span
                      className={`rounded-full px-2.5 py-1 text-xs font-semibold ${
                        cashier.status === 'active'
                          ? 'bg-green-100 text-green-800'
                          : cashier.status === 'inactive'
                            ? 'bg-amber-100 text-amber-800'
                            : 'bg-gray-200 text-gray-700'
                      }`}
                    >
                      {cashier.status === 'active'
                        ? 'Activo'
                        : cashier.status === 'inactive'
                          ? 'Inactivo'
                          : 'Eliminado'}
                    </span>
                  </td>
                  <td className="px-4 py-3 text-gray-500">
                    {new Date(cashier.createdAt).toLocaleDateString('es-ES')}
                  </td>
                  <td className="px-4 py-3">
                    {cashier.status !== 'deleted' && (
                      <div className="flex justify-end gap-2">
                        <button
                          type="button"
                          onClick={() => void toggleCashier(cashier)}
                          className="rounded-lg border px-3 py-2 text-xs font-semibold"
                        >
                          {cashier.active ? 'Desactivar' : 'Reactivar'}
                        </button>
                        <button
                          type="button"
                          onClick={() => void deleteCashier(cashier)}
                          className="rounded-lg border border-red-200 px-3 py-2 text-xs font-semibold text-red-700"
                        >
                          Eliminar
                        </button>
                      </div>
                    )}
                  </td>
                </tr>
              ))}
              {!loading && cashiers.length === 0 && (
                <tr>
                  <td colSpan={4} className="px-4 py-8 text-center text-gray-500">
                    No hay cajeros configurados.
                  </td>
                </tr>
              )}
            </tbody>
          </table>
        </div>
        {cashierMessage && <p className="mt-3 text-sm">{cashierMessage}</p>}
      </section>

      {configuring && (
        <section className="rounded-xl border border-gray-200 bg-white p-6">
          <div className="flex justify-between">
            <div>
              <h2 className="font-bold">Interfaz táctil · {configuring.name}</h2>
              <p className="mt-1 text-sm text-gray-500">
                Elige hasta ocho productos rápidos y las funciones disponibles en esta caja.
              </p>
            </div>
            <button type="button" onClick={() => setConfiguring(null)} aria-label="Cerrar">
              ✕
            </button>
          </div>
          <div className="mt-5 grid gap-3 md:grid-cols-2">
            <label className="flex items-center gap-3 rounded-xl bg-gray-50 p-4 text-sm font-medium">
              <input
                type="checkbox"
                checked={touchEnabled}
                onChange={(event) => setTouchEnabled(event.target.checked)}
                className="h-5 w-5 accent-[#2D6A4F]"
              />{' '}
              Navegación táctil por categorías
            </label>
            <label className="flex items-center gap-3 rounded-xl bg-gray-50 p-4 text-sm font-medium">
              <input
                type="checkbox"
                checked={discountsEnabled}
                onChange={(event) => setDiscountsEnabled(event.target.checked)}
                className="h-5 w-5 accent-[#2D6A4F]"
              />{' '}
              Permitir descuentos por línea
            </label>
          </div>
          <p className="mt-2 text-xs text-gray-500">
            Desactiva descuentos para terminales de autopago.
          </p>
          <div className="mt-5 rounded-2xl border border-gray-200 bg-gray-50 p-4">
            <div className="flex flex-col gap-3 md:flex-row md:items-end md:justify-between">
              <div>
                <h3 className="text-sm font-bold text-gray-900">
                  Productos rápidos ({quickSlots.filter((value) => value !== null).length}/{QUICK_PRODUCTS_MAX})
                </h3>
                <p className="mt-1 text-xs text-gray-500">
                  Busca por nombre, SKU o EAN y añade productos a una lista de hasta ocho accesos rápidos.
                </p>
              </div>
              <button
                type="button"
                onClick={() => void saveTouchConfig()}
                disabled={savingTouch}
                className="rounded-xl bg-[#2D6A4F] px-5 py-2 text-sm font-semibold text-white disabled:opacity-50"
              >
                {savingTouch ? 'Guardando…' : 'Guardar accesos rápidos'}
              </button>
            </div>

            <label className="mt-4 block text-sm font-medium text-gray-700">
              Buscar producto
              <input
                type="search"
                value={quickSearch}
                onChange={(event) => setQuickSearch(event.target.value)}
                placeholder="Ej. Kombucha, SKU123, 8412345678901"
                className="mt-1 w-full rounded-xl border border-gray-300 bg-white px-3 py-2.5"
              />
            </label>

            <div className="mt-3 space-y-2">
              {quickSearchLoading ? (
                <p className="text-sm text-gray-500">Buscando productos…</p>
              ) : quickSearchResults.length > 0 ? (
                quickSearchResults.map((product) => {
                  const isSelected = quickSlots.includes(product.variantId);
                  const isFull = !isSelected && quickSlots.every((value) => value !== null);
                  return (
                    <div
                      key={product.variantId}
                      className="flex flex-col gap-2 rounded-xl border border-white bg-white p-3 shadow-sm md:flex-row md:items-center md:justify-between"
                    >
                      <div>
                        <p className="font-medium text-gray-900">{product.name}</p>
                        <p className="text-xs text-gray-500">
                          {product.sku}
                          {product.ean ? ` · EAN ${product.ean}` : ''}
                        </p>
                      </div>
                      <button
                        type="button"
                        onClick={() => addQuickProduct(product)}
                        disabled={isSelected || isFull}
                        className="rounded-lg border border-[#2D6A4F] px-3 py-2 text-sm font-semibold text-[#2D6A4F] disabled:cursor-not-allowed disabled:border-gray-200 disabled:text-gray-400"
                      >
                        {isSelected ? 'Añadido' : isFull ? 'Lista completa' : 'Añadir'}
                      </button>
                    </div>
                  );
                })
              ) : (
                <p className="text-sm text-gray-500">No se encontraron productos para esa búsqueda.</p>
              )}
            </div>

            <div className="mt-4 grid gap-3">
              {quickSlots.map((variantId, slot) => {
                const product = variantId ? catalogById.get(variantId) : null;
                return (
                  <div
                    key={slot}
                    className="flex flex-col gap-3 rounded-xl border border-white bg-white p-3 shadow-sm md:flex-row md:items-center md:justify-between"
                  >
                    <div>
                      <p className="text-xs font-semibold uppercase tracking-wide text-gray-400">
                        Botón {slot + 1}
                      </p>
                      {variantId ? (
                        <>
                          <p className="font-medium text-gray-900">
                            {product?.name ?? 'Producto configurado previamente'}
                          </p>
                          <p className="text-xs text-gray-500">
                            {product?.sku ?? variantId}
                            {product?.ean ? ` · EAN ${product.ean}` : ''}
                          </p>
                        </>
                      ) : (
                        <p className="text-sm text-gray-500">Sin asignar</p>
                      )}
                    </div>
                    <div className="flex flex-wrap items-center gap-2">
                      <button
                        type="button"
                        onClick={() => moveQuickProduct(slot, -1)}
                        disabled={slot === 0 || variantId === null}
                        className="rounded-lg border bg-white px-3 py-2 text-xs font-semibold disabled:opacity-40"
                      >
                        ↑ Subir
                      </button>
                      <button
                        type="button"
                        onClick={() => moveQuickProduct(slot, 1)}
                        disabled={slot === QUICK_PRODUCTS_MAX - 1 || variantId === null}
                        className="rounded-lg border bg-white px-3 py-2 text-xs font-semibold disabled:opacity-40"
                      >
                        ↓ Bajar
                      </button>
                      <button
                        type="button"
                        onClick={() => removeQuickProduct(slot)}
                        disabled={variantId === null}
                        className="rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-xs font-semibold text-red-700 disabled:opacity-40"
                      >
                        Quitar
                      </button>
                    </div>
                  </div>
                );
              })}
            </div>

            {touchMessage && (
              <p
                className={`mt-3 text-sm ${touchMessage.includes('guardad') ? 'text-green-700' : 'text-red-600'}`}
              >
                {touchMessage}
              </p>
            )}
          </div>
          {/* F-203: cash close security settings */}
          <div className="mt-6 border-t pt-4">
            <h3 className="mb-3 text-sm font-bold text-gray-900">Seguridad de cierre de caja</h3>
            <div className="grid gap-3 md:grid-cols-2">
              <label className="flex items-center gap-3 rounded-xl bg-gray-50 p-4 text-sm font-medium">
                <input
                  type="checkbox"
                  checked={selfpayMode}
                  onChange={(e) => setSelfpayMode(e.target.checked)}
                  className="h-5 w-5 accent-[#2D6A4F]"
                />
                Modo autopago (oculta botón de cierre)
              </label>
              <label className="flex items-center gap-3 rounded-xl bg-gray-50 p-4 text-sm font-medium">
                <input
                  type="checkbox"
                  checked={closePinRequired}
                  onChange={(e) => setClosePinRequired(e.target.checked)}
                  className="h-5 w-5 accent-[#2D6A4F]"
                />
                Requerir PIN para cerrar caja
              </label>
            </div>
            <div className="mt-3">
              <label className="mb-1 block text-sm font-medium text-gray-700">
                PIN de cajero {closePinRequired && <span className="text-red-500">*</span>}
              </label>
              <input
                type="password"
                inputMode="numeric"
                maxLength={6}
                value={closePinValue}
                onChange={(e) => setClosePinValue(e.target.value)}
                placeholder="4-6 dígitos"
                className="w-full rounded-xl border border-gray-300 px-3 py-2 text-sm focus:border-[#2D6A4F] focus:outline-none"
              />
              <p className="mt-1 text-xs text-gray-500">Este PIN se requiere para autorizar el cierre de caja.</p>
            </div>
            <div className="mt-3 flex items-center gap-4">
              <button
                type="button"
                onClick={() => void saveSecuritySettings()}
                disabled={savingSecurity}
                className="rounded-xl bg-[#2D6A4F] px-5 py-2 text-sm font-semibold text-white disabled:opacity-50"
              >
                {savingSecurity ? 'Guardando…' : 'Guardar seguridad'}
              </button>
              {securityMessage && <p className="text-sm">{securityMessage}</p>}
            </div>
          </div>
        </section>
      )}

      <section className="rounded-xl border border-gray-200 bg-white p-6">
        <div>
          <h2 className="font-bold">Formas de pago</h2>
          <p className="mt-1 text-sm text-gray-500">
            Crea Bizum, Stripe, Apple Pay u otro método. “Tarjeta” y “otro” se registran
            manualmente; no activan una pasarela externa.
          </p>
        </div>
        <div className="mt-4 grid gap-3 md:grid-cols-2 xl:grid-cols-3">
          {paymentMethods.map((method) => (
            <div
              key={method.id}
              className={`flex items-center justify-between rounded-xl border p-4 ${method.active ? 'border-green-200 bg-green-50' : 'border-gray-200 bg-gray-50 opacity-70'}`}
            >
              <div>
                <strong className="block">{method.label}</strong>
                <span className="text-xs text-gray-500">
                  {method.code} · {method.kind}
                </span>
              </div>
              <button
                type="button"
                onClick={() => void togglePaymentMethod(method)}
                className="rounded-lg border bg-white px-3 py-2 text-xs font-semibold"
              >
                {method.active ? 'Desactivar' : 'Activar'}
              </button>
            </div>
          ))}
        </div>
        <form
          onSubmit={createPaymentMethod}
          className="mt-5 grid gap-3 rounded-xl bg-gray-50 p-4 md:grid-cols-[1fr_1fr_1fr_auto] md:items-end"
        >
          <label className="text-sm font-medium">
            Código
            <input
              value={newMethod.code}
              onChange={(event) =>
                setNewMethod({
                  ...newMethod,
                  code: event.target.value.toLowerCase().replace(/[^a-z0-9_-]/g, ''),
                })
              }
              required
              maxLength={32}
              placeholder="bizum"
              className="mt-1 w-full rounded-xl border px-3 py-2.5"
            />
          </label>
          <label className="text-sm font-medium">
            Nombre visible
            <input
              value={newMethod.label}
              onChange={(event) => setNewMethod({ ...newMethod, label: event.target.value })}
              required
              maxLength={64}
              placeholder="Bizum"
              className="mt-1 w-full rounded-xl border px-3 py-2.5"
            />
          </label>
          <label className="text-sm font-medium">
            Tipo
            <select
              value={newMethod.kind}
              onChange={(event) =>
                setNewMethod({ ...newMethod, kind: event.target.value as PaymentMethod['kind'] })
              }
              className="mt-1 w-full rounded-xl border bg-white px-3 py-2.5"
            >
              <option value="cash">Efectivo</option>
              <option value="card">Tarjeta</option>
              <option value="other">Otro</option>
            </select>
          </label>
          <button
            disabled={savingMethod}
            className="rounded-xl bg-[#2D6A4F] px-5 py-2.5 text-sm font-semibold text-white disabled:opacity-50"
          >
            Añadir
          </button>
        </form>
        {paymentMessage && <p className="mt-3 text-sm">{paymentMessage}</p>}
      </section>

      <form onSubmit={saveReceipt} className="rounded-xl border border-gray-200 bg-white p-6">
        <div>
          <h2 className="font-bold">Empresa, numeración y política del ticket</h2>
          <p className="mt-1 text-sm text-gray-500">
            Estos datos se congelan en cada ticket emitido.
          </p>
        </div>
        <div className="mt-5 grid gap-4 md:grid-cols-2 xl:grid-cols-3">
          <Field
            label="Razón social / nombre"
            value={receipt.name}
            onChange={(value) => setReceipt({ ...receipt, name: value })}
            required
          />
          <Field
            label="NIF / CIF"
            value={receipt.taxId}
            onChange={(value) => setReceipt({ ...receipt, taxId: value })}
          />
          <Field
            label="Dirección"
            value={receipt.address}
            onChange={(value) => setReceipt({ ...receipt, address: value })}
          />
          <Field
            label="Email"
            type="email"
            value={receipt.contactEmail}
            onChange={(value) => setReceipt({ ...receipt, contactEmail: value })}
          />
          <Field
            label="Teléfono"
            value={receipt.contactPhone}
            onChange={(value) => setReceipt({ ...receipt, contactPhone: value })}
          />
          <Field
            label="Cabecera"
            value={receipt.receiptHeader}
            onChange={(value) => setReceipt({ ...receipt, receiptHeader: value })}
          />
          <Field
            label="Pie"
            value={receipt.receiptFooter}
            onChange={(value) => setReceipt({ ...receipt, receiptFooter: value })}
          />
          <Field
            label="URL del logo"
            value={receipt.logoUrl}
            onChange={(value) => setReceipt({ ...receipt, logoUrl: value })}
            placeholder="https://ejemplo.com/logo.png"
          />
          <Field
            label="Prefijo de ticket"
            value={receipt.prefix}
            onChange={(value) =>
              setReceipt({ ...receipt, prefix: value.toUpperCase().replace(/[^A-Z0-9_-]/g, '') })
            }
            required
          />
          <Field
            label="Próximo número"
            type="number"
            value={String(receipt.nextNumber)}
            onChange={(value) => setReceipt({ ...receipt, nextNumber: Number(value) })}
            required
            min={1}
          />
          <Field
            label="Dígitos (relleno)"
            type="number"
            value={String(receipt.padding)}
            onChange={(value) => setReceipt({ ...receipt, padding: Number(value) })}
            required
            min={1}
            max={12}
          />
        </div>
        <label className="mt-4 block text-sm font-medium">
          Política de devolución
          <textarea
            value={receipt.returnPolicy}
            onChange={(event) => setReceipt({ ...receipt, returnPolicy: event.target.value })}
            required
            maxLength={2000}
            rows={3}
            className="mt-1 w-full rounded-xl border px-3 py-2.5"
          />
        </label>
        <div className="mt-5 flex items-center gap-4">
          <button
            disabled={savingReceipt}
            className="rounded-xl bg-[#2D6A4F] px-5 py-2.5 text-sm font-semibold text-white disabled:opacity-50"
          >
            {savingReceipt ? 'Guardando…' : 'Guardar ticket'}
          </button>
          {receiptMessage && <p className="text-sm">{receiptMessage}</p>}
        </div>
      </form>
    </div>
  );
}

function Field({
  label,
  value,
  onChange,
  type = 'text',
  required = false,
  min,
  max,
  placeholder,
}: {
  label: string;
  value: string;
  onChange: (value: string) => void;
  type?: string;
  required?: boolean;
  min?: number;
  max?: number;
  placeholder?: string;
}) {
  return (
    <label className="text-sm font-medium text-gray-700">
      {label}
      <input
        type={type}
        value={value ?? ""}
        onChange={(event) => onChange(event.target.value)}
        required={required}
        min={min}
        max={max}
        placeholder={placeholder}
        className="mt-1 w-full rounded-xl border border-gray-300 px-3 py-2.5"
      />
    </label>
  );
}
