import { useState, useCallback, useMemo, useEffect } from 'react';
import { extractColorsFromSVG, extractStructuralGroups, rgbToLab } from './colorUtils';
import { buildFilteredSvgHtml } from './svgFilter';
import { exportPSD } from './psdExport';
import { buildStructuralColorGroups } from './grouping';

function LoadingOverlay({ text, progress, pct }) {
  return (
    <div className="loading-overlay" style={{ opacity: 1, pointerEvents: 'all' }}>
      <div className="spinner" />
      <div className="loading-text">{text}</div>
      <div className="loading-progress">{progress}</div>
      <div className="progress-bar-wrap">
        <div className="progress-bar-fill" style={{ width: `${pct}%` }} />
      </div>
    </div>
  );
}

function SwatchGroup({ group, colors, index, active, onClick }) {
  return (
    <div className={`swatch-group${active ? ' swatch-group-active' : ''}`} onClick={onClick}>
      <div className="group-label">Group {index + 1} ({group.length}色)</div>
      {group.map((ci) => (
        <div key={ci} className="swatch" style={{ backgroundColor: colors[ci].hex }} title={colors[ci].hex} />
      ))}
    </div>
  );
}

export default function App() {
  const [svgDoc, setSvgDoc] = useState(null);
  const [uniqueColors, setUniqueColors] = useState([]);
  const [loading, setLoading] = useState(null);
  const [exportStatus, setExportStatus] = useState('');
  const [dragActive, setDragActive] = useState(false);
  const [previewHtml, setPreviewHtml] = useState('');
  const [visibleLayers, setVisibleLayers] = useState(null);
  const [structuralGroups, setStructuralGroups] = useState(null);
  const [loadError, setLoadError] = useState('');

  const groups = useMemo(() => {
    if (!structuralGroups) return [];
    const avgL = (group) => {
      let sum = 0;
      for (const ci of group) {
        const c = uniqueColors[ci];
        sum += rgbToLab(c.r, c.g, c.b)[0];
      }
      return sum / group.length;
    };
    const g = [...structuralGroups];
    g.sort((a, b) => avgL(b) - avgL(a));
    return g;
  }, [structuralGroups, uniqueColors]);

  // Reset visibility when groups change
  useEffect(() => { setVisibleLayers(null); }, [groups]);

  const compositePreview = useMemo(() => {
    if (!svgDoc || groups.length === 0) return previewHtml;
    if (visibleLayers === null) return previewHtml;
    if (visibleLayers.size === 0) return '';
    const mergedColors = new Set();
    for (const gi of visibleLayers) {
      for (const ci of groups[gi]) {
        mergedColors.add(uniqueColors[ci].hex);
      }
    }
    return buildFilteredSvgHtml(svgDoc, mergedColors);
  }, [svgDoc, groups, uniqueColors, visibleLayers, previewHtml]);

  const loadSVG = useCallback(async (text) => {
    setVisibleLayers(null);
    setStructuralGroups(null);
    setLoadError('');
    setLoading({ text: 'SVGを解析中...', progress: '', pct: 0 });
    await tick();

    const parser = new DOMParser();
    const doc = parser.parseFromString(text, 'image/svg+xml');
    const svgEl = doc.querySelector('svg');
    if (!svgEl) { setLoading(null); return; }

    setSvgDoc(doc);
    setPreviewHtml(new XMLSerializer().serializeToString(svgEl));

    setLoading({ text: '色を抽出中...', progress: '', pct: 30 });
    await tick();
    const colors = extractColorsFromSVG(svgEl);
    setUniqueColors(colors);

    const structure = extractStructuralGroups(svgEl);
    if (structure) {
      setLoading({ text: '構造ベースのグループ化...', progress: `${structure.anchors.length}アンカー + ${structure.strokes.length}ストローク`, pct: 60 });
      await tick();
      const sGroups = buildStructuralColorGroups(structure, colors);
      setStructuralGroups(sGroups);
    } else {
      setStructuralGroups(null);
      setLoadError('色グループ構造（<g fill>）が見つかりません。Vectorizer.aiで Group By を Color に設定してエクスポートしてください。');
    }

    setVisibleLayers(null);
    setLoading(null);
  }, []);

  const handleFile = useCallback((file) => {
    if (!file || !file.name.toLowerCase().endsWith('.svg')) return;
    const reader = new FileReader();
    reader.onload = (e) => loadSVG(e.target.result);
    reader.readAsText(file);
  }, [loadSVG]);

  const handleExport = useCallback(async () => {
    if (!svgDoc || groups.length === 0) return;
    setExportStatus('');
    setLoading({ text: 'PSDエクスポート準備中...', progress: '', pct: 0 });
    try {
      await exportPSD(svgDoc, groups, uniqueColors, (text, progress, pct) => {
        setLoading({ text, progress, pct });
      });
      setLoading(null);
      setExportStatus('エクスポート完了!');
    } catch (err) {
      setLoading(null);
      setExportStatus(`エラー: ${err.message}`);
      console.error(err);
    }
  }, [svgDoc, groups, uniqueColors]);

  const onDragOver = useCallback((e) => { e.preventDefault(); setDragActive(true); }, []);
  const onDragLeave = useCallback(() => setDragActive(false), []);
  const onDrop = useCallback((e) => {
    e.preventDefault();
    setDragActive(false);
    if (e.dataTransfer.files.length) handleFile(e.dataTransfer.files[0]);
  }, [handleFile]);

  const toggleLayer = (gi) => {
    setVisibleLayers((prev) => {
      if (prev === null) {
        const next = new Set(Array.from({ length: groups.length }, (_, i) => i));
        next.delete(gi);
        return next;
      }
      const next = new Set(prev);
      if (next.has(gi)) next.delete(gi);
      else next.add(gi);
      if (next.size === groups.length) return null;
      return next;
    });
  };

  const isLayerVisible = (gi) => visibleLayers === null || visibleLayers.has(gi);
  const loaded = uniqueColors.length > 0;

  return (
    <>
      <div className="header">
        <h1>SVG Color Grouper → PSD</h1>
      </div>
      <div
        className={`container${dragActive ? ' drag-active' : ''}`}
        onDragOver={onDragOver}
        onDragLeave={onDragLeave}
        onDrop={onDrop}
      >
        <div className="sidebar">
          <div className="section">
            <h3>入力</h3>
            <label className="file-btn" htmlFor="svg-input">SVGファイルを選択</label>
            <input type="file" id="svg-input" accept=".svg"
              onChange={(e) => handleFile(e.target.files[0])} />
            {loaded && !loadError && <div className="status">
              {uniqueColors.length}色を検出 ({groups.length}グループ)
            </div>}
            {loadError && <div className="status error">{loadError}</div>}
          </div>

          {loaded && groups.length > 0 && (
            <div className="section">
              <h3>出力</h3>
              <button className="export-btn" onClick={handleExport}>
                PSDエクスポート
              </button>
              {exportStatus && <div className="status">{exportStatus}</div>}
            </div>
          )}

          {loaded && groups.length > 0 && (
            <div className="section">
              <h3>色グループ ({groups.length}グループ / クリックで表示切替)</h3>
              <div className="swatches">
                {groups.map((group, gi) => (
                  <SwatchGroup
                    key={gi} group={group} colors={uniqueColors} index={gi}
                    active={isLayerVisible(gi)}
                    onClick={() => toggleLayer(gi)}
                  />
                ))}
              </div>
            </div>
          )}
        </div>

        <div className="main">
          {compositePreview ? (
            <div className="preview-area" dangerouslySetInnerHTML={{ __html: compositePreview }} />
          ) : (
            <div className="preview-area">
              <div className="info">
                {loaded ? 'レイヤーを選択してください' : 'SVGファイルをドラッグ＆ドロップ、または左のボタンから選択'}
              </div>
            </div>
          )}
        </div>
      </div>

      {loading && (
        <LoadingOverlay text={loading.text} progress={loading.progress} pct={loading.pct} />
      )}
    </>
  );
}

function tick() {
  return new Promise((r) => setTimeout(r, 0));
}
