// Filter selectors — one editor per filter type.
// Each editor receives { value, onChange, onClose } and renders a popover body.
// `value` shape is per-filter (object). `onChange(newValue, label)` updates the active filter.

const POP_SHELL = {
  position: 'absolute', top: 'calc(100% + 6px)', left: 0, zIndex: 61,
  background: 'var(--bg-surface)',
  border: '1px solid var(--border)',
  borderRadius: 12,
  boxShadow: '0 12px 32px rgba(14,18,27,0.12)',
  padding: 12,
  minWidth: 260,
};

const PopoverFooter = ({ onClear, onApply }) => (
  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 12, paddingTop: 10, borderTop: '1px solid var(--border)' }}>
    <button onClick={onClear} style={{ background: 'transparent', border: 0, color: 'var(--text-muted)', fontSize: 12, cursor: 'pointer' }}>Reset</button>
    <button onClick={onApply} className="btn btn-primary btn-sm">Apply</button>
  </div>
);

// ---------- value defaults & label formatters ----------

const fmtNum = (n) => {
  if (n >= 1_000_000) return (n / 1_000_000).toFixed(n % 1_000_000 === 0 ? 0 : 1) + 'M';
  if (n >= 1_000) return (n / 1_000).toFixed(n % 1_000 === 0 ? 0 : 1) + 'K';
  return String(n);
};

const FILTER_DEFS = {
  date: {
    initial: (() => {
      const to = new Date();
      const from = new Date(); from.setDate(from.getDate() - 30);
      return { from: from.toISOString().slice(0,10), to: to.toISOString().slice(0,10) };
    })(),
    label: (v) => {
      if (!v?.from && !v?.to) return 'All time';
      const f = (s) => s ? new Date(s + 'T00:00:00').toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) : '';
      if (v.from && !v.to) return f(v.from);
      return `${f(v.from)} – ${f(v.to)}`;
    },
  },
  reach: {
    initial: { min: 0, max: 1_000_000 },
    label: (v) => `${fmtNum(v.min)} – ${fmtNum(v.max)}`,
  },
  spend: {
    initial: { min: 0, max: 20_000 },
    label: (v) => `€${fmtNum(v.min)} – ${fmtNum(v.max)}`,
  },
  format: {
    initial: [],
    label: (v) => v.length === 0 ? 'Any format' : v.map(s => s[0].toUpperCase() + s.slice(1)).join(', '),
    options: [
      { value: 'image',    label: 'Image' },
      { value: 'video',    label: 'Video' },
      { value: 'carousel', label: 'Carousel' },
      { value: 'collection', label: 'Collection' },
    ],
  },
  cta: {
    initial: ['buy_now', 'shop_now'],
    label: (v) => v.length === 0 ? 'Any CTA' : v.map(s => CTA_LABELS[s] || s).join(', '),
  },
  geo: {
    initial: ['FR', 'US', 'UK', 'DE'],
    label: (v) => v.length === 0 ? 'Worldwide' : v.length <= 3 ? v.map(c => COUNTRY_NAMES[c] || c).join(', ') : `${COUNTRY_NAMES[v[0]]}, +${v.length - 1}`,
  },
  shop: {
    initial: 'dropshipping',
    label: (v) => v === 'dropshipping' ? 'Is dropshipping' : v === 'brand' ? 'Brand store' : v === 'dtc' ? 'DTC' : 'Any shop',
  },
  language: {
    initial: ['en', 'fr'],
    label: (v) => v.length === 0 ? 'Any language' : v.map(c => LANG_NAMES[c] || c).join(', '),
  },
  platform: {
    initial: [],
    label: (v) => v.length === 0 ? 'All platforms' : v.map(c => PLATFORM_NAMES[c] || c).join(', '),
  },
  industry: {
    initial: ['fashion', 'beauty'],
    label: (v) => v.length === 0 ? 'All industries' : v.map(c => INDUSTRY_NAMES[c] || c).join(', '),
  },
  creator: {
    initial: 'verified',
    label: (v) => v === 'verified' ? 'Verified only' : v === 'unverified' ? 'Unverified only' : 'Any creator',
  },
};

const CTA_LABELS = { buy_now: 'Buy Now', shop_now: 'Shop Now', learn_more: 'Learn More', sign_up: 'Sign Up', download: 'Download' };
const COUNTRY_NAMES = { FR: 'France', CH: 'Suisse', BE: 'Belgique', US: 'United States', UK: 'UK', DE: 'Germany', ES: 'Spain', IT: 'Italy', CA: 'Canada', AU: 'Australia' };
const LANG_NAMES = { en: 'English', fr: 'French', es: 'Spanish', de: 'German', it: 'Italian', pt: 'Portuguese' };
const PLATFORM_NAMES = { meta: 'Meta', tiktok: 'TikTok', instagram: 'Instagram', youtube: 'YouTube' };
const INDUSTRY_NAMES = { fashion: 'Fashion', beauty: 'Beauty', tech: 'Tech', home: 'Home', fitness: 'Fitness', food: 'Food', pets: 'Pets', kids: 'Kids' };

