import { useState, useCallback, useEffect } from 'react';
import { useProjectStore } from '../store/projectStore';
import { useUIStore } from '../store/uiStore';
import { useAnalysisStore } from '../store/analysisStore';

import MapViewer from '../components/map/MapViewer';
import ProcessGroupList from '../components/process/ProcessGroupList';
import ActionBar from '../components/io/ActionBar';
import StreamDataTable from '../components/analysis/StreamDataTable';
import './DataCollectionPage.css';
import TutorialPanel from '../components/ui/TutorialPanel';

export default function DataCollectionPage() {
  const state = useProjectStore((s) => s.state);
  const setMapCenter = useProjectStore((s) => s.setMapCenter);
  const setMapZoom = useProjectStore((s) => s.setMapZoom);
  const setMapLocked = useProjectStore((s) => s.setMapLocked);
  const setCurrentBase = useProjectStore((s) => s.setCurrentBase);
  const setProcesses = useProjectStore((s) => s.setProcesses);
  const setGroups = useProjectStore((s) => s.setGroups);
  const setGroupNames = useProjectStore((s) => s.setGroupNames);
  
  const selectedStreams = useAnalysisStore((s) => s.selectedStreams);
  const setSelectedStreams = useAnalysisStore((s) => s.setSelectedStreams);

  const [uiMode, setUiMode] = useState<'select' | 'analyze'>(
    state.map_locked ? 'analyze' : 'select'
  );
  const [addressSearch, setAddressSearch] = useState('');
  const [_searchResults, setSearchResults] = useState<any[]>([]);
  const [statusMsg, setStatusMsg] = useState<string | null>(null);

  // Auto-sync UI mode with map_locked state (e.g., when loading files)
  useEffect(() => {
    setUiMode(state.map_locked ? 'analyze' : 'select');
  }, [state.map_locked]);

  // Placement state
  const [placementTarget, setPlacementTarget] = useState<string | null>(null);

  // Measure state
  const [measureMode, setMeasureMode] = useState(false);
  const [measurePoints, setMeasurePoints] = useState<[number, number][]>([]);
  const [measureResult, setMeasureResult] = useState<string | null>(null);

  // Subprocess map view toggles
  const [subprocessMapExpanded, setSubprocessMapExpanded] = useState<
    Record<number, boolean>
  >({});

  const [showTutorial, setShowTutorial] = useState(false);
  const expandedGroups = useUIStore((s) => s.expandedGroups);
  const setExpandedGroups = (val: Set<number>) => useUIStore.getState().setGroupsExpanded(val);

  const handleElementDoubleClick = useCallback((type: 'group' | 'sub' | 'child' | 'stream', id: any, subId?: any) => {
    let pIdx = -1;
    let targetGIdx = -1;

    if (type === 'group') targetGIdx = id;
    else if (type === 'sub') {
      pIdx = id;
      targetGIdx = state.proc_groups.findIndex(g => g.includes(pIdx));
    } else if (type === 'child') {
      pIdx = id.subIdx;
      targetGIdx = state.proc_groups.findIndex(g => g.includes(pIdx));
    } else if (type === 'stream') {
      pIdx = id;
      targetGIdx = state.proc_groups.findIndex(g => g.includes(pIdx));
    }

    if (targetGIdx !== -1) {
      // ONLY expand this group
      setExpandedGroups(new Set([targetGIdx]));

      if (pIdx !== -1) {
        // ONLY expand this subprocess
        useUIStore.getState().setSubprocessExpanded(pIdx, true);
        useUIStore.getState().setActiveSection(pIdx, 'streams');
      }

      // Scroll with a slightly longer delay to allow expansion to paint
      setTimeout(() => {
        let scrollTargetId = `group-list-item-${targetGIdx}`;
        if (type === 'stream' && subId !== undefined) {
          scrollTargetId = `stream-editor-${pIdx}-${subId}`;
        } else if (pIdx !== -1) {
          scrollTargetId = `sub-card-${pIdx}`;
        }

        const el = document.getElementById(scrollTargetId);
        if (el) {
          el.scrollIntoView({ behavior: 'smooth', block: 'center' });
          // Highlight it briefly?
          el.style.outline = '2px solid var(--accent-primary)';
          setTimeout(() => { el.style.outline = 'none'; }, 2000);
        }
      }, 300);
    }
  }, [state.proc_groups]);

  // Resizable sidebar state
  const [sidebarWidth, setSidebarWidth] = useState(350);
  const [isResizing, setIsResizing] = useState(false);

  const startResizing = useCallback(() => {
    setIsResizing(true);
  }, []);

  const stopResizing = useCallback(() => {
    setIsResizing(false);
  }, []);

  const resize = useCallback(
    (e: any) => {
      if (isResizing) {
        // Limit width between 200 and 800
        const newWidth = Math.max(200, Math.min(800, e.clientX));
        setSidebarWidth(newWidth);
      }
    },
    [isResizing]
  );

  useEffect(() => {
    if (isResizing) {
      window.addEventListener('mousemove', resize);
      window.addEventListener('mouseup', stopResizing);
    }
    return () => {
      window.removeEventListener('mousemove', resize);
      window.removeEventListener('mouseup', stopResizing);
    };
  }, [isResizing, resize, stopResizing]);

  const lockMap = useCallback(
    (center: [number, number], zoom: number) => {
      setMapCenter(center);
      setMapZoom(zoom);
      setMapLocked(true);
      setUiMode('analyze');
      setStatusMsg('Map locked — click on map to place processes');
    },
    [setMapCenter, setMapZoom, setMapLocked]
  );

  const unlockMap = useCallback(() => {
    setMapLocked(false);
    setUiMode('select');
    setPlacementTarget(null);
    setMeasureMode(false);
    setStatusMsg(null);
  }, [setMapLocked]);

  const addProcessGroup = useCallback(() => {
    const processes = [...state.processes];
    const groups = [...state.proc_groups];
    const groupNames = [...state.proc_group_names];
    // Create a new empty subprocess (level 0 processes contain subprocesses)
    const newProcess = {
      name: `Subprocess ${processes.length + 1}`,
      lat: '',
      lon: '',
      box_scale: 1.0,
      next: '',
      hours: '',
      extra_info: { notes: '' },
      streams: [],
      children: [],
    };
    const newIdx = processes.length;
    processes.push(newProcess);
    groups.push([newIdx]);
    groupNames.push(`Process ${groups.length}`);

    setProcesses(processes);
    setGroups(groups);
    setGroupNames(groupNames);
    setStatusMsg(`Added Process ${groups.length}`);
  }, [state, setProcesses, setGroups, setGroupNames]);

  const handleAddressSearch = useCallback(async () => {
    if (!addressSearch.trim()) return;
    try {
      const resp = await fetch(
        `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(
          addressSearch
        )}`
      );
      const data = await resp.json();
      if (data.length > 0) {
        setSearchResults(data);
        const lat = parseFloat(data[0].lat);
        const lon = parseFloat(data[0].lon);
        setMapCenter([lat, lon]);
        setMapZoom(17);
        setStatusMsg(`Found: ${data[0].display_name}`);
      } else {
        setStatusMsg('No results found');
      }
    } catch {
      setStatusMsg('Search failed');
    }
  }, [addressSearch, setMapCenter, setMapZoom]);

  // Handle map click (for placement or measurement)
  const handleMapClick = useCallback(
    (lat: number, lon: number) => {
      if (placementTarget) {
        // Place process at clicked coordinates
        const processes = [...state.processes];
        // Parse target: "group_N", "sub_N", "child_N_M"
        if (placementTarget.startsWith('group_')) {
          const gIdx = parseInt(placementTarget.split('_')[1]);
          const coords = { ...state.proc_group_coordinates };
          coords[gIdx] = {
            ...(coords[gIdx] || {}),
            lat: lat.toString(),
            lon: lon.toString(),
          };
          useProjectStore.getState().setGroupCoordinates(coords);
        } else if (placementTarget.startsWith('child_')) {
          const parts = placementTarget.split('_');
          const subIdx = parseInt(parts[1]);
          const childIdx = parseInt(parts[2]);
          processes[subIdx] = { ...processes[subIdx] };
          processes[subIdx].children = [...(processes[subIdx].children || [])];
          processes[subIdx].children[childIdx] = {
            ...processes[subIdx].children[childIdx],
            lat: lat.toString(),
            lon: lon.toString(),
          };
          setProcesses(processes);
        } else {
          // sub_N — place subprocess
          const subIdx = parseInt(placementTarget.split('_')[1]);
          processes[subIdx] = {
            ...processes[subIdx],
            lat: lat.toString(),
            lon: lon.toString(),
          };
          setProcesses(processes);
        }
        setPlacementTarget(null);
        setStatusMsg('Placed successfully');
      } else if (measureMode) {
        const newPoints = [...measurePoints, [lat, lon] as [number, number]];
        setMeasurePoints(newPoints);
        if (newPoints.length === 2) {
          // Haversine distance
          const [lat1, lon1] = newPoints[0];
          const [lat2, lon2] = newPoints[1];
          const R = 6371000;
          const dLat = ((lat2 - lat1) * Math.PI) / 180;
          const dLon = ((lon2 - lon1) * Math.PI) / 180;
          const a =
            Math.sin(dLat / 2) ** 2 +
            Math.cos((lat1 * Math.PI) / 180) *
            Math.cos((lat2 * Math.PI) / 180) *
            Math.sin(dLon / 2) ** 2;
          const d = R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
          const distStr =
            d >= 1000
              ? `${(d / 1000).toFixed(2)} km`
              : `${d.toFixed(1)} m`;
          setMeasureResult(`Distance: ${distStr}`);
          setMeasureMode(false);
          setMeasurePoints([]);
        }
      }
    },
    [placementTarget, measureMode, measurePoints, state, setProcesses]
  );

  return (
    <div className="dc-page">
      {/* Action bar */}
      <ActionBar
        uiMode={uiMode}
        statusMsg={
          placementTarget
            ? `Click on map to place ${placementTarget}`
            : measureMode
              ? `Click ${2 - measurePoints.length} point(s) to measure`
              : measureResult || statusMsg
        }
        onMeasureToggle={() => {
          setMeasureMode(!measureMode);
          setMeasurePoints([]);
          setMeasureResult(null);
        }}
        measureActive={measureMode}
        currentBase={state.current_base || 'OpenStreetMap'}
        onBaseChange={(b) => setCurrentBase(b)}
        onLockMap={lockMap}
        onUnlockMap={unlockMap}
        onAddProcess={addProcessGroup}
        addressSearch={addressSearch}
        onAddressSearchChange={setAddressSearch}
        onAddressSearchSubmit={handleAddressSearch}
        showHelp={showTutorial}
        onHelpToggle={() => setShowTutorial(!showTutorial)}
      />

      <div className="dc-layout">
        {/* Left panel — process editor */}
        <div className="dc-left" style={{ width: sidebarWidth, flex: 'none' }}>
          {uiMode === 'select' ? (
            <div className="dc-select-controls">
              <p className="dc-hint">
                Pan and zoom the map, then click <strong>Lock map</strong> to
                begin editing processes.
              </p>
            </div>
          ) : (
            <>
              <ProcessGroupList
                processes={state.processes}
                groups={state.proc_groups}
                groupNames={state.proc_group_names}
                groupCoordinates={state.proc_group_coordinates}
                onProcessesChange={setProcesses}
                onGroupsChange={setGroups}
                onGroupNamesChange={setGroupNames}
                onGroupCoordinatesChange={(c) =>
                  useProjectStore.getState().setGroupCoordinates(c)
                }
                expandedGroups={expandedGroups}
                onExpandedGroupsChange={setExpandedGroups}
                onPlaceRequest={(target) => {
                  setPlacementTarget(target);
                  setStatusMsg(`Click on map to place ${target}`);
                }}
                placementTarget={placementTarget}
                subprocessMapExpanded={subprocessMapExpanded}
                onSubprocessMapToggle={(gIdx) =>
                  setSubprocessMapExpanded((prev) => ({
                    ...prev,
                    [gIdx]: !prev[gIdx],
                  }))
                }
              />
            </>
          )}
        </div>

        {/* Resizer handle */}
        <div className="dc-resizer" onMouseDown={startResizing} />

        {/* Right panel — map */}
        <div className="dc-right">
          {/* Removed redundant search bar — integrated into ActionBar */}

          <MapViewer
            height="750px"
            center={
              state.map_center?.length === 2
                ? (state.map_center as [number, number])
                : [51.707937580921694, 8.772205607882668]
            }
            zoom={state.map_zoom || 17}
            locked={uiMode === 'analyze'}
            processes={state.processes}
            groups={state.proc_groups}
            groupNames={state.proc_group_names}
            groupCoordinates={state.proc_group_coordinates}
            baseTile={state.current_base || 'OpenStreetMap'}
            onClick={handleMapClick}
            onMoveEnd={(center, zoom) => {
              if (uiMode === 'select') {
                setMapCenter(center);
                setMapZoom(zoom);
              }
            }}
            subprocessMapExpanded={subprocessMapExpanded}
            childMapExpanded={{}}
            onProcessesChange={setProcesses}
            onGroupCoordinatesChange={(c) =>
              useProjectStore.getState().setGroupCoordinates(c)
            }
            onElementDoubleClick={handleElementDoubleClick}
            selectedStreams={selectedStreams}
            onProcessesSelect={(idxs, val) => {
              const next = { ...selectedStreams };
              idxs.forEach((pi) => {
                const p = state.processes[pi];
                if (!p || !p.streams) return;
                p.streams.forEach((_, si) => {
                  next[`stream_${pi}_${si}`] = val;
                });
              });
              setSelectedStreams(next);
            }}
            allowMultiMove={true}
          />

          {/* Legend — directly below the map — VERY COMPACT */}
          {state.processes.some(p => (p.streams || []).length > 0 || (p.children || []).some(c => (c.streams || []).length > 0)) && (
            <div style={{ padding: '4px 10px', display: 'flex', alignItems: 'center', gap: 15, flexWrap: 'wrap', borderBottom: '1px solid var(--border)', background: 'var(--surface)' }}>
              <span style={{ fontSize: 10, fontWeight: 700, textTransform: 'uppercase', color: 'var(--text-muted)' }}>Legend</span>
              {/* Cold scale */}
              <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
                <span style={{ fontSize: 9, color: 'var(--text-muted)' }}>Cold</span>
                <div style={{ width: 40, height: 8, borderRadius: 4, background: 'linear-gradient(to right, rgb(100,150,255), rgb(0,30,180))' }} />
              </div>
              {/* Hot scale */}
              <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
                <span style={{ fontSize: 9, color: 'var(--text-muted)' }}>Hot</span>
                <div style={{ width: 40, height: 8, borderRadius: 4, background: 'linear-gradient(to right, rgb(255,120,120), rgb(180,0,0))' }} />
              </div>
              {/* Size */}
              <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
                {[3, 5, 8].map((r) => (
                  <svg key={r} width={r * 2 + 2} height={r * 2 + 2} style={{ display: 'block', flexShrink: 0 }}>
                    <circle cx={r + 1} cy={r + 1} r={r} fill="rgba(150,150,150,0.45)" stroke="var(--border-strong)" strokeWidth={1} />
                  </svg>
                ))}
                <span style={{ fontSize: 9, color: 'var(--text-muted)' }}>= Q power (kW)</span>
              </div>
            </div>
          )}


          {/* Notes */}
          <div className="card mt-md">
            <label>Project Notes</label>
            <textarea
              value={state.project_notes || ''}
              onChange={(e) =>
                useProjectStore.getState().setProjectNotes(e.target.value)
              }
              rows={4}
              style={{ width: '100%', marginTop: 4 }}
            />
          </div>

          {/* Stream data table — below project notes so it gets all remaining space */}
          <StreamDataTable
            processes={state.processes}
            groups={state.proc_groups}
            groupNames={state.proc_group_names}
            groupCoordinates={state.proc_group_coordinates}
          />
          <TutorialPanel isOpen={showTutorial} onClose={() => setShowTutorial(false)} />
        </div>
      </div>
    </div>
  );
}
