import React, { useEffect, useState } from 'react';
import type { Note } from '@shared/types';
import { useInbox } from '../store.js';
import { Banner } from './Banner.js';
import { DAY_MS, kstTodayIso } from '@shared/util/kstDate.js';

/**
 * due_date 대비 오늘 (KST) 의 상대 라벨. 오늘 = "오늘", 지난 = "N일 지남".
 * findExpiredCandidates 가 미래 due 는 반환하지 않으므로 음수 케이스 미고려.
 */
function dueRelativeLabel(due: string, todayKst: string): string {
  if (due === todayKst) return '오늘';
  const dueUtc = Date.UTC(
    Number(due.slice(0, 4)), Number(due.slice(5, 7)) - 1, Number(due.slice(8, 10))
  );
  const todayUtc = Date.UTC(
    Number(todayKst.slice(0, 4)), Number(todayKst.slice(5, 7)) - 1, Number(todayKst.slice(8, 10))
  );
  const days = Math.round((todayUtc - dueUtc) / DAY_MS);
  return `${days}일 지남`;
}

function headingText(todayCount: number, overdueCount: number): string {
  if (todayCount > 0 && overdueCount > 0) return `오늘 마감 ${todayCount} · 지난 ${overdueCount}`;
  if (todayCount > 0) return `오늘 마감 ${todayCount}개`;
  return `지난 ${overdueCount}개`;
}

/** RecallBanner 와 동일 패턴 — NoteCard 의 `note-{id}` element 로 smooth scroll. */
function scrollToNote(id: string): void {
  const el = document.getElementById(`note-${id}`);
  if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' });
}

export function ExpiryBanner(): React.ReactElement | null {
  const candidates = useInbox((s) => s.expiredCandidates);
  const snoozeUntilMs = useInbox((s) => s.expiredSnoozeUntilMs);
  const trashExpiredBatch = useInbox((s) => s.trashExpiredBatch);
  const snoozeExpired = useInbox((s) => s.snoozeExpired);
  // n1 fix — snoozeUntilMs 가 set 되어 있고 아직 미래면 그 시점에 force re-render 트리거.
  // 24h+ 켜둔 상태에서 자정 KST 넘어 자동 collapse 해제 보장.
  const [, setTick] = useState(0);
  useEffect(() => {
    if (snoozeUntilMs === null) return;
    const remaining = snoozeUntilMs - Date.now();
    if (remaining <= 0) return;
    const t = setTimeout(() => setTick((n) => n + 1), remaining);
    return () => clearTimeout(t);
  }, [snoozeUntilMs]);

  // Q5=A: 0건 / snooze 활성 시 collapse
  if (candidates.length === 0) return null;
  if (snoozeUntilMs !== null && Date.now() < snoozeUntilMs) return null;

  return <ExpiryBannerInner
    candidates={candidates}
    onTrash={(ids) => {
      trashExpiredBatch(ids).catch((e) => {
        // eslint-disable-next-line no-console
        console.warn('trashExpiredBatch failed', e);
      });
    }}
    onSnooze={() => snoozeExpired()}
  />;
}

interface InnerProps {
  candidates: Note[];
  onTrash: (ids: string[]) => void;
  onSnooze: () => void;
}

function ExpiryBannerInner({ candidates, onTrash, onSnooze }: InnerProps): React.ReactElement {
  const [expanded, setExpanded] = useState<boolean>(true);
  const [selected, setSelected] = useState<Set<string>>(new Set());

  // candidates 가 변하면 selected 의 stale id 정리
  useEffect(() => {
    const valid = new Set(candidates.map((c) => c.id));
    setSelected((prev) => {
      const next = new Set<string>();
      for (const id of prev) if (valid.has(id)) next.add(id);
      return next;
    });
  }, [candidates]);

  const allSelected = candidates.length > 0 && candidates.every((c) => selected.has(c.id));
  const someSelected = selected.size > 0 && !allSelected;

  const todayKst = kstTodayIso();
  const todayCount = candidates.filter((c) => c.dueDate === todayKst).length;
  const overdueCount = candidates.length - todayCount;

  function toggleAll() {
    if (allSelected) setSelected(new Set());
    else setSelected(new Set(candidates.map((c) => c.id)));
  }

  function toggle(id: string) {
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  }

  return (
    <Banner severity="warning">
      <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
        <span>⏰ <b>{headingText(todayCount, overdueCount)}</b></span>
        <button
          onClick={() => setExpanded((e) => !e)}
          style={{ background: 'none', border: 'none', cursor: 'pointer', color: '#946100' }}
          aria-expanded={expanded}
        >
          {expanded ? '▲ 접기' : '▼ 펼치기'}
        </button>
        <button
          onClick={onSnooze}
          style={{
            marginLeft: 'auto',
            background: 'transparent', color: '#946100',
            border: '1px solid #d99500', borderRadius: 4,
            padding: '2px 8px', fontSize: 12, cursor: 'pointer'
          }}
        >
          오늘 그만
        </button>
      </div>
      {expanded && (
        <>
          <label style={{ display: 'flex', alignItems: 'center', gap: 6, margin: '8px 0 4px', cursor: 'pointer' }}>
            <input
              type="checkbox"
              checked={allSelected}
              ref={(el) => { if (el) el.indeterminate = someSelected; }}
              onChange={toggleAll}
            />
            <span style={{ color: '#666' }}>전체 선택 ({selected.size}/{candidates.length})</span>
          </label>
          <div>
            {candidates.map((n) => {
              const title = n.aiTitle ?? n.rawText.slice(0, 60);
              return (
                <div
                  key={n.id}
                  style={{
                    display: 'flex', alignItems: 'center', gap: 8,
                    padding: '4px 0'
                  }}
                >
                  <input
                    type="checkbox"
                    checked={selected.has(n.id)}
                    onChange={() => toggle(n.id)}
                    aria-label={`${title} 선택`}
                  />
                  <button
                    type="button"
                    onClick={() => scrollToNote(n.id)}
                    title="해당 메모로 이동"
                    style={{
                      flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
                      background: 'none', border: 'none', padding: 0,
                      cursor: 'pointer', color: 'inherit', font: 'inherit', textAlign: 'left'
                    }}
                  >
                    {title}
                  </button>
                  <span
                    style={{ color: '#946100', fontSize: 12 }}
                    title={`due ${n.dueDate}`}
                  >
                    {dueRelativeLabel(n.dueDate ?? todayKst, todayKst)}
                  </span>
                  {n.tags[0] && (
                    <span style={{
                      background: '#fce8b2', color: '#946100', padding: '0 6px',
                      borderRadius: 10, fontSize: 11
                    }}>
                      #{n.tags[0].name}
                    </span>
                  )}
                </div>
              );
            })}
          </div>
          <button
            onClick={() => onTrash(Array.from(selected))}
            disabled={selected.size === 0}
            style={{
              marginTop: 8,
              background: selected.size === 0 ? '#999' : '#a33', color: '#fff',
              border: 'none', borderRadius: 4,
              padding: '4px 12px', fontSize: 12,
              cursor: selected.size === 0 ? 'not-allowed' : 'pointer'
            }}
          >
            선택 휴지통 ({selected.size}개)
          </button>
        </>
      )}
    </Banner>
  );
}