// ---------- editors ----------

// ---------- Date editor (calendar + presets) ----------

const DOW = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];
const MONTH_NAMES = ['January','February','March','April','May','June','July','August','September','October','November','December'];

const toISO = (d) => d ? d.toISOString().slice(0, 10) : null;
const sameDay = (a, b) => a && b && a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
const startOfDay = (d) => { const c = new Date(d); c.setHours(0,0,0,0); return c; };

const DATE_PRESETS = [
  { id: 'last30',   label: 'Last 30 days',  range: () => { const t = startOfDay(new Date()); const f = new Date(t); f.setDate(f.getDate() - 30); return { from: f, to: t }; } },
  { id: 'last60',   label: 'Last 60 days',  range: () => { const t = startOfDay(new Date()); const f = new Date(t); f.setDate(f.getDate() - 60); return { from: f, to: t }; } },
  { id: 'last6m',   label: 'Last 6 months', range: () => { const t = startOfDay(new Date()); const f = new Date(t); f.setMonth(f.getMonth() - 6); return { from: f, to: t }; } },
  { id: 'thisyear', label: 'This year',     range: () => { const t = startOfDay(new Date()); return { from: new Date(t.getFullYear(), 0, 1), to: t }; } },
  { id: 'lastyear', label: String(new Date().getFullYear() - 1), range: () => { const y = new Date().getFullYear() - 1; return { from: new Date(y, 0, 1), to: new Date(y, 11, 31) }; } },
  { id: 'last2y',   label: 'Last 2 years',  range: () => { const t = startOfDay(new Date()); const f = new Date(t); f.setFullYear(f.getFullYear() - 2); return { from: f, to: t }; } },
  { id: 'all',      label: 'All time',      range: () => ({ from: null, to: null }) },
];

const DateCalendar = ({ viewMonth, onPrev, onNext, from, to, hovered, onPick, onHover }) => {
  const year = viewMonth.getFullYear();
  const m = viewMonth.getMonth();
  const firstWeekday = new Date(year, m, 1).getDay();
  const lastDayNum = new Date(year, m + 1, 0).getDate();

  const cells = [];
  for (let i = firstWeekday; i > 0; i--) cells.push({ date: new Date(year, m, 1 - i), outside: true });
  for (let i = 1; i <= lastDayNum; i++) cells.push({ date: new Date(year, m, i), outside: false });
  while (cells.length % 7 !== 0 || cells.length < 42) cells.push({ date: new Date(year, m, lastDayNum + (cells.length - lastDayNum - firstWeekday + 1)), outside: true });

  const today = startOfDay(new Date());
  const navBtn = {
    width: 28, height: 28, padding: 0, display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
    background: 'var(--bg-surface)', border: '1px solid var(--border)', borderRadius: 8,
    color: 'var(--text-muted)', cursor: 'pointer',
  };

  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 12 }}>
        <button onClick={onPrev} style={navBtn} aria-label="Previous month"><Icon name="chevron-left" size={14}/></button>
        <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--text)' }}>{MONTH_NAMES[m]} {year}</div>
        <button onClick={onNext} style={navBtn} aria-label="Next month"><Icon name="chevron-right" size={14}/></button>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 2, marginBottom: 4 }}>
        {DOW.map(d => (
          <div key={d} style={{ textAlign: 'center', fontSize: 11, fontWeight: 500, color: 'var(--text-faint)', padding: '6px 0' }}>{d}</div>
        ))}
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 0 }}>
        {cells.map((c, i) => {
          const d = startOfDay(c.date);
          const isFrom = sameDay(d, from);
          const isTo = sameDay(d, to);
          const isToday = sameDay(d, today);
          const inRange = (from && to && d > from && d < to) ||
                          (from && !to && hovered && d > from && d <= hovered);
          const isEnd = isFrom || isTo;
          const col = i % 7;
          // Range continuity: a cell is the LEFT edge of the range visually if it's `from`,
          // or starts a new row inside the range. Symmetric for the RIGHT edge.
          const inAnyRange = isEnd || inRange;
          const leftEdge  = isFrom || (inAnyRange && col === 0);
          const rightEdge = isTo   || (isFrom && !to && !hovered) || (inAnyRange && col === 6);
          // Highlight bar background that fills full cell width (no gaps).
          const barBg = isEnd ? 'var(--accent)' : (inRange ? 'var(--accent-soft)' : 'transparent');
          const barRadius = `${leftEdge ? 8 : 0}px ${rightEdge ? 8 : 0}px ${rightEdge ? 8 : 0}px ${leftEdge ? 8 : 0}px`;
          return (
            <button key={i}
              onClick={() => onPick(d)}
              onMouseEnter={() => onHover(d)}
              onMouseLeave={() => onHover(null)}
              style={{
                position: 'relative',
                height: 36, border: 0, padding: 0,
                background: 'transparent',
                color: isEnd ? '#fff' : (inRange ? 'var(--accent)' : (c.outside ? 'var(--text-faint)' : 'var(--text)')),
                fontSize: 13, fontWeight: isEnd ? 600 : 500,
                cursor: 'pointer',
              }}>
              {/* Range bar — fills full cell width so adjacent cells touch */}
              {inAnyRange && (
                <span style={{
                  position: 'absolute', inset: 0,
                  background: barBg,
                  borderRadius: barRadius,
                  zIndex: 0,
                }}/>
              )}
              {/* Today ring (when not selected) */}
              {isToday && !isEnd && (
                <span style={{
                  position: 'absolute', inset: 1,
                  border: '1px solid var(--border)',
                  borderRadius: 8,
                  zIndex: 0,
                }}/>
              )}
              <span style={{ position: 'relative', zIndex: 1 }}>{c.date.getDate()}</span>
            </button>
          );
        })}
      </div>
    </div>
  );
};

