/*
 * 공개 GNB 정보 페이지 4종 (2026-07-23 소유자 지시 — 헤더 메뉴 데드링크(#top) 해소).
 * 자유 창작 금지: 기존 검증된 public 트랙 섹션 패턴(kxp-section·EventGrid·kxp-guide·kxp-transtrip·
 * kxp-list) + kx 토큰만 조합(coordinator 지침 옵션 b). 신규 토큰/하드코딩 색·폰트 0.
 * 데이터(라이브): 행사=/public/events · 참가안내=CMS PAGE · 관람안내=visitor-guide · 교통=transport.
 */
import { useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useSearchParams } from 'react-router-dom';
import type { ComponentType, FormEvent, SVGProps } from 'react';
import { PublicShell } from './PublicShell';
import { EventGrid, type EventsState } from './trackShared';
import {
  publicApi,
  type PublicEvent,
  type PublicNotice,
  type VisitorGuide,
  type TransportInfo,
} from './publicApi';
import { pickFeatured } from './trackShared';
import { errorMessage, deriveStatus } from './publicFormat';
import { EventSubscribeForm } from './EventSubscribeForm';
import {
  IconSearch,
  IconTrain,
  IconParking,
  IconMap,
  IconInfo,
  IconShield,
  IconChat,
  IconVenue,
  IconChevronRight,
  IconArrowRight,
} from './publicIcons';

type Ico = ComponentType<SVGProps<SVGSVGElement>>;

/** 방문가이드/교통 카테고리 → 아이콘 휴리스틱(VisitorTrackPage 동일 규칙 재사용). */
function guideIcon(cat: string | null, title: string | null): Ico {
  const s = `${cat ?? ''} ${title ?? ''}`.toLowerCase();
  if (/교통|transport|gtx|지하철|버스|subway|bus/.test(s)) return IconTrain;
  if (/주차|park/.test(s)) return IconParking;
  if (/길찾기|wayfind|지도|map|동선/.test(s)) return IconMap;
  if (/접근|access|휠체어|수어/.test(s)) return IconShield;
  if (/문의|faq|inquir|연락/.test(s)) return IconChat;
  return IconInfo;
}

