import React, { useState, useRef, useEffect, useMemo, useCallback } from 'react';
import { Link } from 'react-router-dom';
import { Line, Bar } from 'react-chartjs-2';
import {
  filterDataByDateRange, calculateMetrics,
  getUniqueChannels, getUniqueMuseums, getUniqueDistricts,
  umrahData
} from '../services/dataService';
import { chartColors, createBaseOptions } from '../config/chartConfig';
import type { MuseumRecord, Season } from '../types';
import { useLanguage } from '../contexts/LanguageContext';
import type { LC } from '../lib/locale';
import { EN, AR } from '../lib/locale';
import { currentMonth, shiftYear, periodNameL, dateRangeTextL } from '../lib/dateHelpers';
import { InlinePicker } from './shared/PeriodPicker';
import AltMultiSelect from './shared/AltMultiSelect';
import MetricCard from './shared/MetricCard';

interface Props {
  data: MuseumRecord[];
  seasons: Season[];
  includeVAT: boolean;
  allowedMuseums: string[] | null;
  allowedChannels: string[] | null;
  lang?: 'en' | 'ar';
}

// ─── period card ──────────────────────────────────────────────────
function PeriodCard({ role, hint, start, end, variant, onChange, availableYears, L }: {
  role: string; hint: string; start: string; end: string;
  variant: 'current'|'previous';
  onChange: (s: string, e: string) => void;
  availableYears: number[]; L: LC;
}) {
  const [open, setOpen] = useState(false);
  const ref = useRef<HTMLDivElement>(null);
  useEffect(() => {
    if (!open) return;
    const onM = (e: MouseEvent) => { if(ref.current && !ref.current.contains(e.target as Node)) setOpen(false); };
    const onK = (e: KeyboardEvent) => { if(e.key==='Escape') setOpen(false); };
    document.addEventListener('mousedown', onM); document.addEventListener('keydown', onK);
    return () => { document.removeEventListener('mousedown', onM); document.removeEventListener('keydown', onK); };
  }, [open]);

  return (
    <div ref={ref} className={`alt-card alt-card--${variant}${open?' alt-card--open':''}`}>
      <div className="alt-card-bar" />
      <div className="alt-card-body">
        <div className="alt-role-row">
          <span className="alt-role">{role}</span>
          <span className="alt-role-hint">{hint}</span>
        </div>
        <div className="alt-period-name">{periodNameL(start, end, L)}</div>
        <div className="alt-date-range">{dateRangeTextL(start, end, L)}</div>
        <button type="button" className="alt-change-btn" onClick={() => setOpen(v => !v)} aria-expanded={open} aria-controls="period-picker-panel">
          {open ? L.close : L.changePeriod}
          <svg width="10" height="10" viewBox="0 0 10 10" fill="none" style={{ transform:open?'rotate(180deg)':'none', transition:'transform 0.2s' }}>
            <path d="M2 3.5L5 6.5L8 3.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
          </svg>
        </button>
      </div>
      {open && <InlinePicker start={start} end={end} onChange={onChange} onClose={() => setOpen(false)} availableYears={availableYears} L={L} />}
    </div>
  );
}