const DateEditor = ({ value, onCommit, onClose }) => {
  const parse = (s) => s ? startOfDay(new Date(s + 'T00:00:00')) : null;
  const [from, setFrom] = React.useState(() => parse(value?.from));
  const [to, setTo] = React.useState(() => parse(value?.to));
  const [hovered, setHovered] = React.useState(null);
  const [viewMonth, setViewMonth] = React.useState(() => {
    const d = parse(value?.from) || new Date();
    return new Date(d.getFullYear(), d.getMonth(), 1);
  });

  const pick = (d) => {
    if (!from || (from && to)) { setFrom(d); setTo(null); }
    else if (d < from) { setTo(from); setFrom(d); }
    else setTo(d);
  };

  const applyPreset = (p) => {
    const r = p.range();
    setFrom(r.from); setTo(r.to);
    if (r.from) setViewMonth(new Date(r.from.getFullYear(), r.from.getMonth(), 1));
  };

  const apply = () => {
    const v = { from: toISO(from), to: toISO(to) };
    onCommit(v, FILTER_DEFS.date.label(v));
    onClose();
  };

  return (
    <div style={{
      ...POP_SHELL,
      padding: 0,
      width: 580,
      overflow: 'hidden',
    }}>
      <div style={{ display: 'grid', gridTemplateColumns: '160px 1fr' }}>
        <div style={{ borderRight: '1px solid var(--border)', padding: '14px 0', background: 'var(--bg-muted)' }}>
          <div style={{ padding: '0 16px 10px', fontSize: 11, fontWeight: 600, color: 'var(--text-faint)', textTransform: 'uppercase', letterSpacing: 0.06 }}>Date range</div>
          {DATE_PRESETS.map(p => (
            <button key={p.id} onClick={() => applyPreset(p)}
              style={{
                display: 'block', width: '100%', textAlign: 'left',
                padding: '8px 16px', background: 'transparent', border: 0,
                color: 'var(--text)', fontSize: 13, cursor: 'pointer',
              }}
              onMouseEnter={(e) => e.currentTarget.style.background = 'var(--bg-surface)'}
              onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}>
              {p.label}
            </button>
          ))}
        </div>
        <div style={{ padding: '14px 18px' }}>
          <DateCalendar
            viewMonth={viewMonth}
            onPrev={() => setViewMonth(m => new Date(m.getFullYear(), m.getMonth() - 1, 1))}
            onNext={() => setViewMonth(m => new Date(m.getFullYear(), m.getMonth() + 1, 1))}
            from={from} to={to} hovered={hovered}
            onPick={pick}
            onHover={setHovered}
          />
        </div>
      </div>
      <div style={{
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        padding: '10px 14px', borderTop: '1px solid var(--border)', background: 'var(--bg-muted)',
      }}>
        <button onClick={() => { setFrom(null); setTo(null); }}
          style={{ background: 'transparent', border: 0, color: 'var(--text-muted)', fontSize: 13, fontWeight: 500, cursor: 'pointer' }}>
          Clear
        </button>
        <button onClick={apply} className="btn btn-night btn-sm">Apply</button>
      </div>
    </div>
  );
};

