import { useState, useEffect, useMemo } from 'react';
import { StatsPanel } from './components/StatsPanel';
import { PeriodSelector } from './components/PeriodSelector';
import { HeatMap } from './components/HeatMap';
import { FlowMap } from './components/FlowMap';
import { AnimationPlayer } from './components/AnimationPlayer';
import { SearchBar } from './components/SearchBar';
import { fetchData, fetchMemberCities } from './services/DataService';
import type { PeriodStats, MemberCity } from './services/DataService';
import type { Transaction } from './data/mockData';
import type { TransactionArc } from './data/arcData';
import { computeStats } from './data/mockData';
import { computeFlowStats } from './data/arcData';
import { useAnimation } from './hooks/useAnimation';
import { useMediaQuery } from './hooks/useMediaQuery';
import { InfoPanel } from './components/InfoPanel';
import { initialUrlState, useUrlSync } from './hooks/useUrlState';

export default function App() {
  const [periodDays, setPeriodDays] = useState(initialUrlState.period);
  const [transactions, setTransactions] = useState<Transaction[]>([]);
  const [arcs, setArcs] = useState<TransactionArc[]>([]);
  const [stats, setStats] = useState<PeriodStats | null>(null);
  const [loading, setLoading] = useState(true);
  const [refreshing, setRefreshing] = useState(false);
  const [lastUpdate, setLastUpdate] = useState<Date | null>(null);
  const [source, setSource] = useState<'live' | 'mock'>('mock');
  const [currentUD, setCurrentUD] = useState<number>(11.78);
  const [allTimestamps, setAllTimestamps] = useState<number[]>([]);
  const [viewMode, setViewMode] = useState<'heatmap' | 'flow'>(initialUrlState.view);
  const [focusCity, setFocusCity] = useState<string | null>(initialUrlState.city);
  const [panelOpen, setPanelOpen] = useState(false);
  const [infoOpen, setInfoOpen] = useState(false);
  const [showMembers, setShowMembers] = useState(false);
  const [memberCities, setMemberCities] = useState<MemberCity[]>([]);
  const [membersLoading, setMembersLoading] = useState(false);
  const [endpointVersion, setEndpointVersion] = useState(0);
  const isMobile = useMediaQuery('(max-width: 639px)');

  const toggleMembers = async () => {
    if (showMembers) { setShowMembers(false); return; }
    if (memberCities.length > 0) { setShowMembers(true); return; }
    setMembersLoading(true);
    try {
      const cities = await fetchMemberCities();
      setMemberCities(cities);
      setShowMembers(true);
    } catch (err) {
      console.warn('fetchMemberCities error:', err);
    } finally {
      setMembersLoading(false);
    }
  };

  const animation = useAnimation(transactions, arcs, periodDays, allTimestamps);

  // Synchronise l'état dans l'URL (deep link / partage)
  useUrlSync(periodDays, viewMode, focusCity);

  const handlePeriodChange = (days: number) => {
    animation.deactivate();
    setPeriodDays(days);
  };

  const handleViewModeChange = (mode: 'heatmap' | 'flow') => {
    setViewMode(mode);
    setFocusCity(null);
  };

  // Raccourcis clavier
  useEffect(() => {
    const onKey = (e: KeyboardEvent) => {
      if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) return;
      if (e.key === 'ArrowLeft' && animation.active) {
        animation.seek(Math.max(0, animation.currentIndex - 1));
        e.preventDefault();
      } else if (e.key === 'ArrowRight' && animation.active) {
        animation.seek(Math.min(animation.frames.length - 1, animation.currentIndex + 1));
        e.preventDefault();
      } else if (e.key === ' ' && animation.active) {
        animation.playing ? animation.pause() : animation.play();
        e.preventDefault();
      } else if (e.key === 'Escape') {
        if (infoOpen) { setInfoOpen(false); e.preventDefault(); }
        else if (animation.active) { animation.deactivate(); e.preventDefault(); }
      } else if (e.key === 'h' || e.key === 'H') {
        handleViewModeChange(viewMode === 'heatmap' ? 'flow' : 'heatmap');
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [animation.active, animation.playing, animation.currentIndex, animation.frames.length, infoOpen, viewMode]);

  useEffect(() => {
    let cancelled = false;

    const load = (showLoading: boolean) => {
      if (showLoading) setLoading(true);
      else setRefreshing(true);
      fetchData(periodDays)
        .then(({ transactions, arcs, stats, source, currentUD, allTimestamps }) => {
          if (!cancelled) {
            setTransactions(transactions);
            setArcs(arcs);
            setStats(stats);
            setSource(source);
            setCurrentUD(currentUD);
            setAllTimestamps(allTimestamps);
            setLastUpdate(new Date());
          }
        })
        .catch((err) => console.warn('Ğ1Flux refresh error:', err))
        .finally(() => {
          if (!cancelled) { setLoading(false); setRefreshing(false); }
        });
    };

    load(true);
    const interval = setInterval(() => load(false), 30_000);

    return () => { cancelled = true; clearInterval(interval); };
  }, [periodDays, endpointVersion]);

  // Stats heatmap sur la fenêtre courante en mode animation
  const visibleStats: PeriodStats | null = animation.active
    ? {
        ...computeStats(animation.visibleTransactions),
        geoCount: animation.visibleTransactions.length,
        transactionCount: animation.frameTotalCount ?? animation.visibleTransactions.length,
      }
    : stats;

  // Stats flux (recalculées sur les arcs visibles)
  const flowStats = useMemo(
    () => {
      const activeArcs = animation.active ? animation.visibleArcs : arcs;
      return activeArcs.length > 0 ? computeFlowStats(activeArcs) : null;
    },
    [arcs, animation.visibleArcs, animation.active],
  );

  const statsPanelProps = {
    stats: visibleStats,
    loading,
    periodDays,
    source,
    currentUD,
    animationLabel: animation.active ? (animation.currentFrame?.label ?? undefined) : undefined,
    viewMode,
    flowStats,
    focusCity,
    allTimestamps,
    onEndpointChange: () => setEndpointVersion((v) => v + 1),
  };

  return (
    <div className="flex h-svh w-full overflow-hidden bg-[#0a0b0f] text-white">
      {/* Side panel — desktop uniquement */}
      {!isMobile && <StatsPanel {...statsPanelProps} />}

      {/* Map area */}
      <div className="relative flex-1 min-w-0">
        {viewMode === 'heatmap' ? (
          <HeatMap
            transactions={animation.visibleTransactions}
            memberCities={showMembers ? memberCities : []}
          />
        ) : (
          <FlowMap
            arcs={animation.active ? animation.visibleArcs : arcs}
            focusCity={focusCity}
            onCityClick={setFocusCity}
          />
        )}

        {/* Bouton menu — mobile uniquement */}
        {isMobile && (
          <button
            onClick={() => setPanelOpen(true)}
            className="absolute top-4 left-4 z-[1001] w-10 h-10 bg-[#0a0b0f]/90 backdrop-blur-sm border border-[#2e2f3a] rounded-xl flex items-center justify-center text-[#d4a843] text-lg"
            aria-label="Ouvrir le panneau"
          >
            ☰
          </button>
        )}

        {/* Bouton info — sous ☰ sur mobile, top-left sur desktop */}
        <button
          onClick={() => setInfoOpen(true)}
          className={`absolute ${isMobile ? 'top-16' : 'top-4'} left-4 z-[1001] w-10 h-10 bg-[#0a0b0f]/90 backdrop-blur-sm border border-[#2e2f3a] rounded-xl flex items-center justify-center text-[#6b7280] hover:text-[#d4a843] transition-colors text-base`}
          aria-label="Aide"
        >
          ℹ
        </button>

        {/* Barre de recherche identité */}
        <div className={`absolute ${isMobile ? 'top-28' : 'top-16'} left-4 z-[1001]`}>
          <SearchBar
            onResult={(city) => {
              setViewMode('flow');
              setFocusCity(city);
            }}
          />
        </div>

        {/* Toggle overlay membres DU */}
        <button
          onClick={toggleMembers}
          disabled={membersLoading}
          title={showMembers ? 'Masquer les membres' : 'Afficher les membres Ğ1 actifs géolocalisés'}
          className={`absolute ${isMobile ? 'top-40' : 'top-28'} left-4 z-[1001] w-10 h-10 backdrop-blur-sm border rounded-xl flex items-center justify-center text-sm transition-colors
            ${showMembers
              ? 'bg-[#00c853]/20 border-[#00c853]/60 text-[#00c853]'
              : 'bg-[#0a0b0f]/90 border-[#2e2f3a] text-[#6b7280] hover:text-[#00c853]'
            }`}
          aria-label="Membres DU"
        >
          {membersLoading ? <span className="animate-spin inline-block text-xs">↻</span> : 'DU'}
        </button>

        {/* Period selector — floating over map */}
        <div className={`absolute top-4 z-[1000] ${isMobile ? 'left-16 right-4' : 'left-1/2 -translate-x-1/2'}`}>
          <PeriodSelector
            value={periodDays}
            onChange={handlePeriodChange}
            animationActive={animation.active}
            onAnimate={() => animation.active ? animation.deactivate() : animation.activate()}
            viewMode={viewMode}
            onViewModeChange={handleViewModeChange}
            geoPercent={visibleStats && visibleStats.transactionCount > 0
              ? Math.round((visibleStats.geoCount / visibleStats.transactionCount) * 100)
              : null}
          />
        </div>

        {/* Badge ville focus — mobile uniquement */}
        {isMobile && focusCity && (
          <div className="absolute top-20 left-1/2 -translate-x-1/2 z-[1001] flex items-center gap-2 bg-[#0a0b0f]/90 backdrop-blur-sm border border-[#d4a843]/40 rounded-full px-3 py-1.5">
            <span className="text-[#d4a843] text-xs font-medium">{focusCity}</span>
            <button onClick={() => setFocusCity(null)} className="text-[#4b5563] hover:text-white text-xs leading-none">✕</button>
          </div>
        )}

        {/* Transaction count + source badge (masqués sur mobile et en mode animation) */}
        {!loading && !animation.active && !isMobile && (
          <div className="absolute bottom-8 left-1/2 -translate-x-1/2 z-[1000] flex items-center gap-2">
            <div className="bg-[#0a0b0f]/80 backdrop-blur-sm border border-[#2e2f3a] rounded-full px-4 py-1.5 text-xs text-[#6b7280]">
              <span className="text-[#d4a843] font-medium">{transactions.length}</span> transactions affichées
            </div>
            <div className={`backdrop-blur-sm border rounded-full px-3 py-1.5 text-xs font-medium ${
              source === 'live'
                ? 'bg-emerald-950/80 border-emerald-700 text-emerald-400'
                : 'bg-[#0a0b0f]/80 border-[#2e2f3a] text-[#4b5563]'
            }`}>
              {source === 'live'
                ? <>{refreshing ? <span className="animate-spin inline-block">↻</span> : '●'} live Ğ1v2{lastUpdate && <span className="ml-1 opacity-60">{lastUpdate.toLocaleTimeString('fr-FR')}</span>}</>
                : '○ mock'}
            </div>
          </div>
        )}

        {/* Animation player */}
        {animation.active && (
          <AnimationPlayer
            frames={animation.frames}
            currentIndex={animation.currentIndex}
            playing={animation.playing}
            speed={animation.speed}
            onSeek={animation.seek}
            onPlay={animation.play}
            onPause={animation.pause}
            onSpeedChange={animation.setSpeed}
          />
        )}

        {/* Loading overlay */}
        {loading && (
          <div className="absolute inset-0 z-[999] flex items-center justify-center bg-[#0a0b0f]/60 backdrop-blur-sm">
            <div className="flex flex-col items-center gap-3">
              <div className="w-10 h-10 rounded-full border-2 border-[#d4a843] border-t-transparent animate-spin" />
              <p className="text-[#d4a843] text-sm">Chargement des flux…</p>
            </div>
          </div>
        )}
      </div>

      {/* Info panel */}
      {infoOpen && <InfoPanel onClose={() => setInfoOpen(false)} />}

      {/* Bottom drawer — mobile uniquement */}
      {isMobile && (
        <>
          {/* Overlay */}
          {panelOpen && (
            <div
              className="fixed inset-0 z-[1009] bg-black/50"
              onClick={() => setPanelOpen(false)}
            />
          )}
          {/* Drawer */}
          <div
            className={`fixed bottom-0 left-0 right-0 z-[1010] h-[85vh] flex flex-col transition-transform duration-300 ${panelOpen ? 'translate-y-0' : 'translate-y-full'}`}
          >
            <div className="flex justify-center pt-2 pb-1 bg-[#0a0b0f] rounded-t-2xl border-t border-x border-[#2e2f3a] shrink-0">
              <div className="w-10 h-1 rounded-full bg-[#2e2f3a]" />
            </div>
            <StatsPanel {...statsPanelProps} onClose={() => setPanelOpen(false)} className="w-full flex-1 min-h-0" />
          </div>
        </>
      )}
    </div>
  );
}
