import { useEffect, useState, useCallback } from 'react';
import { apiPatch, apiFetchOne, apiFetch, apiLink, apiUnlink } from '../lib/api';
import { STATUS_COLORS } from '../lib/tables';

const READ_ONLY_FIELDS = new Set(['id', 'created_at', 'updated_at']);
const TIMESTAMP_RE = /(_at|_timestamp)$/;

function isReadOnly(key) {
  return READ_ONLY_FIELDS.has(key) || TIMESTAMP_RE.test(key);
}

function FieldLabel({ name }) {
  return (
    <span className="text-xs font-semibold text-slate-400 uppercase tracking-wide">
      {name.replace(/_/g, ' ')}
    </span>
  );
}

function ReadOnlyValue({ fieldKey, value }) {
  if (value == null || value === '') return <span className="text-slate-300 text-sm">—</span>;

  if (Array.isArray(value)) {
    if (value.length === 0) return <span className="text-slate-400 text-sm">[]</span>;
    return (
      <div className="flex flex-wrap gap-1">
        {value.map((v, i) => (
          <span key={i} className="text-xs font-mono bg-slate-100 text-slate-600 rounded px-1.5 py-0.5">
            {String(v).slice(0, 12)}
          </span>
        ))}
      </div>
    );
  }

  if (TIMESTAMP_RE.test(fieldKey)) {
    return (
      <span className="text-sm text-slate-600">
        {new Date(value).toLocaleString('de-DE')}
      </span>
    );
  }

  if (fieldKey === 'status') {
    const cls = STATUS_COLORS[value] || 'bg-slate-100 text-slate-600';
    return <span className={`text-xs font-medium px-2 py-0.5 rounded-full ${cls}`}>{value}</span>;
  }

  if (fieldKey === 'id') {
    return <span className="text-sm font-mono text-slate-500">{value}</span>;
  }

  return <span className="text-sm text-slate-700 break-words">{String(value)}</span>;
}

function EditableField({ fieldKey, value, fieldDef, onChange }) {
  const { type, options, min, max } = fieldDef;

  if (type === 'select') {
    return (
      <select
        value={value ?? ''}
        onChange={e => onChange(e.target.value)}
        className="w-full border border-slate-300 rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-400 bg-white"
      >
        <option value="">— wählen —</option>
        {options.map(o => <option key={o} value={o}>{o}</option>)}
      </select>
    );
  }

  if (type === 'textarea') {
    return (
      <textarea
        value={value ?? ''}
        onChange={e => onChange(e.target.value)}
        rows={3}
        className="w-full border border-slate-300 rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-400 bg-white resize-y"
      />
    );
  }

  if (type === 'number') {
    return (
      <input
        type="number"
        value={value ?? ''}
        min={min}
        max={max}
        onChange={e => onChange(e.target.value === '' ? null : Number(e.target.value))}
        className="w-full border border-slate-300 rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-400 bg-white"
      />
    );
  }

  // default: text
  return (
    <input
      type="text"
      value={value ?? ''}
      onChange={e => onChange(e.target.value)}
      className="w-full border border-slate-300 rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-400 bg-white"
    />
  );
}