const RangeEditor = ({ value, defKey, onCommit, onClose, title, prefix = '', suffix = '', step = 1, min = 0, max = 100 }) => {
  const [v, setV] = React.useState(value || FILTER_DEFS[defKey].initial);
  const def = FILTER_DEFS[defKey];
  const apply = () => { onCommit(v, def.label(v)); onClose(); };
  return (
    <div style={POP_SHELL}>
      <div style={{ fontSize: 12, color: 'var(--text-faint)', textTransform: 'uppercase', letterSpacing: 0.06, fontWeight: 600, marginBottom: 8 }}>{title || 'Range'}</div>
      <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
        <input type="number" value={v.min} step={step} min={min} max={max}
               onChange={(e) => setV({ ...v, min: Number(e.target.value) })}
               style={{ flex: 1, padding: '6px 8px', borderRadius: 8, border: '1px solid var(--border)', background: 'var(--bg-surface)', color: 'var(--text)', fontSize: 13 }}/>
        <span style={{ color: 'var(--text-faint)' }}>–</span>
        <input type="number" value={v.max} step={step} min={min} max={max}
               onChange={(e) => setV({ ...v, max: Number(e.target.value) })}
               style={{ flex: 1, padding: '6px 8px', borderRadius: 8, border: '1px solid var(--border)', background: 'var(--bg-surface)', color: 'var(--text)', fontSize: 13 }}/>
      </div>
      <div style={{ marginTop: 10, fontSize: 12, color: 'var(--text-muted)' }}>
        {prefix}{fmtNum(v.min)} – {fmtNum(v.max)}{suffix}
      </div>
      <PopoverFooter onClear={() => setV(FILTER_DEFS[defKey].initial)} onApply={apply}/>
    </div>
  );
};

const MultiEditor = ({ value, onCommit, onClose, options, title }) => {
  const [v, setV] = React.useState(value || []);
  const toggle = (val) => setV(s => s.includes(val) ? s.filter(x => x !== val) : [...s, val]);
  return (
    <div style={POP_SHELL}>
      <div style={{ fontSize: 12, color: 'var(--text-faint)', textTransform: 'uppercase', letterSpacing: 0.06, fontWeight: 600, marginBottom: 8 }}>{title}</div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 2, maxHeight: 280, overflow: 'auto' }} className="scroll">
        {options.map(o => {
          const on = v.includes(o.value);
          return (
            <button key={o.value} onClick={() => toggle(o.value)}
                    style={{
                      display: 'flex', alignItems: 'center', gap: 10,
                      padding: '8px 10px', borderRadius: 8,
                      background: on ? 'var(--accent-soft)' : 'transparent',
                      border: 0, color: 'var(--text)', fontSize: 13, textAlign: 'left', cursor: 'pointer',
                    }}>
              <span style={{
                width: 16, height: 16, borderRadius: 4,
                border: `1.5px solid ${on ? 'var(--accent)' : 'var(--border)'}`,
                background: on ? 'var(--accent)' : 'transparent',
                display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
              }}>
                {on && <Icon name="check" size={10} style={{ color: '#fff' }}/>}
              </span>
              <span style={{ flex: 1 }}>{o.label}</span>
            </button>
          );
        })}
      </div>
      <PopoverFooter onClear={() => setV([])} onApply={() => onCommit(v) /* outer wraps label */}/>
    </div>
  );
};

const SingleEditor = ({ value, onCommit, onClose, options, title }) => {
  const [v, setV] = React.useState(value);
  return (
    <div style={POP_SHELL}>
      <div style={{ fontSize: 12, color: 'var(--text-faint)', textTransform: 'uppercase', letterSpacing: 0.06, fontWeight: 600, marginBottom: 8 }}>{title}</div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
        {options.map(o => (
          <button key={o.value} onClick={() => setV(o.value)}
                  style={{
                    display: 'flex', alignItems: 'center', gap: 10,
                    padding: '8px 10px', borderRadius: 8,
                    background: v === o.value ? 'var(--accent-soft)' : 'transparent',
                    color: v === o.value ? 'var(--accent)' : 'var(--text)',
                    border: 0, fontSize: 13, textAlign: 'left', cursor: 'pointer', fontWeight: v === o.value ? 600 : 400,
                  }}>
            <span style={{
              width: 14, height: 14, borderRadius: 999,
              border: `1.5px solid ${v === o.value ? 'var(--accent)' : 'var(--border)'}`,
              display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
            }}>
              {v === o.value && <span style={{ width: 6, height: 6, borderRadius: 999, background: 'var(--accent)' }}/>}
            </span>
            {o.label}
          </button>
        ))}
      </div>
      <PopoverFooter onClear={() => setV(null)} onApply={() => onCommit(v)}/>
    </div>
  );
};