// ══════════════════════════════════════════════════════════════════════════
// 1. 행사 목록 + 검색 (/public/events) — 헤더 검색 실행 대상.
// ══════════════════════════════════════════════════════════════════════════
export function PublicEventsListPage() {
  const { t } = useTranslation();
  const [params, setParams] = useSearchParams();
  const urlQ = params.get('q') ?? '';

  const [term, setTerm] = useState(urlQ);
  const [events, setEvents] = useState<PublicEvent[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');

  // URL q 변경(헤더 검색 이동 포함) → 재조회. 입력창은 URL 을 단일 출처로 동기화.
  useEffect(() => {
    setTerm(urlQ);
    let alive = true;
    setLoading(true);
    publicApi
      .listEvents(undefined, urlQ || undefined)
      .then((list) => {
        if (alive) {
          setEvents(pickFeatured(list, 60));
          setError('');
        }
      })
      .catch((e) => alive && setError(errorMessage(e)))
      .finally(() => alive && setLoading(false));
    return () => {
      alive = false;
    };
  }, [urlQ]);

  const state: EventsState = { events, loading, error };

  // F-C1: 오픈 예정(가장 가까운 upcoming) 행사에 대한 오픈 알림 구독 배너 대상.
  const upcomingTarget = useMemo(
    () => events.find((e) => deriveStatus(e.startDate, e.endDate) === 'upcoming') ?? null,
    [events],
  );

  function onSubmit(e: FormEvent) {
    e.preventDefault();
    const q = term.trim();
    setParams(q ? { q } : {});
  }

  return (
    <PublicShell active="events">
      <section className="kxp-section" aria-label={t('shell.nav.events')}>
        <div className="kxp-wrap">
          <div className="kxp-section__head">
            <div>
              <h1 className="kxp-section__title">
                <IconVenue className="kx-title-ic" width={22} height={22} />
                {t('shell.nav.events')}
              </h1>
              <p className="kxp-section__sub">
                {t('publicInfo.events.sub', { defaultValue: '진행 중·예정 행사를 검색하고 사전등록하세요.' })}
              </p>
            </div>
          </div>

          {/* 검색 폼 — 헤더 검색과 동일 대상(?q). 넓은 인라인 검색바. */}
          <form className="kxp-search kxp-search--page" role="search" onSubmit={onSubmit}>
            <button type="submit" className="kxp-search__btn" aria-label={t('shell.searchPlaceholder')}>
              <IconSearch className="kxp-search__icon" />
            </button>
            <input
              className="kxp-search__input"
              type="search"
              value={term}
              onChange={(e) => setTerm(e.target.value)}
              placeholder={t('shell.searchPlaceholder')}
              aria-label={t('shell.searchPlaceholder')}
            />
          </form>

          {urlQ && !loading && !error && (
            <p className="kxp-section__sub" role="status">
              {t('publicInfo.events.resultFor', { q: urlQ, n: events.length, defaultValue: '‘{{q}}’ 검색 결과 {{n}}건' })}
            </p>
          )}

          {/* F-C1: 오픈 예정 행사 구독 배너 — 가장 가까운 upcoming 행사가 있을 때만 */}
          {upcomingTarget && !loading && !error && (
            <div style={{ margin: 'var(--space-4) 0' }}>
              <EventSubscribeForm eventId={upcomingTarget.id} variant="banner" />
            </div>
          )}

          <EventGrid state={state} />
        </div>
      </section>
    </PublicShell>
  );
}

// ══════════════════════════════════════════════════════════════════════════
// 2. 참가안내 (/public/exhibit-guide) — CMS PAGE 콘텐츠.
// ══════════════════════════════════════════════════════════════════════════
export function PublicExhibitGuidePage() {
  const { t } = useTranslation();
  const [items, setItems] = useState<PublicNotice[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');

  useEffect(() => {
    let alive = true;
    setLoading(true);
    publicApi
      .listCms('PAGE', 30)
      .then((list) => alive && (setItems(list), setError('')))
      .catch((e) => alive && setError(errorMessage(e)))
      .finally(() => alive && setLoading(false));
    return () => {
      alive = false;
    };
  }, []);

  return (
    <PublicShell active="exhibit" cta={t('shell.footer.supportContact')}>
      <section className="kxp-section" aria-label={t('shell.nav.exhibit')}>
        <div className="kxp-wrap">
          <div className="kxp-section__head">
            <div>
              <h1 className="kxp-section__title">
                <IconInfo className="kx-title-ic" width={22} height={22} />
                {t('shell.nav.exhibit')}
              </h1>
              <p className="kxp-section__sub">
                {t('publicInfo.exhibit.sub', { defaultValue: '참가업체를 위한 부스 신청·시공·운영 안내입니다.' })}
              </p>
            </div>
          </div>

          {loading && (
            <p className="kxp-empty" role="status">
              {t('home.loading')}
            </p>
          )}
          {!loading && (error || items.length === 0) && (
            <p className="kxp-empty">
              {t('publicInfo.exhibit.empty', { defaultValue: '등록된 참가안내 콘텐츠가 없습니다. 문의하기로 상담을 요청하세요.' })}
            </p>
          )}
          {!loading && !error && items.length > 0 && (
            <div className="kxp-guidegrid">
              {items.map((it) => (
                <article key={it.id} className="kxp-guide">
                  <span className="kxp-guide__ic" aria-hidden>
                    <IconInfo width={22} height={22} />
                  </span>
                  <div>
                    <div className="kxp-guide__title">{it.title}</div>
                    <p className="kxp-guide__desc">{it.body ?? ''}</p>
                  </div>
                </article>
              ))}
            </div>
          )}
        </div>
      </section>
    </PublicShell>
  );
}

// ══════════════════════════════════════════════════════════════════════════
// 3. 관람안내 (/public/visit-guide) — visitor-guide 라이브 데이터.
// ══════════════════════════════════════════════════════════════════════════
export function PublicVisitGuidePage() {
  const { t } = useTranslation();
  const [guides, setGuides] = useState<VisitorGuide[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');

  useEffect(() => {
    let alive = true;
    setLoading(true);
    publicApi
      .listVisitorGuide()
      .then((list) => alive && (setGuides(list), setError('')))
      .catch((e) => alive && setError(errorMessage(e)))
      .finally(() => alive && setLoading(false));
    return () => {
      alive = false;
    };
  }, []);

  return (
    <PublicShell active="visit" track="visitor">
      <section className="kxp-section" aria-label={t('shell.nav.visit')}>
        <div className="kxp-wrap">
          <div className="kxp-section__head">
            <div>
              <h1 className="kxp-section__title">
                <IconMap className="kx-title-ic" width={22} height={22} />
                {t('shell.nav.visit')}
              </h1>
              <p className="kxp-section__sub">
                {t('publicInfo.visit.sub', { defaultValue: '입장·편의시설·접근성 등 관람에 필요한 안내입니다.' })}
              </p>
            </div>
          </div>

          {loading && (
            <p className="kxp-empty" role="status">
              {t('home.loading')}
            </p>
          )}
          {!loading && (error || guides.length === 0) && (
            <p className="kxp-empty">
              {t('publicInfo.visit.empty', { defaultValue: '등록된 관람안내가 없습니다.' })}
            </p>
          )}
          {!loading && !error && guides.length > 0 && (
            <div className="kxp-guidegrid">
              {guides.map((g) => {
                const Icon = guideIcon(g.category, g.title);
                return (
                  <article key={g.id} className="kxp-guide">
                    <span className="kxp-guide__ic" aria-hidden>
                      <Icon width={22} height={22} />
                    </span>
                    <div>
                      <div className="kxp-guide__title">{g.title}</div>
                      <p className="kxp-guide__desc">{g.summary || g.body || ''}</p>
                      {g.sourceUrl && (
                        <a
                          className="kxp-guide__link"
                          href={g.sourceUrl}
                          target="_blank"
                          rel="noreferrer noopener"
                        >
                          {t('track.visitor.guideMore')} <IconChevronRight width={15} height={15} />
                        </a>
                      )}
                    </div>
                  </article>
                );
              })}
            </div>
          )}
        </div>
      </section>
    </PublicShell>
  );
}

// ══════════════════════════════════════════════════════════════════════════
// 4. 교통 (/public/transport) — transport 라이브 데이터.
// ══════════════════════════════════════════════════════════════════════════
export function PublicTransportPage() {
  const { t } = useTranslation();
  const [transport, setTransport] = useState<TransportInfo[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');

  useEffect(() => {
    let alive = true;
    setLoading(true);
    publicApi
      .listTransport()
      .then((list) => alive && (setTransport(list), setError('')))
      .catch((e) => alive && setError(errorMessage(e)))
      .finally(() => alive && setLoading(false));
    return () => {
      alive = false;
    };
  }, []);

  // 수단(mode)별 그룹 — 라이브 데이터 순서 보존.
  const groups = useMemo(() => {
    const map = new Map<string, TransportInfo[]>();
    transport.forEach((tr) => {
      const key = tr.mode || '기타';
      const arr = map.get(key) ?? [];
      arr.push(tr);
      map.set(key, arr);
    });
    return Array.from(map.entries());
  }, [transport]);

  return (
    <PublicShell active="transport" track="visitor">
      <section className="kxp-section" aria-label={t('shell.nav.transport')}>
        <div className="kxp-wrap">
          <div className="kxp-section__head">
            <div>
              <h1 className="kxp-section__title">
                <IconTrain className="kx-title-ic" width={22} height={22} />
                {t('shell.nav.transport')}
              </h1>
              <p className="kxp-section__sub">
                {t('shell.footer.contactAddress')} · {t('publicInfo.transport.sub', { defaultValue: '대중교통·자가용·셔틀 안내' })}
              </p>
            </div>
          </div>

          {loading && (
            <p className="kxp-empty" role="status">
              {t('home.loading')}
            </p>
          )}
          {!loading && (error || transport.length === 0) && (
            <p className="kxp-empty">
              {t('publicInfo.transport.empty', { defaultValue: '등록된 교통 안내가 없습니다.' })}
            </p>
          )}
          {!loading && !error && transport.length > 0 &&
            groups.map(([mode, rows]) => (
              <div key={mode} className="kxp-tgroup">
                <h2 className="kxp-tgroup__title">{mode}</h2>
                <div className="kxp-transtrip">
                  {rows.map((tr) => (
                    <div key={tr.id} className="kxp-transtrip__item">
                      <span className="kxp-transtrip__ic" aria-hidden>
                        <IconTrain width={18} height={18} />
                      </span>
                      <div>
                        <div className="kxp-transtrip__name">{tr.lineName || tr.mode}</div>
                        <div className="kxp-transtrip__desc">
                          {[tr.route, tr.fromPoint, tr.travelTime, tr.note]
                            .filter(Boolean)
                            .join(' · ')}
                        </div>
                        {tr.sourceUrl && (
                          <a
                            className="kxp-guide__link"
                            href={tr.sourceUrl}
                            target="_blank"
                            rel="noreferrer noopener"
                          >
                            {t('track.visitor.guideMore')} <IconArrowRight width={15} height={15} />
                          </a>
                        )}
                      </div>
                    </div>
                  ))}
                </div>
              </div>
            ))}
        </div>
      </section>
    </PublicShell>
  );
}