// ─── main page ────────────────────────────────────────────────────
export default function PeriodSelectorDemo({ data, seasons, includeVAT, allowedMuseums, allowedChannels }: Props) {
  const { lang: activeLang, setLanguage } = useLanguage();
  const L = activeLang === 'ar' ? AR : EN;
  const curr = currentMonth();
  const [currStart, setCurrStart] = useState(curr.start);
  const [currEnd,   setCurrEnd]   = useState(curr.end);
  const [prevStart, setPrevStart] = useState(() => shiftYear(curr.start));
  const [prevEnd,   setPrevEnd]   = useState(() => shiftYear(curr.end));
  const [selDistricts, setSelDistricts] = useState<string[]>([]);
  const [selChannels,  setSelChannels]  = useState<string[]>([]);
  const [selMuseums,   setSelMuseums]   = useState<string[]>([]);
  const [metric, setMetric] = useState('revenue');
  const [gran,   setGran]   = useState('week');

  const perm = useMemo(() => {
    if (!allowedMuseums || !allowedChannels) return [];
    let d = data;
    if (allowedMuseums.length) d = d.filter(r => allowedMuseums.includes(r.museum_name));
    if (allowedChannels.length) d = d.filter(r => allowedChannels.includes(r.channel));
    return d;
  }, [data, allowedMuseums, allowedChannels]);

  const availableYears = useMemo(() => {
    const s = new Set<number>(); perm.forEach(r => r.date && s.add(parseInt(r.date.slice(0,4))));
    const a = Array.from(s).sort((a,b) => b-a); return a.length ? a : [new Date().getFullYear()];
  }, [perm]);

  const handleCurr = (s: string, e: string) => { setCurrStart(s); setCurrEnd(e); setPrevStart(shiftYear(s)); setPrevEnd(shiftYear(e)); };

  const applyFilters = useCallback((rows: MuseumRecord[]) => {
    let d = rows;
    if (selChannels.length)  d = d.filter(r => selChannels.includes(r.channel));
    if (selMuseums.length)   d = d.filter(r => selMuseums.includes(r.museum_name));
    if (selDistricts.length) d = d.filter(r => selDistricts.includes(r.district));
    return d;
  }, [selDistricts, selChannels, selMuseums]);

  const currData = useMemo(() => applyFilters(filterDataByDateRange(perm, currStart, currEnd, {})), [perm, currStart, currEnd, applyFilters]);
  const prevData = useMemo(() => applyFilters(filterDataByDateRange(perm, prevStart, prevEnd, {})), [perm, prevStart, prevEnd, applyFilters]);
  const currM    = useMemo(() => calculateMetrics(currData, includeVAT), [currData, includeVAT]);
  const prevM    = useMemo(() => calculateMetrics(prevData, includeVAT), [prevData, includeVAT]);

  const revenueField = includeVAT ? 'revenue_gross' : 'revenue_net';

  const getVal = useCallback((rows: MuseumRecord[], m: string) => {
    if (m==='avgRevenue') {
      const rev = rows.reduce((s,r) => s + parseFloat(String((r as any)[revenueField]||0)), 0);
      const vis = rows.reduce((s,r) => s + parseInt(String(r.visits||0)), 0);
      return vis>0 ? rev/vis : 0;
    }
    const f: Record<string,string> = { revenue:revenueField, visitors:'visits', tickets:'tickets' };
    return rows.reduce((s,r) => s + parseFloat(String((r as any)[f[m]]||0)), 0);
  }, [revenueField]);

  const channels  = useMemo(() => getUniqueChannels(perm),  [perm]);
  const districts = useMemo(() => getUniqueDistricts(perm), [perm]);
  const museums   = useMemo(() => getUniqueMuseums(perm),   [perm]);

  const periodLabel = (s: string, e: string) => {
    const sy=s.slice(0,4), ey=e.slice(0,4);
    return sy===ey ? sy : `${L.monthShort[parseInt(s.slice(5,7))-1]} '${sy.slice(-2)}–${L.monthShort[parseInt(e.slice(5,7))-1]} '${ey.slice(-2)}`;
  };

  const trendData = useMemo(() => {
    const group = (rows: MuseumRecord[], ps: string) => {
      const s=new Date(ps); const acc: Record<number,MuseumRecord[]> = {};
      rows.forEach(r => {
        if (!r.date) return;
        const diff = Math.floor((new Date(r.date).getTime() - s.getTime()) / 86400000);
        const key = gran==='month' ? Math.floor(diff/30)+1 : gran==='week' ? Math.floor(diff/7)+1 : diff+1;
        if (!acc[key]) acc[key]=[]; acc[key].push(r);
      });
      const res: Record<number,number> = {};
      Object.entries(acc).forEach(([k,v]) => res[Number(k)] = getVal(v, metric)); return res;
    };
    const pg = group(prevData, prevStart), cg = group(currData, currStart);
    const maxK = Math.max(...Object.keys(pg).map(Number), ...Object.keys(cg).map(Number), 1);
    const labels = Array.from({length:maxK}, (_,i) =>
      gran==='week' ? `W${i+1}` : gran==='month' ? L.monthShort[(new Date(currStart).getMonth()+i)%12] : `D${i+1}`
    );
    return {
      labels,
      datasets: [
        { label:periodLabel(prevStart,prevEnd), data:labels.map((_,i) => pg[i+1]||0), borderColor:chartColors.muted, backgroundColor:'transparent', borderWidth:2, tension:0.4, pointRadius:gran==='week'?3:1, pointBackgroundColor:chartColors.muted },
        { label:periodLabel(currStart,currEnd), data:labels.map((_,i) => cg[i+1]||0), borderColor:chartColors.primary, backgroundColor:chartColors.primary+'15', borderWidth:2, tension:0.4, fill:true, pointRadius:gran==='week'?4:2, pointBackgroundColor:chartColors.primary },
      ]
    };
  }, [prevData, currData, prevStart, currStart, prevEnd, currEnd, metric, gran, getVal, L]);

  const museumData = useMemo(() => {
    const all = [...new Set(data.map(r => r.museum_name))].filter(Boolean) as string[];
    const pb: Record<string,number>={}, cb: Record<string,number>={};
    all.forEach(m => { pb[m]=getVal(prevData.filter(r => r.museum_name===m), metric); cb[m]=getVal(currData.filter(r => r.museum_name===m), metric); });
    const active = all.filter(m => pb[m]>0 || cb[m]>0);
    return {
      labels: active,
      datasets: [
        { label:periodLabel(prevStart,prevEnd), data:active.map(m => pb[m]), backgroundColor:chartColors.muted+'cc', borderRadius:4 },
        { label:periodLabel(currStart,currEnd), data:active.map(m => cb[m]), backgroundColor:chartColors.primary, borderRadius:4 },
      ]
    };
  }, [data, prevData, currData, prevStart, prevEnd, currStart, currEnd, metric, getVal]);

  const baseOpts = useMemo(() => createBaseOptions(false), []);
  const { chartOpts } = useMemo(() => {
    const chartOpts: any = { ...baseOpts, plugins:{ ...baseOpts.plugins, legend:{ position:'top', align:'end', labels:{ boxWidth:12, padding:12 } } } };
    return { chartOpts };
  }, [baseOpts]);

  const metricOpts = [
    { value:'revenue', label:L.revenue }, { value:'visitors', label:L.visitors },
    { value:'tickets', label:L.tickets }, { value:'avgRevenue', label:L.avgRev },
  ];
  const granOpts = [{ value:'day', label:L.daily }, { value:'week', label:L.weekly }, { value:'month', label:L.monthly }];

  const estimatePilgrims = useCallback((s: string, e: string) => {
    const sd=new Date(s), ed=new Date(e); let total=0, has=false;
    for (let y=sd.getFullYear(); y<=ed.getFullYear(); y++) {
      for (let q=1; q<=4; q++) {
        const qs=new Date(y,(q-1)*3,1), qe=new Date(y,q*3,0);
        if (qe<sd||qs>ed) continue;
        const p=umrahData[y]?.[q]; if(!p) continue;
        const os=new Date(Math.max(qs.getTime(),sd.getTime())), oe=new Date(Math.min(qe.getTime(),ed.getTime()));
        total+=p*((oe.getTime()-os.getTime())/86400000+1)/((qe.getTime()-qs.getTime())/86400000+1); has=true;
      }
    }
    return has ? Math.round(total) : null;
  }, []);

  const currPilgrims = useMemo(() => estimatePilgrims(currStart, currEnd), [currStart, currEnd, estimatePilgrims]);
  const prevPilgrims = useMemo(() => estimatePilgrims(prevStart, prevEnd), [prevStart, prevEnd, estimatePilgrims]);
  const currCapture  = currPilgrims ? currM.visitors/currPilgrims*100 : null;
  const prevCapture  = prevPilgrims ? prevM.visitors/prevPilgrims*100 : null;

  const hasFilters = selDistricts.length>0 || selChannels.length>0 || selMuseums.length>0;
  const activeFilterCount = selDistricts.length + selChannels.length + selMuseums.length;
  const [filtersOpen, setFiltersOpen] = useState(false);

  return (
    <div
      className="alt-page"
      dir={L.dir}
      style={{
        '--alt-body-font': L.bodyFont,
        '--alt-display-font': L.displayFont,
        '--alt-mono-font': L.monoFont,
      } as React.CSSProperties}
    >
      <Link to={L.backTo} className="alt-back">
        <svg width="14" height="14" viewBox="0 0 14 14" fill="none" style={{ transform: L.dir==='rtl' ? 'scaleX(-1)' : undefined }}>
          <path d="M9 2L4 7L9 12" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
        </svg>
        {L.backLink}
      </Link>
      <h1 className="alt-page-title">{L.pageTitle}</h1>
      <p className="alt-page-sub">{L.pageSub}</p>

      <div className="alt-period-row">
        <PeriodCard role={L.currentRole} hint={L.currentHint} start={currStart} end={currEnd} variant="current"
          onChange={handleCurr} availableYears={availableYears} L={L} />
        <div className="alt-vs">
          <div className="alt-vs-line" />
          <span className="alt-vs-badge">{L.vs}</span>
        </div>
        <PeriodCard role={L.previousRole} hint={L.previousHint} start={prevStart} end={prevEnd} variant="previous"
          onChange={(s,e) => { setPrevStart(s); setPrevEnd(e); }} availableYears={availableYears} L={L} />
      </div>

      <div className={`alt-filter-bar${filtersOpen ? ' alt-filter-bar--open' : ''}`}>
        <div className="alt-filter-head">
          <span className="alt-filter-label">{L.filter}</span>
          {activeFilterCount > 0 && <span className="alt-filter-badge">{activeFilterCount}</span>}
          <button type="button" className="alt-filter-toggle" onClick={() => setFiltersOpen(v => !v)} aria-expanded={filtersOpen} aria-label="Toggle filters">
            <svg className={`alt-filter-chevron${filtersOpen ? ' alt-filter-chevron--open' : ''}`} width="14" height="14" viewBox="0 0 10 10" fill="none">
              <path d="M2 3.5L5 6.5L8 3.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
            </svg>
          </button>
        </div>
        <div className="alt-filter-body">
          <div className="alt-filter-sep" />
          <AltMultiSelect value={selDistricts} options={districts} onChange={setSelDistricts} allLabel={L.allDistricts} countLabel={L.countDistricts} clearLabel={L.clearSel} />
          <AltMultiSelect value={selChannels}  options={channels}  onChange={setSelChannels}  allLabel={L.allChannels}  countLabel={L.countChannels}  clearLabel={L.clearSel} />
          <AltMultiSelect value={selMuseums}   options={museums}   onChange={setSelMuseums}   allLabel={L.allMuseums}   countLabel={L.countMuseums}   clearLabel={L.clearSel} />
          {hasFilters && <button type="button" className="alt-filter-reset" onClick={() => { setSelDistricts([]); setSelChannels([]); setSelMuseums([]); }}>{L.reset}</button>}
        </div>
      </div>

      <div className="alt-section-heading"><h2>{L.keyMetrics}</h2></div>
      <div className="alt-metrics">
        <MetricCard title={L.revenue}  curr={currM.revenue}          prev={prevM.revenue}          isCurrency newLabel={L.newLabel} />
        <MetricCard title={L.visitors} curr={currM.visitors}         prev={prevM.visitors}                    newLabel={L.newLabel} />
        <MetricCard title={L.tickets}  curr={currM.tickets}          prev={prevM.tickets}                     newLabel={L.newLabel} />
        <MetricCard title={L.avgRev}   curr={currM.avgRevPerVisitor} prev={prevM.avgRevPerVisitor} isCurrency newLabel={L.newLabel} />
        {currPilgrims!==null && prevPilgrims!==null &&
          <MetricCard title={L.pilgrims} curr={currPilgrims} prev={prevPilgrims} newLabel={L.newLabel} />}
        {currCapture!==null && prevCapture!==null &&
          <MetricCard title={L.captureRate} curr={parseFloat(currCapture.toFixed(2))} prev={parseFloat((prevCapture??0).toFixed(2))} newLabel={L.newLabel} />}
      </div>

      <div className="alt-charts">
        <div className="alt-chart-card">
          <div className="alt-chart-header">
            <h3 className="alt-chart-title">{L.trendTitle}</h3>
            <div className="alt-chart-controls">
              {metricOpts.map(o => <button key={o.value} type="button" aria-pressed={metric===o.value} className={`alt-ctrl${metric===o.value?' alt-ctrl-on':''}`} onClick={() => setMetric(o.value)}>{o.label}</button>)}
              <div className="alt-ctrl-sep" />
              {granOpts.map(o => <button key={o.value} type="button" aria-pressed={gran===o.value} className={`alt-ctrl${gran===o.value?' alt-ctrl-on':''}`} onClick={() => setGran(o.value)}>{o.label}</button>)}
            </div>
          </div>
          <div className="alt-chart-wrap"><Line data={trendData} options={chartOpts} /></div>
        </div>
        <div className="alt-chart-card">
          <div className="alt-chart-header">
            <h3 className="alt-chart-title">{L.museumTitle}</h3>
            <div className="alt-chart-controls">
              {metricOpts.map(o => <button key={o.value} type="button" aria-pressed={metric===o.value} className={`alt-ctrl${metric===o.value?' alt-ctrl-on':''}`} onClick={() => setMetric(o.value)}>{o.label}</button>)}
            </div>
          </div>
          <div className="alt-chart-wrap"><Bar data={museumData} options={chartOpts} /></div>
        </div>
      </div>
    </div>
  );
}