// Dispatcher — picks the right editor for a filter id
const FilterEditor = ({ filter, onCommit, onClose }) => {
  const wrap = (v) => onCommit(v, FILTER_DEFS[filter.id].label(v));
  switch (filter.id) {
    case 'date':
      return <DateEditor value={filter.value} onCommit={onCommit} onClose={onClose}/>;
    case 'reach':
      return <RangeEditor value={filter.value} defKey="reach" title="Reach" onCommit={onCommit} onClose={onClose} step={50000} min={0} max={50000000}/>;
    case 'spend':
      return <RangeEditor value={filter.value} defKey="spend" title="Daily spend" onCommit={onCommit} onClose={onClose} prefix="€" suffix=" daily" step={50} min={0} max={100000}/>;
    case 'format':
      return <MultiEditor value={filter.value} title="Ad format"
        options={[{ value:'image',label:'Image' },{ value:'video',label:'Video' },{ value:'carousel',label:'Carousel' },{ value:'collection',label:'Collection' }]}
        onCommit={(v) => { wrap(v); onClose(); }} onClose={onClose}/>;
    case 'cta':
      return <MultiEditor value={filter.value} title="Call to action"
        options={Object.entries(CTA_LABELS).map(([value,label]) => ({ value, label }))}
        onCommit={(v) => { wrap(v); onClose(); }} onClose={onClose}/>;
    case 'geo':
      return <MultiEditor value={filter.value} title="Country"
        options={Object.entries(COUNTRY_NAMES).map(([value,label]) => ({ value, label }))}
        onCommit={(v) => { wrap(v); onClose(); }} onClose={onClose}/>;
    case 'language':
      return <MultiEditor value={filter.value} title="Language"
        options={Object.entries(LANG_NAMES).map(([value,label]) => ({ value, label }))}
        onCommit={(v) => { wrap(v); onClose(); }} onClose={onClose}/>;
    case 'platform':
      return <MultiEditor value={filter.value} title="Platform"
        options={Object.entries(PLATFORM_NAMES).map(([value,label]) => ({ value, label }))}
        onCommit={(v) => { wrap(v); onClose(); }} onClose={onClose}/>;
    case 'industry':
      return <MultiEditor value={filter.value} title="Industry"
        options={Object.entries(INDUSTRY_NAMES).map(([value,label]) => ({ value, label }))}
        onCommit={(v) => { wrap(v); onClose(); }} onClose={onClose}/>;
    case 'shop':
      return <SingleEditor value={filter.value} title="Shop type"
        options={[{ value:'any',label:'Any shop' },{ value:'dropshipping',label:'Is dropshipping' },{ value:'brand',label:'Brand store' },{ value:'dtc',label:'DTC' }]}
        onCommit={(v) => { wrap(v); onClose(); }} onClose={onClose}/>;
    case 'creator':
      return <SingleEditor value={filter.value} title="Verified creator"
        options={[{ value:'any',label:'Any creator' },{ value:'verified',label:'Verified only' },{ value:'unverified',label:'Unverified only' }]}
        onCommit={(v) => { wrap(v); onClose(); }} onClose={onClose}/>;
    default:
      return <div style={POP_SHELL}>No editor for {filter.id}</div>;
  }
};

// ---------- matchers — applied to each ad in Explore ----------
// Filters without a corresponding field on the ad return `true` (no-op) so
// they remain visible in the UI without removing every ad.
const FILTER_MATCHERS = {
  reach:    (ad, v) => ad.reach >= v.min && ad.reach <= v.max,
  spend:    (ad, v) => ad.estSpend >= v.min && ad.estSpend <= v.max,
  format:   (ad, v) => v.length === 0 || v.includes(ad.type.toLowerCase()),
  geo:      (ad, v) => v.length === 0 || v.map(c => c.toLowerCase()).includes((ad.country || '').toLowerCase()),
  platform: (ad, v) => v.length === 0 || v.includes(ad.platform),
};

const applyFilters = (ads, filters) => {
  if (!filters || filters.length === 0) return ads;
  return ads.filter(ad => filters.every(f => {
    const m = FILTER_MATCHERS[f.id];
    return m ? m(ad, f.value) : true;
  }));
};

Object.assign(window, { FILTER_DEFS, FILTER_MATCHERS, FilterEditor, applyFilters });