function RelationManager({ recordId, rel }) {
  const [items, setItems] = useState(undefined);   // undefined = loading
  const [search, setSearch] = useState('');
  const [searchResults, setSearchResults] = useState(null);
  const [searching, setSearching] = useState(false);
  const [showSearch, setShowSearch] = useState(false);
  const [error, setError] = useState('');

  // Load linked items
  useEffect(() => {
    setItems(undefined);
    apiFetchOne(rel.endpoint(recordId))
      .then(data => setItems(Array.isArray(data) ? data : []))
      .catch(() => setItems(null));
  }, [recordId, rel]);

  // Search available items
  useEffect(() => {
    if (!showSearch) return;
    if (!search.trim()) { setSearchResults([]); return; }
    const timer = setTimeout(() => {
      setSearching(true);
      const q = encodeURIComponent(search.trim());
      apiFetch(`${rel.searchEndpoint}?search=${q}&limit=20&offset=0`)
        .then(data => {
          const arr = Array.isArray(data) ? data : [];
          const linked = new Set((items || []).map(i => i.id));
          setSearchResults(arr.filter(r => !linked.has(r.id)));
        })
        .catch(() => setSearchResults([]))
        .finally(() => setSearching(false));
    }, 300);
    return () => clearTimeout(timer);
  }, [search, showSearch, items, rel]);

  async function handleLink(targetId) {
    try {
      await apiLink(rel.linkEndpoint(recordId, targetId));
      // refresh
      const data = await apiFetchOne(rel.endpoint(recordId));
      setItems(Array.isArray(data) ? data : []);
      setSearch('');
      setSearchResults([]);
      setShowSearch(false);
    } catch (e) { setError(e.message); }
  }

  async function handleUnlink(targetId) {
    try {
      await apiUnlink(rel.linkEndpoint(recordId, targetId));
      setItems(prev => (prev || []).filter(i => i.id !== targetId));
    } catch (e) { setError(e.message); }
  }

  return (
    <section>
      <div className="flex items-center justify-between mb-2">
        <h3 className="text-xs font-bold text-slate-400 uppercase tracking-widest">{rel.label}</h3>
        <button
          onClick={() => { setShowSearch(s => !s); setSearch(''); setSearchResults([]); }}
          className="text-xs text-indigo-600 hover:text-indigo-800 font-medium flex items-center gap-1"
        >
          {showSearch ? '✕ Schließen' : '+ Verknüpfen'}
        </button>
      </div>

      {/* Search box */}
      {showSearch && (
        <div className="mb-2">
          <input
            autoFocus
            type="text"
            placeholder={`${rel.label} suchen…`}
            value={search}
            onChange={e => setSearch(e.target.value)}
            className="w-full border border-slate-300 rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-400"
          />
          {searching && <p className="text-xs text-slate-400 mt-1">Suche…</p>}
          {searchResults && searchResults.length === 0 && search && !searching && (
            <p className="text-xs text-slate-400 mt-1">Keine Ergebnisse</p>
          )}
          {searchResults && searchResults.length > 0 && (
            <div className="mt-1 border border-slate-200 rounded-lg overflow-hidden max-h-36 overflow-y-auto">
              {searchResults.map(r => (
                <button
                  key={r.id}
                  onClick={() => handleLink(r.id)}
                  className="w-full text-left px-3 py-1.5 text-sm hover:bg-indigo-50 hover:text-indigo-700 transition-colors border-b border-slate-100 last:border-0"
                >
                  {rel.searchLabel(r)}
                </button>
              ))}
            </div>
          )}
        </div>
      )}

      {/* Linked items */}
      <div className="bg-slate-50 rounded-lg p-3 min-h-[40px]">
        {items === undefined && (
          <div className="flex gap-1">
            {[1,2,3].map(i => <div key={i} className="h-6 w-16 bg-slate-200 rounded animate-pulse" />)}
          </div>
        )}
        {items === null && <span className="text-xs text-red-500">Fehler beim Laden</span>}
        {Array.isArray(items) && items.length === 0 && (
          <span className="text-sm text-slate-400">Keine verknüpften Einträge</span>
        )}
        {Array.isArray(items) && items.length > 0 && (
          <div className="flex flex-wrap gap-1.5">
            {items.map(item => (
              <span key={item.id} className="group flex items-center gap-1 text-xs bg-indigo-50 text-indigo-700 rounded-full pl-2.5 pr-1 py-1 font-medium">
                {rel.display(item)}
                <button
                  onClick={() => handleUnlink(item.id)}
                  className="text-indigo-400 hover:text-red-500 hover:bg-red-50 rounded-full w-4 h-4 flex items-center justify-center transition-colors"
                  title="Verknüpfung entfernen"
                >
                  ×
                </button>
              </span>
            ))}
          </div>
        )}
        {error && <p className="text-xs text-red-500 mt-1">{error}</p>}
      </div>
    </section>
  );
}

