import { useEffect, useState } from 'react';
import type { FormEvent } from 'react';
import { api } from '../api/client';
import EpaperPreview from '../components/EpaperPreview';

interface Layout {
  id: number;
  name: string;
  type: string;
  width: number;
  height: number;
}

interface LayoutElement {
  id: number;
  layout_id: number;
  type: string;
  x: number;
  y: number;
  width: number | null;
  height: number | null;
  font_size: number;
  font_weight: string;
  text_align: string;
  style: string;
  static_text: string | null;
  datapoint_id: number | null;
  icon: string | null;
  sort_order: number;
}

interface LayoutWithElements extends Layout {
  elements: LayoutElement[];
}

interface Datapoint {
  id: number;
  name: string;
  label: string | null;
  value: string | null;
  unit: string | null;
}

const ICONS = ['', 'thermometer', 'droplet', 'wind', 'pressure', 'sun', 'bolt', 'gauge', 'wifi', 'battery', 'check', 'warning', 'clock'];

export default function Layouts() {
  const [layouts, setLayouts] = useState<Layout[]>([]);
  const [selected, setSelected] = useState<LayoutWithElements | null>(null);
  const [datapoints, setDatapoints] = useState<Datapoint[]>([]);
  const [newName, setNewName] = useState('');
  const [error, setError] = useState('');

  async function loadLayouts() {
    try {
      setLayouts(await api.get<Layout[]>('/api/layouts'));
    } catch (e) { setError((e as Error).message); }
  }

  async function loadDatapoints() {
    try {
      setDatapoints(await api.get<Datapoint[]>('/api/datapoints'));
    } catch (_) {}
  }

  async function selectLayout(id: number) {
    try {
      setSelected(await api.get<LayoutWithElements>(`/api/layouts/${id}`));
    } catch (e) { setError((e as Error).message); }
  }

  useEffect(() => { loadLayouts(); loadDatapoints(); }, []);

  async function handleAddLayout(e: FormEvent) {
    e.preventDefault();
    if (!newName.trim()) return;
    try {
      const res = await api.post<{ id: number }>('/api/layouts', { name: newName.trim() });
      setNewName('');
      loadLayouts();
      selectLayout(res.id);
    } catch (e) { setError((e as Error).message); }
  }

  async function handleDeleteLayout(id: number) {
    if (!confirm('Layout wirklich loeschen?')) return;
    try {
      await api.del(`/api/layouts/${id}`);
      if (selected?.id === id) setSelected(null);
      loadLayouts();
    } catch (e) { setError((e as Error).message); }
  }

  async function handleAddElement(type: string) {
    if (!selected) return;
    const sortOrder = selected.elements.length;
    const defaults: Record<string, any> = {
      value: { type: 'value', x: 20, y: 70 + sortOrder * 100, width: 370, height: 90, font_size: 32, font_weight: 'bold', style: 'card', sort_order: sortOrder },
      label: { type: 'label', x: 400, y: 15, font_size: 28, font_weight: 'bold', text_align: 'center', static_text: 'Titel', sort_order: sortOrder },
      line:  { type: 'line', x: 10, y: 55, width: 780, height: 2, sort_order: sortOrder },
      rect:  { type: 'rect', x: 10, y: 10, width: 100, height: 50, sort_order: sortOrder },
    };
    try {
      await api.post(`/api/layouts/${selected.id}/elements`, defaults[type] || defaults.value);
      selectLayout(selected.id);
    } catch (e) { setError((e as Error).message); }
  }

  async function updateElement(elId: number, field: string, value: any) {
    if (!selected) return;
    try {
      await api.put(`/api/layouts/${selected.id}/elements/${elId}`, { [field]: value });
      selectLayout(selected.id);
    } catch (e) { setError((e as Error).message); }
  }

  async function updateDatapointLabel(dpId: number, label: string) {
    try {
      await api.put(`/api/datapoints/${dpId}`, { label });
      loadDatapoints();
      if (selected) selectLayout(selected.id);
    } catch (e) { setError((e as Error).message); }
  }

  async function updateDatapointUnit(dpId: number, unit: string) {
    try {
      await api.put(`/api/datapoints/${dpId}`, { unit });
      loadDatapoints();
      if (selected) selectLayout(selected.id);
    } catch (e) { setError((e as Error).message); }
  }

  async function handleDeleteElement(elId: number) {
    if (!selected) return;
    try {
      await api.del(`/api/layouts/${selected.id}/elements/${elId}`);
      selectLayout(selected.id);
    } catch (e) { setError((e as Error).message); }
  }

  function handleExport() {
    if (!selected) return;
    window.open(`/api/layouts/${selected.id}/export`, '_blank');
  }

  async function handleImport() {
    const input = document.createElement('input');
    input.type = 'file';
    input.accept = '.json';
    input.onchange = async (e) => {
      const file = (e.target as HTMLInputElement).files?.[0];
      if (!file) return;
      try {
        const text = await file.text();
        const data = JSON.parse(text);
        const result = await api.post<any>('/api/layouts/import', data);
        loadLayouts();
        selectLayout(result.id);
      } catch (e) {
        setError((e as Error).message);
      }
    };
    input.click();
  }

  function NumInput({ value, onChange, label, w }: { value: number; onChange: (v: number) => void; label: string; w?: string }) {
    return (
      <div className={w || 'w-16'}>
        <div className="text-[10px] text-gray-400">{label}</div>
        <input type="number" className="w-full border border-gray-300 rounded px-1.5 py-1 text-xs"
          defaultValue={value} onBlur={(e) => { const v = parseInt(e.target.value); if (!isNaN(v) && v !== value) onChange(v); }} />
      </div>
    );
  }

  return (
    <div>
      <h2 className="text-xl font-semibold text-gray-800 mb-6">Layouts</h2>
      {error && <div className="mb-4 p-3 bg-red-50 border border-red-200 rounded text-red-700 text-sm">{error}<button className="ml-2 text-red-400" onClick={() => setError('')}>x</button></div>}

      <div className="flex gap-6">
        {/* Left: layout list */}
        <div className="w-56 shrink-0">
          <div className="bg-white rounded-lg border border-gray-200 overflow-hidden mb-3">
            {layouts.length === 0 && <p className="px-4 py-4 text-sm text-gray-400">Keine Layouts</p>}
            {layouts.map((l) => (
              <div key={l.id} onClick={() => selectLayout(l.id)}
                className={`flex items-center justify-between px-3 py-2.5 cursor-pointer text-sm border-b border-gray-100 last:border-0 ${selected?.id === l.id ? 'bg-sky-50 text-sky-700 font-medium' : 'hover:bg-gray-50'}`}>
                <span>{l.name}</span>
                <button onClick={(e) => { e.stopPropagation(); handleDeleteLayout(l.id); }} className="text-red-400 hover:text-red-600 text-xs ml-2">X</button>
              </div>
            ))}
          </div>
          <form onSubmit={handleAddLayout} className="flex gap-2 mb-2">
            <input placeholder="Neues Layout..." className="flex-1 border border-gray-300 rounded px-3 py-1.5 text-sm" value={newName} onChange={(e) => setNewName(e.target.value)} />
            <button type="submit" className="bg-sky-500 hover:bg-sky-600 text-white text-sm px-3 py-1.5 rounded">+</button>
          </form>
          <button onClick={handleImport} className="w-full text-xs text-gray-500 hover:text-sky-600 border border-dashed border-gray-300 rounded py-1.5 hover:border-sky-400">
            Layout importieren (.json)
          </button>
        </div>

        {/* Right: element editor */}
        {selected && (
          <div className="flex-1 min-w-0">
            <div className="flex items-center justify-between mb-4">
              <h3 className="font-medium text-gray-700">
                <span className="text-sky-600">{selected.name}</span>
                <span className="text-xs text-gray-400 ml-2">({selected.width}x{selected.height})</span>
              </h3>
              <div className="flex gap-2">
                <button onClick={() => handleAddElement('value')} className="bg-green-500 hover:bg-green-600 text-white text-xs px-3 py-1.5 rounded">+ Wert</button>
                <button onClick={() => handleAddElement('label')} className="bg-blue-500 hover:bg-blue-600 text-white text-xs px-3 py-1.5 rounded">+ Label</button>
                <button onClick={() => handleAddElement('line')} className="bg-gray-500 hover:bg-gray-600 text-white text-xs px-3 py-1.5 rounded">+ Linie</button>
                <button onClick={handleExport} className="border border-gray-300 text-gray-600 hover:bg-gray-100 text-xs px-3 py-1.5 rounded">Exportieren</button>
              </div>
            </div>

            {/* Element list — editable */}
            <div className="space-y-2 mb-6">
              {selected.elements.length === 0 && (
                <div className="bg-white rounded-lg border border-gray-200 p-6 text-center text-gray-400 text-sm">
                  Noch keine Elemente. Klicke oben auf "+ Wert" oder "+ Label" um ein Element hinzuzufuegen.
                </div>
              )}
              {selected.elements.map((el) => {
                const dp = datapoints.find((d) => d.id === el.datapoint_id);
                return (
                  <div key={el.id} className="bg-white rounded-lg border border-gray-200 p-3">
                    <div className="flex items-center gap-2 mb-2">
                      <span className={`text-xs font-bold px-2 py-0.5 rounded ${
                        el.type === 'value' ? 'bg-green-100 text-green-700' :
                        el.type === 'label' ? 'bg-blue-100 text-blue-700' :
                        el.type === 'line' ? 'bg-gray-100 text-gray-600' :
                        'bg-yellow-100 text-yellow-700'
                      }`}>{el.type.toUpperCase()}</span>
                      {el.type === 'value' && dp && (
                        <span className="text-xs text-gray-500">{dp.label || dp.name} = <strong>{dp.value ?? '—'}</strong> {dp.unit || ''}</span>
                      )}
                      {el.type === 'label' && (
                        <span className="text-xs text-gray-500 italic">"{el.static_text}"</span>
                      )}
                      <div className="flex-1" />
                      <button onClick={() => handleDeleteElement(el.id)} className="text-red-400 hover:text-red-600 text-xs">Loeschen</button>
                    </div>

                    <div className="flex flex-wrap gap-2 items-end">
                      {/* Position */}
                      <NumInput label="X" value={el.x} onChange={(v) => updateElement(el.id, 'x', v)} />
                      <NumInput label="Y" value={el.y} onChange={(v) => updateElement(el.id, 'y', v)} />

                      {/* Size (for value, line, rect) */}
                      {(el.type === 'value' || el.type === 'line' || el.type === 'rect') && (
                        <>
                          <NumInput label="Breite" value={el.width ?? 370} onChange={(v) => updateElement(el.id, 'width', v)} />
                          <NumInput label="Hoehe" value={el.height ?? 90} onChange={(v) => updateElement(el.id, 'height', v)} />
                        </>
                      )}

                      {/* Font size (for value, label) */}
                      {(el.type === 'value' || el.type === 'label') && (
                        <NumInput label="Schrift" value={el.font_size} onChange={(v) => updateElement(el.id, 'font_size', v)} />
                      )}

                      {/* Font weight */}
                      {(el.type === 'value' || el.type === 'label') && (
                        <div className="w-20">
                          <div className="text-[10px] text-gray-400">Gewicht</div>
                          <select className="w-full border border-gray-300 rounded px-1.5 py-1 text-xs"
                            value={el.font_weight} onChange={(e) => updateElement(el.id, 'font_weight', e.target.value)}>
                            <option value="normal">normal</option>
                            <option value="bold">bold</option>
                          </select>
                        </div>
                      )}

                      {/* Text align (for label) */}
                      {el.type === 'label' && (
                        <div className="w-20">
                          <div className="text-[10px] text-gray-400">Ausrichtung</div>
                          <select className="w-full border border-gray-300 rounded px-1.5 py-1 text-xs"
                            value={el.text_align} onChange={(e) => updateElement(el.id, 'text_align', e.target.value)}>
                            <option value="left">links</option>
                            <option value="center">mitte</option>
                            <option value="right">rechts</option>
                          </select>
                        </div>
                      )}

                      {/* Style (for value) */}
                      {el.type === 'value' && (
                        <div className="w-20">
                          <div className="text-[10px] text-gray-400">Stil</div>
                          <select className="w-full border border-gray-300 rounded px-1.5 py-1 text-xs"
                            value={el.style} onChange={(e) => updateElement(el.id, 'style', e.target.value)}>
                            <option value="plain">plain</option>
                            <option value="card">card</option>
                          </select>
                        </div>
                      )}

                      {/* Icon (for value) */}
                      {el.type === 'value' && (
                        <div className="w-28">
                          <div className="text-[10px] text-gray-400">Icon</div>
                          <select className="w-full border border-gray-300 rounded px-1.5 py-1 text-xs"
                            value={el.icon || ''} onChange={(e) => updateElement(el.id, 'icon', e.target.value || null)}>
                            {ICONS.map((i) => <option key={i} value={i}>{i || '— kein Icon —'}</option>)}
                          </select>
                        </div>
                      )}

                      {/* Datapoint (for value) */}
                      {el.type === 'value' && (
                        <div className="w-48">
                          <div className="text-[10px] text-gray-400">Datenpunkt</div>
                          <select className="w-full border border-gray-300 rounded px-1.5 py-1 text-xs"
                            value={el.datapoint_id || ''} onChange={(e) => updateElement(el.id, 'datapoint_id', e.target.value ? parseInt(e.target.value) : null)}>
                            <option value="">— keiner —</option>
                            {datapoints.map((d) => (
                              <option key={d.id} value={d.id}>{d.label || d.name}{d.value ? ` (${d.value}${d.unit ? ' ' + d.unit : ''})` : ''}</option>
                            ))}
                          </select>
                        </div>
                      )}

                      {/* Editable datapoint label + unit (for value with assigned datapoint) */}
                      {el.type === 'value' && dp && (
                        <>
                          <div className="w-40">
                            <div className="text-[10px] text-gray-400">Anzeigename</div>
                            <input className="w-full border border-gray-300 rounded px-1.5 py-1 text-xs"
                              defaultValue={dp.label || dp.name}
                              onBlur={(e) => { if (e.target.value !== (dp.label || dp.name)) updateDatapointLabel(dp.id, e.target.value); }}
                              placeholder="Anzeigename" />
                          </div>
                          <div className="w-16">
                            <div className="text-[10px] text-gray-400">Einheit</div>
                            <input className="w-full border border-gray-300 rounded px-1.5 py-1 text-xs"
                              defaultValue={dp.unit || ''}
                              onBlur={(e) => { if (e.target.value !== (dp.unit || '')) updateDatapointUnit(dp.id, e.target.value); }}
                              placeholder="z.B. W" />
                          </div>
                        </>
                      )}

                      {/* Static text (for label) */}
                      {el.type === 'label' && (
                        <div className="flex-1 min-w-48">
                          <div className="text-[10px] text-gray-400">Text</div>
                          <input className="w-full border border-gray-300 rounded px-1.5 py-1 text-xs"
                            defaultValue={el.static_text || ''} onBlur={(e) => updateElement(el.id, 'static_text', e.target.value)} />
                        </div>
                      )}
                    </div>
                  </div>
                );
              })}
            </div>

            {/* E-paper preview */}
            <h4 className="text-sm font-medium text-gray-600 mb-2">Vorschau ({selected.width}x{selected.height})</h4>
            <EpaperPreview
              layoutId={selected.id}
              elements={selected.elements}
              layoutWidth={selected.width}
              layoutHeight={selected.height}
            />
          </div>
        )}
      </div>
    </div>
  );
}
