import { 
  Box, 
  Heading, 
  Text, 
  Spinner, 
  Alert, 
  AlertIcon, 
  Table, 
  Thead, 
  Tbody, 
  Tr, 
  Th, 
  Td, 
  HStack, 
  Badge, 
  Button, 
  useToast, 
  Drawer, 
  DrawerOverlay, 
  DrawerContent, 
  DrawerHeader, 
  DrawerBody, 
  DrawerFooter, 
  FormControl, 
  FormLabel, 
  Input, 
  Stack, 
  InputGroup, 
  InputRightElement, 
  List, 
  ListItem, 
  FormErrorMessage, 
  Image, 
  useBreakpointValue, 
  Wrap,
  WrapItem,
  useColorModeValue,
  Select
} from '@chakra-ui/react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import AdminLayout from '../../layouts/AdminLayout';
import { putMatchOverride, patchMatchOverride, searchClubs, uploadImage, fetchLogoAsBlob, uploadToLogaSportcreative, fetchTeamLogoOverrides } from '../../services/adminMatches';
import { getPublicSettings } from '../../services/settings';
 
import { useEffect, useMemo, useRef, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import { parse } from 'date-fns';
import { assetUrl } from '../../utils/url';
import { batchFetchLogosFromSportLogosAPI } from '../../utils/sportLogosAPI';
import { API_URL } from '../../services/api';

const MatchesAdminPage = () => {
  const queryClient = useQueryClient();
  const toast = useToast();
  const [isOpen, setIsOpen] = useState(false);
  const [focusSide, setFocusSide] = useState<'home' | 'away' | null>(null);
  const [selected, setSelected] = useState<any | null>(null);
  const [form, setForm] = useState({
    home_name_override: '',
    away_name_override: '',
    venue_override: '',
    date_time_override: '',
    home_logo_url: '',
    away_logo_url: '',
    notes: '',
  });

  const { data: overrides = {} } = useQuery({
    queryKey: ['teamLogoOverrides'],
    queryFn: fetchTeamLogoOverrides,
    staleTime: 5 * 60 * 1000,
  });

  const normalizeName = (s: string) => {
    let out = String(s || '');
    out = out
      .normalize('NFD')
      .replace(/[\u0300-\u036f]/g, '')
      .toLowerCase();
    out = out.replace(/[\u2012\u2013\u2014\u2015\u2212]/g, '-');
    const orgPhrases = [
      'fotbalovy klub',
      'sportovni klub',
      'telovychovna jednota',
      'skolni sportovni klub',
      'fotbal',
      'futsal',
    ];
    for (const phrase of orgPhrases) {
      const re = new RegExp(`(^|\\b)${phrase}(\\b|$)`, 'g');
      out = out.replace(re, ' ');
    }
    out = out.replace(/\b(1\.)?\s*(sfc|afc|fc|fk|mfk|tj|sk|afk)\b\.?/g, ' ');
    out = out.replace(/[\.,!;:()\[\]{}]/g, ' ');
    out = out.replace(/\s+/g, ' ').trim();
    return out;
  };

  const byName: Record<string, string> = (overrides as any)?.by_name || {};
  const byNameNormalized = useMemo(() => {
    const idx: Record<string, string> = {};
    for (const k of Object.keys(byName)) idx[normalizeName(k)] = byName[k];
    return idx;
  }, [byName]);

  const [sportLogosMap, setSportLogosMap] = useState<Record<string, string>>({});
  

  const getLogo = (teamName?: string, teamId?: string, facrOriginal?: string) => {
    if (!teamName) return assetUrl('/dist/img/logo-club-empty.svg') as string;
    if (teamId && sportLogosMap[String(teamId)]) return sportLogosMap[String(teamId)];
    let overrideUrl = byName[teamName];
    if (!overrideUrl) overrideUrl = byNameNormalized[normalizeName(teamName)];
    if (overrideUrl) {
      if (overrideUrl.startsWith('/')) return assetUrl(overrideUrl) as string;
      return overrideUrl;
    }
    if (facrOriginal) return facrOriginal;
    return '/dist/img/logo-club-empty.svg';
  };

  // External logo upload helpers/state
  const [homeExternalTeamId, setHomeExternalTeamId] = useState<string>('');
  const [awayExternalTeamId, setAwayExternalTeamId] = useState<string>('');
  const [homeUploadedFile, setHomeUploadedFile] = useState<File | null>(null);
  const [awayUploadedFile, setAwayUploadedFile] = useState<File | null>(null);

  // Team search state
  const [homeQuery, setHomeQuery] = useState('');
  const [awayQuery, setAwayQuery] = useState('');
  const [debouncedHome, setDebouncedHome] = useState('');
  const [debouncedAway, setDebouncedAway] = useState('');
  useEffect(() => {
    const t = setTimeout(() => setDebouncedHome(homeQuery), 300);
    return () => clearTimeout(t);
  }, [homeQuery]);
  useEffect(() => {
    const t = setTimeout(() => setDebouncedAway(awayQuery), 300);
    return () => clearTimeout(t);
  }, [awayQuery]);
  const { data: homeResults = [] } = useQuery({
    queryKey: ['club-search-home', debouncedHome],
    queryFn: () => searchClubs(debouncedHome),
    enabled: debouncedHome.trim().length >= 2,
  });
  const { data: awayResults = [] } = useQuery({
    queryKey: ['club-search-away', debouncedAway],
    queryFn: () => searchClubs(debouncedAway),
    enabled: debouncedAway.trim().length >= 2,
  });

  // Upload refs
  const homeFileRef = useRef<HTMLInputElement | null>(null);
  const awayFileRef = useRef<HTMLInputElement | null>(null);

  const { data: matches = [], isLoading, error } = useQuery<any[], Error>({
    queryKey: ['admin-matches-list-cache'],
    queryFn: async () => {
      // Read cached FACR club info
      const origin = new URL(API_URL, typeof window !== 'undefined' ? window.location.origin : 'http://localhost:3000').origin;
      const url = `${origin}/cache/prefetch/facr_club_info.json`;
      const res = await fetch(url, { headers: { 'Cache-Control': 'no-cache' } });
      if (!res.ok) throw new Error(`Failed to load cache: ${res.status}`);
      const json = await res.json();

      const comps = Array.isArray(json?.competitions) ? json.competitions : [];
      const items: any[] = comps.flatMap((c: any) =>
        (Array.isArray(c.matches) ? c.matches : []).map((m: any) => ({ ...m, competitionName: c.name, competition_id: c.id }))
      );

      // Optional: stable sort by date ascending
      const FACR_DATE_FMT = 'dd.MM.yyyy HH:mm';
      items.sort((a, b) => {
        const da = parse(String(a.date_time || a.date), FACR_DATE_FMT, new Date()).getTime();
        const db = parse(String(b.date_time || b.date), FACR_DATE_FMT, new Date()).getTime();
        return da - db;
      });

      return items.map((m: any) => ({
        id: m.match_id,
        date_time: m.date_time || m.date,
        competitionName: m.competitionName,
        competition_id: m.competition_id,
        home: m.home || m.home_team,
        home_id: m.home_id || m.home_team_id || m.home_team_facr_id,
        away: m.away || m.away_team,
        away_id: m.away_id || m.away_team_id || m.away_team_facr_id,
        score: m.score,
        venue: m.venue,
        home_logo_url: m.home_logo_url,
        away_logo_url: m.away_logo_url,
      }));
    },
  });
  useEffect(() => {
    if (!Array.isArray(matches) || matches.length === 0) return;
    const ids = new Set<string>();
    for (const m of matches as any[]) {
      if (m.home_id) ids.add(String(m.home_id));
      if (m.away_id) ids.add(String(m.away_id));
    }
    if (ids.size === 0) return;
    (async () => {
      try {
        const map = await batchFetchLogosFromSportLogosAPI(Array.from(ids));
        setSportLogosMap(map);
      } catch (e) {
        console.warn('Failed to batch fetch logos:', e);
      }
    })();
  }, [matches]);
  
  // Filters
  const [teamFilter, setTeamFilter] = useState('');
  const [dateFrom, setDateFrom] = useState<string>(''); // YYYY-MM-DD
  const [dateTo, setDateTo] = useState<string>(''); // YYYY-MM-DD
  const [competitionFilter, setCompetitionFilter] = useState<string>('');
  const [sideFilter, setSideFilter] = useState<'home' | 'away' | ''>('');
  const normalizedTeam = teamFilter.trim().toLowerCase();
  const FACR_DATE_FMT = 'dd.MM.yyyy HH:mm';
  // Club name (for side filter)
  const { data: publicSettings } = useQuery({
    queryKey: ['public-settings'],
    queryFn: getPublicSettings,
  });
  const { data: facrClubInfo } = useQuery({
    queryKey: ['facr-club-info-name'],
    queryFn: async () => {
      const origin = new URL(API_URL, typeof window !== 'undefined' ? window.location.origin : 'http://localhost:3000').origin;
      const url = `${origin}/cache/prefetch/facr_club_info.json`;
      const res = await fetch(url, { headers: { 'Cache-Control': 'no-cache' } });
      if (!res.ok) return null;
      return await res.json();
    },
  });
  const clubName: string = (publicSettings as any)?.club_name || (facrClubInfo as any)?.name || '';
  const normalize = (s: string) => String(s || '')
    .normalize('NFD')
    .replace(/[\u0300-\u036f]/g, '')
    .replace(/\s+/g, ' ')
    .trim()
    .toLowerCase();
  const stripPrefixes = (s: string) => {
    let x = normalize(s);
    // Common Czech club prefixes/words
    x = x.replace(/\b(mestsky|m\.?f\.?k\.?|mfk|tj|sk|sokol|fotbalovy|fotbalový|fotbalovy\s+klub|fotbalovy\s+klub)\b/g, '').replace(/\s+/g, ' ').trim();
    return x;
  };
  const clubNorm = normalize(clubName);
  const clubStrip = stripPrefixes(clubName);
  const teamMatchesClub = (team: string): boolean => {
    const t = normalize(team);
    const ts = stripPrefixes(team);
    return !!clubNorm && (t.includes(clubNorm) || ts.includes(clubStrip) || t.endsWith(clubStrip) || clubStrip.endsWith(ts));
  };
  const competitionOptions = useMemo(() => {
    const set = new Set<string>();
    for (const m of matches) {
      if (m.competitionName) set.add(String(m.competitionName));
    }
    return Array.from(set).sort((a, b) => a.localeCompare(b));
  }, [matches]);
  const filteredMatches = matches.filter((m: any) => {
    // team filter
    const teamOk = normalizedTeam
      ? (
          sideFilter === 'home'
            ? [m.home, m.home_team].filter(Boolean).some((v: string) => String(v).toLowerCase().includes(normalizedTeam))
            : sideFilter === 'away'
            ? [m.away, m.away_team].filter(Boolean).some((v: string) => String(v).toLowerCase().includes(normalizedTeam))
            : [m.home, m.home_team, m.away, m.away_team]
                .filter(Boolean)
                .some((v: string) => String(v).toLowerCase().includes(normalizedTeam))
        )
      : true;
    if (!teamOk) return false;

    // competition filter
    if (competitionFilter && String(m.competitionName || '') !== competitionFilter) return false;

    // side filter based on club name
    if (sideFilter && clubNorm) {
      const homeName = String(m.home || m.home_team || '');
      const awayName = String(m.away || m.away_team || '');
      if (sideFilter === 'home' && !teamMatchesClub(homeName)) return false;
      if (sideFilter === 'away' && !teamMatchesClub(awayName)) return false;
    }

    // date parse
    const dtStr = String(m.date_time || m.date || '');
    let ts = NaN;
    try {
      ts = parse(dtStr, FACR_DATE_FMT, new Date()).getTime();
    } catch (_) {
      const d2 = new Date(dtStr);
      ts = d2.getTime();
    }
    if (isNaN(ts)) return true; // if can't parse, let it pass other filters

    // date range filter
    if (dateFrom) {
      const fromTs = new Date(dateFrom + 'T00:00:00').getTime();
      if (!isNaN(fromTs) && ts < fromTs) return false;
    }
    if (dateTo) {
      const toTs = new Date(dateTo + 'T23:59:59').getTime();
      if (!isNaN(toTs) && ts > toTs) return false;
    }
    return true;
  });

  // Pagination (Load more) + page size selector
  const [pageSize, setPageSize] = useState(50);
  const [limit, setLimit] = useState(50);
  const [searchParams, setSearchParams] = useSearchParams();

  // Initialize filters from URL on first load and when data changes (so comps are known)
  useEffect(() => {
    const spTeam = searchParams.get('team') || '';
    const spFrom = searchParams.get('from') || '';
    const spTo = searchParams.get('to') || '';
    const spComp = searchParams.get('comp') || '';
    const spVenue = searchParams.get('venue') || '';
    const spSide = searchParams.get('side') || '';
    const spSize = parseInt(searchParams.get('size') || '') || undefined;
    const spLimit = parseInt(searchParams.get('limit') || '') || undefined;
    if (spTeam) setTeamFilter(spTeam);
    if (spFrom) setDateFrom(spFrom);
    if (spTo) setDateTo(spTo);
    if (spComp) setCompetitionFilter(spComp);
    // venue filter removed
    if (spSide === 'home' || spSide === 'away') setSideFilter(spSide);
    if (spSize) {
      setPageSize(spSize);
      setLimit(spSize);
    }
    if (spLimit) setLimit(spLimit);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Keep URL in sync when filters/pagination change
  useEffect(() => {
    const params: Record<string, string> = {};
    if (teamFilter) params.team = teamFilter;
    if (dateFrom) params.from = dateFrom;
    if (dateTo) params.to = dateTo;
    if (competitionFilter) params.comp = competitionFilter;
    // venue filter removed
    if (sideFilter) params.side = sideFilter;
    if (pageSize !== 50) params.size = String(pageSize);
    if (limit !== pageSize) params.limit = String(limit);
    setSearchParams(params, { replace: true });
  }, [teamFilter, dateFrom, dateTo, competitionFilter, sideFilter, pageSize, limit, setSearchParams]);
  useEffect(() => {
    // reset pagination on filter change
    setLimit(pageSize);
  }, [normalizedTeam, dateFrom, dateTo, competitionFilter, sideFilter, clubNorm, pageSize]);
  const visibleMatches = filteredMatches.slice(0, limit);

  // Date presets
  const setThisWeek = () => {
    const now = new Date();
    const day = now.getDay(); // 0 Sun .. 6 Sat
    const diffToMonday = (day === 0 ? -6 : 1 - day); // Monday start
    const monday = new Date(now);
    monday.setDate(now.getDate() + diffToMonday);
    const sunday = new Date(monday);
    sunday.setDate(monday.getDate() + 6);
    const f = monday.toISOString().slice(0, 10);
    const t = sunday.toISOString().slice(0, 10);
    setDateFrom(f);
    setDateTo(t);
  };
  const setNext30Days = () => {
    const now = new Date();
    const to = new Date(now);
    to.setDate(now.getDate() + 30);
    const f = now.toISOString().slice(0, 10);
    const t = to.toISOString().slice(0, 10);
    setDateFrom(f);
    setDateTo(t);
  };

  // Export CSV of filtered results
  const exportCsv = () => {
    const rows = filteredMatches.map((m: any) => {
      const date = m.date_time || m.date || '';
      const comp = m.competitionName || '';
      const home = m.home || m.home_team || '';
      const away = m.away || m.away_team || '';
      const score = m.score || (m.result_home != null && m.result_away != null ? `${m.result_home}:${m.result_away}` : '');
      const venue = m.venue || '';
      return { date, competition: comp, home, away, score, venue };
    });
    const headers = ['date', 'competition', 'home', 'away', 'score', 'venue'];
    const escape = (v: any) => {
      const s = String(v ?? '');
      if (/[",\n]/.test(s)) return '"' + s.replace(/"/g, '""') + '"';
      return s;
    };
    const csv = [headers.join(','), ...rows.map(r => headers.map(h => escape((r as any)[h])).join(','))].join('\n');
    const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'matches.csv';
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  };

  // Datetime validation (RFC3339-ish)
  const isDateInvalid = form.date_time_override.trim() !== '' && isNaN(Date.parse(form.date_time_override));

  const saveMutation = useMutation({
    mutationFn: async () => {
      const externalMatchId: string = selected?.match_id || selected?.id;
      if (!externalMatchId) throw new Error('Chybí match_id');
      const payload: any = { ...form };
      // normalize empty strings to null so backend can clear values
      Object.keys(payload).forEach((k) => {
        if (payload[k as keyof typeof payload] === '') payload[k as keyof typeof payload] = null;
      });
      // First store current overrides
      await putMatchOverride(externalMatchId, payload);

      // Best-effort upload to logoapi.sportcreative.eu for home/away
      const results: { home?: { success: boolean; error?: string }; away?: { success: boolean; error?: string } } = {};

      const processSide = async (
        side: 'home' | 'away',
        externalTeamId: string,
        uploadedFile: File | null,
        nameOverride: string,
        logoUrl: string | null
      ) => {
        try {
          if (!externalTeamId) return { success: false, error: 'Chybí ID týmu' };
          let file: File | Blob | null = uploadedFile;
          if (!file && logoUrl) {
            file = await fetchLogoAsBlob(logoUrl);
          }
          if (!file) return { success: false, error: 'Nelze získat soubor loga' };
          const up = await uploadToLogaSportcreative(externalTeamId, file, {
            filename: file instanceof File ? file.name : `${externalTeamId}.png`,
            clubName: nameOverride || 'Neznámý klub',
            clubType: 'football',
          });
          if (!up.success) return { success: false, error: up.error || 'Upload selhal' };
          if (up.url) {
            // Patch override to immediately use external URL
            await patchMatchOverride(
              externalMatchId,
              side === 'home' ? { home_logo_url: up.url } : { away_logo_url: up.url }
            );
          }
          return { success: true };
        } catch (e: any) {
          return { success: false, error: e?.message || 'Chyba při uploadu' };
        }
      };

      if (homeExternalTeamId && (form.home_logo_url || homeUploadedFile)) {
        results.home = await processSide('home', homeExternalTeamId, homeUploadedFile, form.home_name_override, form.home_logo_url);
      }
      if (awayExternalTeamId && (form.away_logo_url || awayUploadedFile)) {
        results.away = await processSide('away', awayExternalTeamId, awayUploadedFile, form.away_name_override, form.away_logo_url);
      }

      return { ok: true, results };
    },
    onSuccess: (res: any) => {
      const r = res?.results || {};
      const parts: string[] = [];
      if (r.home) parts.push(r.home.success ? 'Logo domácích nahráno' : `Domácí: ${r.home.error || 'chyba'}`);
      if (r.away) parts.push(r.away.success ? 'Logo hostů nahráno' : `Hosté: ${r.away.error || 'chyba'}`);
      const description = parts.length ? parts.join(' • ') : undefined;
      toast({ title: 'Uloženo', description, status: 'success' });
      setIsOpen(false);
      setSelected(null);
      setHomeUploadedFile(null);
      setAwayUploadedFile(null);
      // Invalidate the cache-backed list to refresh any merged overrides
      queryClient.invalidateQueries({ queryKey: ['admin-matches-list-cache'] });
    },
    onError: (e: any) => {
      toast({ title: 'Uložení selhalo', description: e?.message || 'Zkuste to znovu', status: 'error' });
    },
  });

  const openEdit = (m: any, side?: 'home' | 'away') => {
    setSelected(m);
    // Convert FACR-style date (e.g., 25.08.2025 18:30) to RFC3339 for backend
    const facrStr: string = m.date_time || m.date || '';
    let iso = '';
    if (facrStr) {
      try {
        const dt = parse(String(facrStr), 'dd.MM.yyyy HH:mm', new Date());
        if (!isNaN(dt.getTime())) iso = dt.toISOString();
      } catch (_) {
        // If it's already ISO or another parseable format, keep as-is if valid
        const d2 = new Date(facrStr);
        if (!isNaN(d2.getTime())) iso = d2.toISOString();
      }
    }
    setForm({
      home_name_override: m.home || m.home_team || '',
      away_name_override: m.away || m.away_team || '',
      venue_override: m.venue || '',
      date_time_override: iso,
      home_logo_url: m.home_logo_url || '',
      away_logo_url: m.away_logo_url || '',
      notes: '',
    });
    setIsOpen(true);
    setFocusSide(side ?? null);
    // Reset external selections and uploaded files to avoid stale state
    setHomeExternalTeamId('');
    setAwayExternalTeamId('');
    setHomeUploadedFile(null);
    setAwayUploadedFile(null);
  };

  // Autofocus on the selected team input when drawer opens
  const homeInputRef = useRef<HTMLInputElement | null>(null);
  const awayInputRef = useRef<HTMLInputElement | null>(null);
  const handleHomeInput = (e: React.ChangeEvent<HTMLInputElement>) => {
    setHomeQuery(e.target.value);
  };
  const handleAwayInput = (e: React.ChangeEvent<HTMLInputElement>) => {
    setAwayQuery(e.target.value);
  };
  useEffect(() => {
    if (isOpen && focusSide) {
      const t = setTimeout(() => {
        if (focusSide === 'home') homeInputRef.current?.focus();
        if (focusSide === 'away') awayInputRef.current?.focus();
      }, 50);
      return () => clearTimeout(t);
    }
  }, [isOpen, focusSide]);

  const drawerSize = useBreakpointValue({ base: 'full', md: 'md' });
  // Horizontal scroll affordance
  const scrollRef = useRef<HTMLDivElement | null>(null);
  const [canScrollLeft, setCanScrollLeft] = useState(false);
  const [canScrollRight, setCanScrollRight] = useState(false);
  const [showScrollHint, setShowScrollHint] = useState(true);
  
  // Drag-to-scroll state
  const [isDragging, setIsDragging] = useState(false);
  const [startX, setStartX] = useState(0);
  const [scrollLeft, setScrollLeft] = useState(0);
  const lastXRef = useRef(0);
  const lastTimeRef = useRef(0);
  const velocityRef = useRef(0);
  const animationRef = useRef<number | null>(null);
  const scrollRaf = useRef<number | null>(null);
  
  const updateScrollShadow = () => {
    const el = scrollRef.current;
    if (!el) return;
    const left = el.scrollLeft > 0;
    const right = el.scrollLeft + el.clientWidth < el.scrollWidth - 1;
    if (left !== canScrollLeft) setCanScrollLeft(left);
    if (right !== canScrollRight) setCanScrollRight(right);
  };
  
  // Drag-to-scroll handlers
  const handleMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
    if (!scrollRef.current) return;
    // Cancel any ongoing momentum animation
    if (animationRef.current) {
      cancelAnimationFrame(animationRef.current);
      animationRef.current = null;
    }
    setIsDragging(true);
    setStartX(e.pageX - scrollRef.current.offsetLeft);
    setScrollLeft(scrollRef.current.scrollLeft);
    lastXRef.current = e.pageX;
    lastTimeRef.current = Date.now();
    velocityRef.current = 0;
    scrollRef.current.style.cursor = 'grabbing';
    scrollRef.current.style.userSelect = 'none';
    scrollRef.current.style.scrollBehavior = 'auto'; // Disable smooth scroll during drag
  };
  
  const handleMouseLeave = () => {
    setIsDragging(false);
    if (scrollRef.current) {
      scrollRef.current.style.cursor = 'grab';
      scrollRef.current.style.userSelect = 'auto';
    }
  };
  
  const handleMouseUp = () => {
    setIsDragging(false);
    if (scrollRef.current) {
      scrollRef.current.style.cursor = 'grab';
      scrollRef.current.style.userSelect = 'auto';
      scrollRef.current.style.scrollBehavior = 'smooth';
      
      // Apply momentum scrolling
      const velocity = velocityRef.current;
      if (Math.abs(velocity) > 0.5) {
        const applyMomentum = () => {
          if (!scrollRef.current) return;
          velocityRef.current *= 0.95; // Deceleration factor
          scrollRef.current.scrollLeft -= velocityRef.current;
          
          if (Math.abs(velocityRef.current) > 0.5) {
            animationRef.current = requestAnimationFrame(applyMomentum);
          } else {
            animationRef.current = null;
          }
        };
        animationRef.current = requestAnimationFrame(applyMomentum);
      }
    }
  };
  
  const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
    if (!isDragging || !scrollRef.current) return;
    e.preventDefault();
    const x = e.pageX - scrollRef.current.offsetLeft;
    const walk = (x - startX) * 1.5; // Scroll speed multiplier (reduced for smoother feel)
    scrollRef.current.scrollLeft = scrollLeft - walk;
    
    // Calculate velocity for momentum
    const now = Date.now();
    const timeDelta = now - lastTimeRef.current;
    if (timeDelta > 0) {
      const currentX = e.pageX;
      const distance = currentX - lastXRef.current;
      velocityRef.current = distance / timeDelta * 16; // Normalize to ~60fps
      lastXRef.current = currentX;
      lastTimeRef.current = now;
    }
  };
  
  // Touch handlers for mobile
  const handleTouchStart = (e: React.TouchEvent<HTMLDivElement>) => {
    if (!scrollRef.current) return;
    if (animationRef.current) {
      cancelAnimationFrame(animationRef.current);
      animationRef.current = null;
    }
    const touch = e.touches[0];
    setIsDragging(true);
    setStartX(touch.pageX - scrollRef.current.offsetLeft);
    setScrollLeft(scrollRef.current.scrollLeft);
    lastXRef.current = touch.pageX;
    lastTimeRef.current = Date.now();
    velocityRef.current = 0;
    if (scrollRef.current) scrollRef.current.style.scrollBehavior = 'auto';
  };
  
  const handleTouchMove = (e: React.TouchEvent<HTMLDivElement>) => {
    if (!isDragging || !scrollRef.current) return;
    const touch = e.touches[0];
    const x = touch.pageX - scrollRef.current.offsetLeft;
    const walk = (x - startX) * 1.5;
    scrollRef.current.scrollLeft = scrollLeft - walk;
    
    const now = Date.now();
    const timeDelta = now - lastTimeRef.current;
    if (timeDelta > 0) {
      const currentX = touch.pageX;
      const distance = currentX - lastXRef.current;
      velocityRef.current = distance / timeDelta * 16;
      lastXRef.current = currentX;
      lastTimeRef.current = now;
    }
  };
  
  const handleTouchEnd = () => {
    setIsDragging(false);
    if (scrollRef.current) {
      scrollRef.current.style.scrollBehavior = 'smooth';
      
      const velocity = velocityRef.current;
      if (Math.abs(velocity) > 0.5) {
        const applyMomentum = () => {
          if (!scrollRef.current) return;
          velocityRef.current *= 0.95;
          scrollRef.current.scrollLeft -= velocityRef.current;
          
          if (Math.abs(velocityRef.current) > 0.5) {
            animationRef.current = requestAnimationFrame(applyMomentum);
          } else {
            animationRef.current = null;
          }
        };
        animationRef.current = requestAnimationFrame(applyMomentum);
      }
    }
  };
  
  // Utility to check if match is in the past
  const isMatchPast = (dateTimeStr: string): boolean => {
    if (!dateTimeStr) return false;
    try {
      const dt = parse(dateTimeStr, FACR_DATE_FMT, new Date());
      if (!isNaN(dt.getTime())) {
        return dt.getTime() < Date.now();
      }
    } catch (_) {
      const d = new Date(dateTimeStr);
      if (!isNaN(d.getTime())) {
        return d.getTime() < Date.now();
      }
    }
    return false;
  };

  useEffect(() => {
    updateScrollShadow();
    const onResize = () => updateScrollShadow();
    window.addEventListener('resize', onResize);
    return () => {
      window.removeEventListener('resize', onResize);
      // Cleanup momentum animation on unmount
      if (animationRef.current) {
        cancelAnimationFrame(animationRef.current);
      }
    };
  }, []);

  const headerBg = useColorModeValue('brand.primary', 'gray.700');
  const headerText = useColorModeValue('text.onPrimary', 'white');
  const cardBg = useColorModeValue('white', 'gray.800');
  const borderColor = useColorModeValue('gray.200', 'gray.700');
  const edgeGradientLeft = useColorModeValue('linear(to-r, white, transparent)', 'linear(to-r, gray.800, transparent)');
  const edgeGradientRight = useColorModeValue('linear(to-l, white, transparent)', 'linear(to-l, gray.800, transparent)');
  const pastMatchBg = useColorModeValue('gray.100', 'gray.700');
  const futureMatchBg = useColorModeValue('white', 'gray.800');
  const pastMatchHoverBg = useColorModeValue('gray.200', 'gray.600');
  const futureMatchHoverBg = useColorModeValue('gray.50', 'gray.700');

  return (
    <AdminLayout requireAdmin={false}>
      <Box>
        <Box mb={6}>
          <Heading size="lg" mb={2}>Správa zápasů</Heading>
          <Text color={useColorModeValue('gray.600', 'gray.400')}>
            Správa a úprava zápasů. Můžete upravovat informace o zápasech, včetně názvů týmů, termínů, log a dalších detailů.
          </Text>
        </Box>

        {isLoading ? (
          <HStack spacing={3} mb={4}>
            <Spinner />
            <Text>Načítám zápasy…</Text>
          </HStack>
        ) : error ? (
          <Alert status="error" variant="left-accent" mb={4}>
            <AlertIcon />
            Nepodařilo se načíst zápasy.
          </Alert>
        ) : (
          <Box>
            <Wrap mb={4} spacing={3} align="center">
              <WrapItem minW="160px">
                <Select size="sm" value={sideFilter} onChange={(e) => setSideFilter((e.target.value as any) || '')}>
                  <option value="">Všechny strany</option>
                  <option value="home">Domácí</option>
                  <option value="away">Hosté</option>
                </Select>
              </WrapItem>
              <WrapItem flex={1} minW="220px">
                <Input
                  placeholder="Filtrovat podle týmu…"
                  value={teamFilter}
                  onChange={(e) => setTeamFilter(e.target.value)}
                  size="sm"
                />
              </WrapItem>
              <WrapItem>
                <HStack>
                  <Input
                    type="date"
                    size="sm"
                    value={dateFrom}
                    onChange={(e) => setDateFrom(e.target.value)}
                  />
                  <Text color="gray.500" fontSize="sm">–</Text>
                  <Input
                    type="date"
                    size="sm"
                    value={dateTo}
                    onChange={(e) => setDateTo(e.target.value)}
                  />
                </HStack>
              </WrapItem>
              <WrapItem>
                <HStack>
                  <Button size="sm" variant="outline" onClick={setThisWeek} borderRadius="md" _hover={{ borderColor: 'brand.primary', color: 'brand.primary' }}>Tento týden</Button>
                  <Button size="sm" variant="outline" onClick={setNext30Days} borderRadius="md" _hover={{ borderColor: 'brand.primary', color: 'brand.primary' }}>Dalších 30 dní</Button>
                </HStack>
              </WrapItem>
              <WrapItem minW="220px">
                <Select size="sm" value={competitionFilter} onChange={(e) => setCompetitionFilter(e.target.value)}>
                  <option value="">Všechny soutěže</option>
                  {competitionOptions.map((c) => (
                    <option key={c} value={c}>{c}</option>
                  ))}
                </Select>
              </WrapItem>
              {(teamFilter || dateFrom || dateTo || competitionFilter || sideFilter) && (
                <WrapItem>
                  <Button size="sm" variant="outline" colorScheme="red" onClick={() => { setTeamFilter(''); setDateFrom(''); setDateTo(''); setCompetitionFilter(''); setSideFilter(''); }} borderRadius="md">
                    Vymazat filtry
                  </Button>
                </WrapItem>
              )}
              <WrapItem>
                <HStack>
                  <Text fontSize="sm">Na stránku:</Text>
                  <Select size="sm" value={pageSize} onChange={(e) => setPageSize(parseInt(e.target.value) || 25)} width="auto">
                    <option value={25}>25</option>
                    <option value={50}>50</option>
                    <option value={100}>100</option>
                    <option value={200}>200</option>
                  </Select>
                </HStack>
              </WrapItem>
              <WrapItem>
                <Button size="sm" onClick={exportCsv} bg="brand.primary" color="text.onPrimary" _hover={{ filter: 'brightness(0.95)' }} borderRadius="md">Export CSV</Button>
              </WrapItem>
              <WrapItem>
                <Text color="gray.500" fontSize="sm">
                  Zobrazeno {visibleMatches.length} / {filteredMatches.length}
                </Text>
              </WrapItem>
            </Wrap>
            {showScrollHint && (
              <Text fontSize="xs" color="blue.600" fontWeight="600" mb={2} display="flex" alignItems="center" gap={1}>
                💡 Tip: Tabulku můžete plynule posouvat tažením myší nebo prstem →
              </Text>
            )}
            <Box
              ref={scrollRef}
              overflowX="auto"
              borderWidth="2px"
              borderRadius="xl"
              borderColor={borderColor}
              w="full"
              bg={cardBg}
              boxShadow="md"
              maxW="100%"
              position="relative"
              cursor="grab"
              onMouseDown={handleMouseDown}
              onMouseLeave={handleMouseLeave}
              onMouseUp={handleMouseUp}
              onMouseMove={handleMouseMove}
              onTouchStart={handleTouchStart}
              onTouchMove={handleTouchMove}
              onTouchEnd={handleTouchEnd}
              onScroll={(e) => {
                if (scrollRaf.current == null) {
                  scrollRaf.current = requestAnimationFrame(() => {
                    const el = scrollRef.current;
                    if (el) {
                      updateScrollShadow();
                      if (el.scrollLeft > 0 && showScrollHint) setShowScrollHint(false);
                    }
                    scrollRaf.current = null;
                  });
                }
              }}
              sx={{
                WebkitOverflowScrolling: 'touch',
                scrollBehavior: 'smooth',
                transform: 'translateZ(0)',
                willChange: 'transform',
                overscrollBehaviorX: 'contain',
                touchAction: 'pan-x',
                'th, td': { whiteSpace: 'nowrap' },
                '::-webkit-scrollbar': { height: '14px' },
                '::-webkit-scrollbar-thumb': { 
                  background: '#3182ce', 
                  borderRadius: '10px',
                  border: '3px solid transparent',
                  backgroundClip: 'content-box',
                  transition: 'background 0.2s ease',
                  '&:hover': { background: '#2c5aa0', backgroundClip: 'content-box' },
                  '&:active': { background: '#2a4e8a', backgroundClip: 'content-box' }
                },
                '::-webkit-scrollbar-track': { 
                  background: useColorModeValue('#f7fafc', '#2d3748'),
                  borderRadius: '10px',
                  margin: '0 8px',
                  border: '1px solid',
                  borderColor: useColorModeValue('#e2e8f0', '#4a5568')
                },
              }}
            >
              {/* Gradient edges to indicate horizontal scroll */}
              {canScrollLeft && (
                <Box position="sticky" left={0} top={0} bottom={0} w="24px" pointerEvents="none"
                  bgGradient={edgeGradientLeft}
                  zIndex={1}
                />
              )}
              {canScrollRight && (
                <Box position="sticky" right={0} top={0} bottom={0} w="24px" pointerEvents="none"
                  bgGradient={edgeGradientRight}
                  zIndex={1}
                />
              )}
              <Table size="sm" sx={{ width: 'max-content' }}>
                <Thead sx={{ position: 'sticky', top: 0, zIndex: 2, backgroundColor: headerBg, 'th': { bg: headerBg, color: headerText, fontWeight: 'bold', textTransform: 'uppercase', fontSize: 'xs', letterSpacing: '0.05em' } }}>
                  <Tr>
                    <Th minW="140px">Datum</Th>
                    <Th minW="200px">Soutěž</Th>
                    <Th minW="260px">Domácí</Th>
                    <Th minW="80px" textAlign="center">Skóre</Th>
                    <Th minW="260px">Hosté</Th>
                    <Th minW="220px">Místo</Th>
                    <Th minW="180px">Akce</Th>
                  </Tr>
                </Thead>
                <Tbody>
                  {filteredMatches.length === 0 ? (
                    <Tr>
                      <Td colSpan={6}>
                        <Text color="gray.500">Žádné zápasy k zobrazení.</Text>
                      </Td>
                    </Tr>
                  ) : (
                    visibleMatches.map((m: any, idx: number) => {
                      const isPast = isMatchPast(m.date_time || m.date || '');
                      const hasScore = m.score || (m.result_home != null && m.result_away != null);
                      return (
                        <Tr 
                          key={m.id ?? idx} 
                          bg={isPast ? pastMatchBg : futureMatchBg}
                          _hover={{ bg: isPast ? pastMatchHoverBg : futureMatchHoverBg }}
                          opacity={isPast ? 0.85 : 1}
                          transition="all 0.2s"
                        >
                          <Td>
                            <HStack spacing={2}>
                              <Text>{m.date_time || m.date || ''}</Text>
                              {isPast && <Badge colorScheme="gray" fontSize="xs">Odehráno</Badge>}
                              {!isPast && <Badge colorScheme="green" fontSize="xs">Nadcházející</Badge>}
                            </HStack>
                          </Td>
                          <Td>
                            <HStack spacing={2}>
                              <Badge bg="brand.primary" color="text.onPrimary" borderRadius="md">{m.competitionName}</Badge>
                            </HStack>
                          </Td>
                          <Td>
                            <HStack spacing={2}>
                              <Image
                                src={getLogo(m.home || m.home_team || '', m.home_id, m.home_logo_url)}
                                alt={m.home || m.home_team || ''}
                                boxSize="24px"
                                objectFit="contain"
                                loading="lazy"
                                decoding="async"
                                draggable={false}
                              />
                              <Text fontWeight={isPast ? 'normal' : 'medium'}>{m.home || m.home_team || ''}</Text>
                              <Button size="xs" variant="outline" onClick={() => openEdit(m, 'home')} borderRadius="md" _hover={{ borderColor: 'brand.primary', color: 'brand.primary' }}>Tým</Button>
                            </HStack>
                          </Td>
                          <Td textAlign="center">
                            <Text fontWeight={hasScore ? 'bold' : 'normal'} color={hasScore ? 'blue.600' : 'gray.500'}>
                              {m.score || (m.result_home != null && m.result_away != null ? `${m.result_home}:${m.result_away}` : '–:–')}
                            </Text>
                          </Td>
                          <Td>
                            <HStack spacing={2}>
                              <Image
                                src={getLogo(m.away || m.away_team || '', m.away_id, m.away_logo_url)}
                                alt={m.away || m.away_team || ''}
                                boxSize="24px"
                                objectFit="contain"
                                loading="lazy"
                                decoding="async"
                                draggable={false}
                              />
                              <Text fontWeight={isPast ? 'normal' : 'medium'}>{m.away || m.away_team || ''}</Text>
                              <Button size="xs" variant="outline" onClick={() => openEdit(m, 'away')} borderRadius="md" _hover={{ borderColor: 'brand.primary', color: 'brand.primary' }}>Tým</Button>
                            </HStack>
                          </Td>
                          <Td>{m.venue || ''}</Td>
                          <Td>
                            <HStack spacing={2}>
                              <Button size="xs" onClick={() => openEdit(m)} bg="brand.primary" color="text.onPrimary" _hover={{ filter: 'brightness(0.95)' }} borderRadius="md">Upravit</Button>
                            </HStack>
                          </Td>
                        </Tr>
                      );
                    })
                  )}
                </Tbody>
              </Table>
            </Box>
            {filteredMatches.length > visibleMatches.length && (
              <HStack justify="center" mt={6}>
                <Button onClick={() => setLimit((n) => n + pageSize)} size="lg" bg="brand.primary" color="text.onPrimary" _hover={{ filter: 'brightness(0.95)' }} borderRadius="lg" px={8}>
                  Načíst další ({filteredMatches.length - visibleMatches.length} zápasů)
                </Button>
              </HStack>
            )}
          </Box>
        )}
      </Box>

      {/* Edit Drawer */}
      <Drawer isOpen={isOpen} placement="right" onClose={() => setIsOpen(false)} size={drawerSize}>
        <DrawerOverlay />
        <DrawerContent>
          <DrawerHeader>Upravit zápas</DrawerHeader>
          <DrawerBody>
            {!selected ? (
              <Text color="gray.500">Není vybrán žádný zápas.</Text>
            ) : (
              <Stack spacing={4}>
                <FormControl>
                  <FormLabel>Datum a čas (ISO)</FormLabel>
                  <Input
                    placeholder="YYYY-MM-DDTHH:mm:ss.sssZ"
                    value={form.date_time_override}
                    onChange={(e) => setForm((f) => ({ ...f, date_time_override: e.target.value }))}
                  />
                  {isDateInvalid && (
                    <FormErrorMessage>Neplatný formát data/času</FormErrorMessage>
                  )}
                </FormControl>

                <FormControl>
                  <FormLabel>Místo</FormLabel>
                  <Input
                    placeholder="Místo konání"
                    value={form.venue_override}
                    onChange={(e) => setForm((f) => ({ ...f, venue_override: e.target.value }))}
                  />
                </FormControl>

                {/* Home team */}
                <FormControl>
                  <FormLabel>Domácí tým (název)</FormLabel>
                  <InputGroup>
                    <Input
                      ref={homeInputRef}
                      placeholder="Zadejte název týmu"
                      value={form.home_name_override}
                      onChange={(e) => {
                        setForm((f) => ({ ...f, home_name_override: e.target.value }));
                        handleHomeInput(e);
                      }}
                    />
                    <InputRightElement width="4.5rem">
                      <Button h="1.75rem" size="sm" onClick={() => homeFileRef.current?.click()}>Logo</Button>
                    </InputRightElement>
                  </InputGroup>
                  <input
                    type="file"
                    accept="image/*"
                    hidden
                    ref={homeFileRef}
                    onChange={async (e) => {
                      const file = e.target.files?.[0];
                      if (!file) return;
                      try {
                        const up = await uploadImage(file);
                        setForm((f) => ({ ...f, home_logo_url: up.url }));
                        setHomeUploadedFile(file);
                        toast({ title: 'Logo nahráno (domácí)', status: 'success' });
                      } catch (err: any) {
                        toast({ title: 'Nahrání se nezdařilo', description: err?.message || '', status: 'error' });
                      } finally {
                        if (homeFileRef.current) homeFileRef.current.value = '' as any;
                      }
                    }}
                  />
                  {homeResults.length > 0 && (
                    <Box mt={2} borderWidth="1px" borderRadius="md" p={2} maxH="180px" overflowY="auto">
                      <List spacing={1}>
                        {homeResults.map((r: any) => (
                          <ListItem key={r.id}>
                            <Button size="xs" variant="ghost" onClick={() => {
                              setForm((f) => ({ ...f, home_name_override: r.name, home_logo_url: r.logo_url || f.home_logo_url }));
                              setHomeQuery(r.name);
                              setHomeExternalTeamId(String(r.id || ''));
                            }}>
                              {r.name}
                            </Button>
                          </ListItem>
                        ))}
                      </List>
                    </Box>
                  )}
                  {form.home_logo_url && (
                    <HStack mt={2} spacing={3}>
                      <Image src={form.home_logo_url} alt="home logo" boxSize="28px" objectFit="contain" />
                      <Button size="xs" variant="outline" onClick={() => setForm((f) => ({ ...f, home_logo_url: '' }))}>Odebrat logo</Button>
                    </HStack>
                  )}
                </FormControl>

                {/* Away team */}
                <FormControl>
                  <FormLabel>Hostující tým (název)</FormLabel>
                  <InputGroup>
                    <Input
                      ref={awayInputRef}
                      placeholder="Zadejte název týmu"
                      value={form.away_name_override}
                      onChange={(e) => {
                        setForm((f) => ({ ...f, away_name_override: e.target.value }));
                        handleAwayInput(e);
                      }}
                    />
                    <InputRightElement width="4.5rem">
                      <Button h="1.75rem" size="sm" onClick={() => awayFileRef.current?.click()}>Logo</Button>
                    </InputRightElement>
                  </InputGroup>
                  <input
                    type="file"
                    accept="image/*"
                    hidden
                    ref={awayFileRef}
                    onChange={async (e) => {
                      const file = e.target.files?.[0];
                      if (!file) return;
                      try {
                        const up = await uploadImage(file);
                        setForm((f) => ({ ...f, away_logo_url: up.url }));
                        setAwayUploadedFile(file);
                        toast({ title: 'Logo nahráno (hosté)', status: 'success' });
                      } catch (err: any) {
                        toast({ title: 'Nahrání se nezdařilo', description: err?.message || '', status: 'error' });
                      } finally {
                        if (awayFileRef.current) awayFileRef.current.value = '' as any;
                      }
                    }}
                  />
                  {awayResults.length > 0 && (
                    <Box mt={2} borderWidth="1px" borderRadius="md" p={2} maxH="180px" overflowY="auto">
                      <List spacing={1}>
                        {awayResults.map((r: any) => (
                          <ListItem key={r.id}>
                            <Button size="xs" variant="ghost" onClick={() => {
                              setForm((f) => ({ ...f, away_name_override: r.name, away_logo_url: r.logo_url || f.away_logo_url }));
                              setAwayQuery(r.name);
                              setAwayExternalTeamId(String(r.id || ''));
                            }}>
                              {r.name}
                            </Button>
                          </ListItem>
                        ))}
                      </List>
                    </Box>
                  )}
                  {form.away_logo_url && (
                    <HStack mt={2} spacing={3}>
                      <Image src={form.away_logo_url} alt="away logo" boxSize="28px" objectFit="contain" />
                      <Button size="xs" variant="outline" onClick={() => setForm((f) => ({ ...f, away_logo_url: '' }))}>Odebrat logo</Button>
                    </HStack>
                  )}
                </FormControl>

                <FormControl>
                  <FormLabel>Poznámka</FormLabel>
                  <Input
                    placeholder="Libovolná poznámka (interní)"
                    value={form.notes}
                    onChange={(e) => setForm((f) => ({ ...f, notes: e.target.value }))}
                  />
                </FormControl>
              </Stack>
            )}
          </DrawerBody>
          <DrawerFooter>
            <HStack spacing={3}>
              <Button variant="outline" onClick={() => setIsOpen(false)}>Zavřít</Button>
              <Button colorScheme="blue" isLoading={saveMutation.isPending} onClick={() => saveMutation.mutate()} isDisabled={isDateInvalid}>
                Uložit změny
              </Button>
            </HStack>
          </DrawerFooter>
        </DrawerContent>
      </Drawer>
 
    </AdminLayout>
  );
};

export default MatchesAdminPage;