export default function RecordModal({ record, meta, onClose, onSaved }) {
  const [values, setValues] = useState({});
  const [dirty, setDirty] = useState({});
  const [saving, setSaving] = useState(false);
  const [saveError, setSaveError] = useState('');

  // Init values from record
  useEffect(() => {
    if (!record) return;
    setValues({ ...record });
    setDirty({});
    setSaveError('');
  }, [record]);

  const handleChange = useCallback((key, val) => {
    setValues(prev => ({ ...prev, [key]: val }));
    setDirty(prev => ({ ...prev, [key]: true }));
  }, []);

  const handleSave = async () => {
    const patch = {};
    Object.keys(dirty).forEach(k => { patch[k] = values[k]; });
    if (Object.keys(patch).length === 0) { onClose(); return; }

    setSaving(true);
    setSaveError('');
    try {
      const updated = await apiPatch(meta.endpoint, record.id, patch);
      onSaved(updated || { ...record, ...patch });
      onClose();
    } catch (err) {
      setSaveError(err.message);
    } finally {
      setSaving(false);
    }
  };

  if (!record) return null;

  // All field keys from the record
  const allKeys = Object.keys(record);
  // Split into editable and read-only
  const editableKeys = allKeys.filter(k => !isReadOnly(k) && meta.editableFields?.[k]);
  const extraKeys = allKeys.filter(k => !isReadOnly(k) && !meta.editableFields?.[k] && !Array.isArray(record[k]));
  const arrayKeys = allKeys.filter(k => Array.isArray(record[k]));
  const roKeys = allKeys.filter(k => isReadOnly(k));

  const hasDirty = Object.keys(dirty).length > 0;

  return (
    <div className="fixed inset-0 z-50 flex items-start justify-center bg-black/40 backdrop-blur-sm p-4 overflow-y-auto">
      <div className="bg-white rounded-2xl shadow-2xl w-full max-w-2xl my-8 flex flex-col">
        {/* Header */}
        <div className="flex items-center justify-between px-6 py-4 border-b border-slate-200">
          <div>
            <span className="text-xl mr-2">{meta.icon}</span>
            <span className="font-semibold text-slate-800">{meta.label}</span>
            <span className="ml-2 font-mono text-xs text-slate-400">{record.id?.slice(0, 8)}…</span>
          </div>
          <button
            onClick={onClose}
            className="text-slate-400 hover:text-slate-600 text-2xl leading-none transition-colors"
            aria-label="Schließen"
          >
            ×
          </button>
        </div>

        {/* Body */}
        <div className="px-6 py-5 space-y-5 overflow-y-auto">

          {/* Editable fields */}
          {editableKeys.length > 0 && (
            <section>
              <h3 className="text-xs font-bold text-slate-400 uppercase tracking-widest mb-3">Bearbeiten</h3>
              <div className="space-y-3">
                {editableKeys.map(key => (
                  <div key={key}>
                    <FieldLabel name={key} />
                    <div className="mt-1">
                      <EditableField
                        fieldKey={key}
                        value={values[key]}
                        fieldDef={meta.editableFields[key]}
                        onChange={val => handleChange(key, val)}
                      />
                    </div>
                    {dirty[key] && (
                      <span className="text-xs text-indigo-500 mt-0.5 block">geändert</span>
                    )}
                  </div>
                ))}
              </div>
            </section>
          )}

          {/* Extra non-editable non-array fields */}
          {extraKeys.length > 0 && (
            <section>
              <h3 className="text-xs font-bold text-slate-400 uppercase tracking-widest mb-3">Weitere Felder</h3>
              <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
                {extraKeys.map(key => (
                  <div key={key} className="bg-slate-50 rounded-lg p-3">
                    <FieldLabel name={key} />
                    <div className="mt-1">
                      <ReadOnlyValue fieldKey={key} value={values[key]} />
                    </div>
                  </div>
                ))}
              </div>
            </section>
          )}

          {/* Array / linked fields */}
          {arrayKeys.length > 0 && (
            <section>
              <h3 className="text-xs font-bold text-slate-400 uppercase tracking-widest mb-3">Verknüpfte IDs</h3>
              <div className="space-y-2">
                {arrayKeys.map(key => (
                  <div key={key} className="bg-slate-50 rounded-lg p-3">
                    <FieldLabel name={key} />
                    <div className="mt-1">
                      <ReadOnlyValue fieldKey={key} value={values[key]} />
                    </div>
                  </div>
                ))}
              </div>
            </section>
          )}

          {/* Related data with link/unlink */}
          {meta.fetchRelated?.map(rel => (
            <RelationManager key={rel.key} recordId={record.id} rel={rel} />
          ))}

          {/* Read-only metadata */}
          <section>
            <h3 className="text-xs font-bold text-slate-400 uppercase tracking-widest mb-3">Metadaten</h3>
            <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
              {roKeys.map(key => (
                <div key={key} className="bg-slate-50 rounded-lg p-3">
                  <FieldLabel name={key} />
                  <div className="mt-1">
                    <ReadOnlyValue fieldKey={key} value={values[key]} />
                  </div>
                </div>
              ))}
            </div>
          </section>
        </div>

        {/* Footer */}
        <div className="px-6 py-4 border-t border-slate-200 flex items-center justify-between gap-3">
          {saveError && (
            <span className="text-sm text-red-600 flex-1">{saveError}</span>
          )}
          {!saveError && <span className="flex-1" />}
          <div className="flex gap-2">
            <button
              onClick={onClose}
              className="px-4 py-2 text-sm text-slate-600 hover:text-slate-800 border border-slate-300 rounded-lg transition-colors"
            >
              Abbrechen
            </button>
            <button
              onClick={handleSave}
              disabled={saving || !hasDirty}
              className="px-4 py-2 text-sm bg-indigo-600 hover:bg-indigo-700 disabled:opacity-40 text-white font-medium rounded-lg transition-colors"
            >
              {saving ? 'Speichern…' : hasDirty ? 'Speichern' : 'Gespeichert'}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}
