/*
 * 관람객 마이 — F-C6 멤버십·F-B4/C5 세션 RSVP·F-C4 컨택트 지갑·F-B5 결제수단·F-C7 최근본·F-C5 알림.
 * 인증(본인만). 공용 client(JWT) 사용. ★ PII 불변: 서버 마스킹 필드만 소비.
 * 자체 스타일(account.css, kx 토큰만) — 공유 css 무수정. Nifty 카드/그리드·공용 Modal 재사용.
 */
import { useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useResolvedEventId } from '../../hooks/useResolvedEventId';
import { EmptyState, ErrorState, Skeleton } from '../../components/ui/States';
import { Button } from '../../components/ui/Button';
import { Modal } from '../../components/ui/Modal';
import { accountApi, type Contact, type SessionItem } from './visitorAccountApi';
import './account.css';

const TABS = [
  ['membership', '멤버십'],
  ['sessions', '세션 신청'],
  ['contacts', '컨택트 지갑'],
  ['payments', '결제수단'],
  ['feed', '최근 본'],
  ['alerts', '알림'],
] as const;
type TabKey = (typeof TABS)[number][0];

export function VisitorAccountPage() {
  const [tab, setTab] = useState<TabKey>('membership');
  const alertsQ = useQuery({ queryKey: ['visitorAlerts'], queryFn: () => accountApi.notifications(), retry: false });
  const unread = (alertsQ.data ?? []).filter((n) => !n.read).length;

  return (
    <div className="kx-vis kx-acct">
      <header className="kx-vis__head">
        <div>
          <h1 className="kx-vis__title">관람객 마이</h1>
          <p className="kx-vis__subtitle">멤버십 · 세션 · 컨택트 · 결제수단 · 최근 본 · 알림</p>
        </div>
      </header>

      <nav className="kx-acct__tabs" role="tablist" aria-label="관람객 마이 메뉴">
        {TABS.map(([k, label]) => (
          <button
            key={k}
            role="tab"
            aria-selected={tab === k}
            className={`kx-acct__tab${tab === k ? ' is-active' : ''}`}
            onClick={() => setTab(k)}
          >
            {label}
            {k === 'alerts' && unread > 0 && <span className="kx-acct__dot">{unread}</span>}
          </button>
        ))}
      </nav>

      <div className="kx-acct__body">
        {tab === 'membership' && <MembershipSection />}
        {tab === 'sessions' && <SessionsSection />}
        {tab === 'contacts' && <ContactsSection />}
        {tab === 'payments' && <PaymentsSection />}
        {tab === 'feed' && <FeedSection />}
        {tab === 'alerts' && <AlertsSection />}
      </div>
    </div>
  );
}

// ── F-C6 멤버십 ──
function MembershipSection() {
  const qc = useQueryClient();
  const q = useQuery({ queryKey: ['membership'], queryFn: () => accountApi.membership(), retry: false });
  const verifyMut = useMutation({
    mutationFn: (v: boolean) => accountApi.buyerVerify(v),
    onSuccess: () => qc.invalidateQueries({ queryKey: ['membership'] }),
  });

  if (q.isLoading) return <Skeleton height={200} radius={12} />;
  if (q.isError) return <ErrorState message="멤버십 정보를 불러오지 못했습니다." onRetry={() => void q.refetch()} />;
  const m = q.data!;
  return (
    <div className="kx-card kx-acct__card">
      <div className={`kx-mem__hero is-${m.tier.toLowerCase()}`}>
        <span className="kx-mem__tier">{m.tierLabel}</span>
        <span className="kx-mem__points">{m.points.toLocaleString()} P</span>
      </div>
      <div className="kx-mem__stats">
        <div><dt>누적 방문</dt><dd>{m.visitCount}회</dd></div>
        <div><dt>바이어 인증</dt><dd>{m.buyerVerified ? '완료' : '미인증'}</dd></div>
        <div><dt>VIP까지</dt><dd>{m.tier === 'VIP' ? '달성' : `방문 ${m.visitsToNextTier}회`}</dd></div>
      </div>
      <div className="kx-mem__benefits">
        <h3>등급 혜택</h3>
        <ul>{m.benefits.map((b) => <li key={b}>{b}</li>)}</ul>
      </div>
      {!m.buyerVerified && (
        <Button variant="secondary" onClick={() => verifyMut.mutate(true)} disabled={verifyMut.isPending}>
          {verifyMut.isPending ? '처리 중…' : '바이어 인증하기(데모)'}
        </Button>
      )}
    </div>
  );
}

// ── F-B4/C5 세션 RSVP ──
function SessionsSection() {
  const eventId = useResolvedEventId();
  const qc = useQueryClient();
  const q = useQuery({
    queryKey: ['visitorSessions', eventId],
    queryFn: () => accountApi.sessions(eventId as string),
    enabled: !!eventId,
    retry: false,
  });
  const rsvpMut = useMutation({
    mutationFn: (s: SessionItem) =>
      s.myStatus ? accountApi.cancelRsvp(s.id) : accountApi.rsvp(s.id),
    onSuccess: () => qc.invalidateQueries({ queryKey: ['visitorSessions', eventId] }),
  });

  if (!eventId) return <EmptyState title="행사를 선택해 주세요" />;
  if (q.isLoading) return <Skeleton height={240} radius={12} />;
  if (q.isError) return <ErrorState message="세션을 불러오지 못했습니다." onRetry={() => void q.refetch()} />;
  const sessions = q.data ?? [];
  if (sessions.length === 0) return <EmptyState title="등록된 세션이 없습니다." />;

  return (
    <div className="kx-acct__list">
      {sessions.map((s) => (
        <div key={s.id} className="kx-card kx-sess">
          <div className="kx-sess__info">
            <div className="kx-sess__head">
              <h3>{s.title}</h3>
              {s.track && <span className="kx-sess__track">{s.track}</span>}
            </div>
            <p className="kx-sess__meta">
              {s.speaker ?? ''} · {s.room ?? ''} · {(s.startsAt ?? '').replace('T', ' ').slice(0, 16)}
            </p>
            <div className="kx-sess__cap">
              {s.capacity === 0 ? (
                <span className="kx-sess__seats">정원 제한 없음</span>
              ) : (
                <span className={`kx-sess__seats${s.full ? ' is-full' : ''}`}>
                  {s.full ? '정원 마감' : `잔여 ${s.remaining}석`} / {s.capacity}석
                </span>
              )}
              {s.myStatus === 'CONFIRMED' && <span className="kx-sess__badge is-ok">신청 확정</span>}
              {s.myStatus === 'WAITLIST' && <span className="kx-sess__badge is-wait">대기 등록</span>}
            </div>
          </div>
          <Button
            variant={s.myStatus ? 'secondary' : 'primary'}
            onClick={() => rsvpMut.mutate(s)}
            disabled={rsvpMut.isPending}
          >
            {s.myStatus ? '신청 취소' : s.full ? '대기 신청' : '신청'}
          </Button>
        </div>
      ))}
    </div>
  );
}

// ── F-C4 컨택트 지갑 ──
function ContactsSection() {
  const qc = useQueryClient();
  const [scan, setScan] = useState(false);
  const [scanValue, setScanValue] = useState('');
  const [scanError, setScanError] = useState('');
  const cardQ = useQuery({ queryKey: ['myCard'], queryFn: () => accountApi.myCard(), retry: false });
  const listQ = useQuery({ queryKey: ['contacts'], queryFn: () => accountApi.contacts(), retry: false });

  const exchangeMut = useMutation({
    mutationFn: (payload: string) => accountApi.exchange(payload),
    onSuccess: () => {
      setScan(false);
      setScanValue('');
      setScanError('');
      qc.invalidateQueries({ queryKey: ['contacts'] });
    },
    onError: () => setScanError('명함을 찾을 수 없습니다. QR 값을 확인해 주세요.'),
  });
  const delMut = useMutation({
    mutationFn: (id: string) => accountApi.deleteContact(id),
    onSuccess: () => qc.invalidateQueries({ queryKey: ['contacts'] }),
  });

  return (
    <div className="kx-acct__grid2">
      {/* 내 명함 QR */}
      <div className="kx-card kx-acct__card">
        <h3 className="kx-acct__card-title">내 명함</h3>
        {cardQ.isLoading ? (
          <Skeleton height={160} radius={12} />
        ) : cardQ.isError ? (
          <ErrorState message="명함을 불러오지 못했습니다." onRetry={() => void cardQ.refetch()} />
        ) : cardQ.data ? (
          <div className="kx-cc">
            <MiniQr payload={cardQ.data.qrPayload} />
            <div className="kx-cc__info">
              <b>{cardQ.data.displayName}</b>
              <span>{cardQ.data.company ?? ''} {cardQ.data.title ?? ''}</span>
              <span>{cardQ.data.emailMasked ?? ''}</span>
              <span>{cardQ.data.phoneMasked ?? ''}</span>
            </div>
            <p className="kx-cc__hint">상대에게 이 QR을 보여주면 상호 명함이 교환됩니다.</p>
          </div>
        ) : null}
        <Button variant="secondary" onClick={() => { setScan(true); setScanError(''); }}>
          QR로 명함 교환
        </Button>
      </div>

      {/* 지갑 목록 */}
      <div className="kx-card kx-acct__card">
        <h3 className="kx-acct__card-title">컨택트 지갑</h3>
        {listQ.isLoading ? (
          <Skeleton height={120} radius={12} />
        ) : (listQ.data ?? []).length === 0 ? (
          <EmptyState title="저장된 명함이 없습니다." description="QR을 교환해 명함을 저장하세요." />
        ) : (
          <ul className="kx-acct__contacts">
            {listQ.data!.map((c: Contact) => (
              <li key={c.id} className="kx-contact">
                <div>
                  <b>{c.displayName}</b>
                  <span>{c.company ?? ''} {c.title ?? ''}</span>
                  <span>{c.emailMasked ?? ''} {c.phoneMasked ?? ''}</span>
                  {c.memo && <em>{c.memo}</em>}
                </div>
                <button type="button" className="kx-contact__del" aria-label="삭제" onClick={() => delMut.mutate(c.id)}>×</button>
              </li>
            ))}
          </ul>
        )}
      </div>

      <Modal
        open={scan}
        onClose={() => setScan(false)}
        title="명함 QR 교환"
        footer={
          <>
            <Button variant="secondary" onClick={() => setScan(false)}>취소</Button>
            <Button onClick={() => scanValue.trim() && exchangeMut.mutate(scanValue.trim())} disabled={exchangeMut.isPending}>
              {exchangeMut.isPending ? '교환 중…' : '교환'}
            </Button>
          </>
        }
      >
        <div className="kx-acct__scan">
          <p>상대 명함 QR의 값을 입력(또는 스캔)하세요.</p>
          <input
            className="kx-acct__scan-input"
            value={scanValue}
            onChange={(e) => setScanValue(e.target.value)}
            placeholder="CONTACT|SHARE-XXXX"
          />
          {scanError && <p className="kx-acct__scan-err" role="alert">{scanError}</p>}
        </div>
      </Modal>
    </div>
  );
}

// ── F-B5 결제수단 ──
function PaymentsSection() {
  const qc = useQueryClient();
  const [add, setAdd] = useState(false);
  const [kind, setKind] = useState('card');
  const [brand, setBrand] = useState('');
  const [cardNumber, setCardNumber] = useState('');
  const [makeDefault, setMakeDefault] = useState(false);
  const q = useQuery({ queryKey: ['payMethods'], queryFn: () => accountApi.payMethods(), retry: false });

  const addMut = useMutation({
    mutationFn: () => accountApi.registerPayMethod({ kind, brand: brand.trim() || undefined, cardNumber: cardNumber.trim() || undefined, makeDefault }),
    onSuccess: () => {
      setAdd(false);
      setBrand('');
      setCardNumber('');
      setMakeDefault(false);
      qc.invalidateQueries({ queryKey: ['payMethods'] });
    },
  });
  const defMut = useMutation({ mutationFn: (id: string) => accountApi.setDefaultPayMethod(id), onSuccess: () => qc.invalidateQueries({ queryKey: ['payMethods'] }) });
  const delMut = useMutation({ mutationFn: (id: string) => accountApi.deletePayMethod(id), onSuccess: () => qc.invalidateQueries({ queryKey: ['payMethods'] }) });

  return (
    <div className="kx-card kx-acct__card">
      <div className="kx-acct__card-head">
        <h3 className="kx-acct__card-title">저장 결제수단</h3>
        <Button variant="secondary" onClick={() => setAdd(true)}>결제수단 추가</Button>
      </div>
      {q.isLoading ? (
        <Skeleton height={120} radius={12} />
      ) : (q.data ?? []).length === 0 ? (
        <EmptyState title="저장된 결제수단이 없습니다." description="사전 등록하면 빠른결제를 사용할 수 있습니다." />
      ) : (
        <ul className="kx-acct__pms">
          {q.data!.map((p) => (
            <li key={p.id} className="kx-pm">
              <div className="kx-pm__info">
                <b>{p.brand ?? p.kind}</b>
                <span>•••• {p.last4 ?? '----'} · {p.kind}</span>
                {p.isDefault && <span className="kx-pm__default">기본</span>}
              </div>
              <div className="kx-pm__actions">
                {!p.isDefault && <button type="button" onClick={() => defMut.mutate(p.id)}>기본 설정</button>}
                <button type="button" className="kx-pm__del" onClick={() => delMut.mutate(p.id)}>삭제</button>
              </div>
            </li>
          ))}
        </ul>
      )}

      <Modal
        open={add}
        onClose={() => setAdd(false)}
        title="결제수단 등록"
        footer={
          <>
            <Button variant="secondary" onClick={() => setAdd(false)}>취소</Button>
            <Button onClick={() => addMut.mutate()} disabled={addMut.isPending}>
              {addMut.isPending ? '등록 중…' : '등록(토큰화)'}
            </Button>
          </>
        }
      >
        <div className="kx-acct__form">
          <label><span>유형</span>
            <select value={kind} onChange={(e) => setKind(e.target.value)}>
              <option value="card">카드</option>
              <option value="easy">간편결제</option>
              <option value="bank">계좌이체</option>
            </select>
          </label>
          <label><span>브랜드/표시명</span><input value={brand} onChange={(e) => setBrand(e.target.value)} placeholder="신한카드 / 카카오페이" /></label>
          <label><span>카드번호(저장 안 함)</span><input value={cardNumber} onChange={(e) => setCardNumber(e.target.value)} placeholder="끝 4자리만 표시용" inputMode="numeric" /></label>
          <label className="kx-acct__check"><input type="checkbox" checked={makeDefault} onChange={(e) => setMakeDefault(e.target.checked)} /><span>기본 결제수단으로</span></label>
          <p className="kx-acct__note">카드 원문은 저장하지 않고 브랜드·끝4자리·모의 토큰만 보관합니다.</p>
        </div>
      </Modal>
    </div>
  );
}

// ── F-C7 최근 본 ──
function FeedSection() {
  const q = useQuery({ queryKey: ['visitorFeed'], queryFn: () => accountApi.feed(20), retry: false });
  if (q.isLoading) return <Skeleton height={160} radius={12} />;
  if (q.isError) return <ErrorState message="피드를 불러오지 못했습니다." onRetry={() => void q.refetch()} />;
  const items = q.data ?? [];
  if (items.length === 0) return <EmptyState title="최근 본 항목이 없습니다." description="행사·부스를 조회하면 여기에 표시됩니다." />;
  return (
    <ul className="kx-acct__feed">
      {items.map((f) => (
        <li key={f.id} className="kx-card kx-accfeed">
          <span className={`kx-accfeed__type is-${f.itemType.toLowerCase()}`}>{f.itemType === 'EVENT' ? '행사' : '부스'}</span>
          <div className="kx-accfeed__info">
            <b>{f.itemTitle}</b>
            {f.itemSub && <span>{f.itemSub}</span>}
          </div>
          <time>{(f.viewedAt ?? '').replace('T', ' ').slice(5, 16)}</time>
        </li>
      ))}
    </ul>
  );
}

// ── F-C5 알림 ──
function AlertsSection() {
  const qc = useQueryClient();
  const q = useQuery({ queryKey: ['visitorAlerts'], queryFn: () => accountApi.notifications(), retry: false });
  const readMut = useMutation({ mutationFn: (id: string) => accountApi.markNotificationRead(id), onSuccess: () => qc.invalidateQueries({ queryKey: ['visitorAlerts'] }) });
  const allMut = useMutation({ mutationFn: () => accountApi.markAllNotificationsRead(), onSuccess: () => qc.invalidateQueries({ queryKey: ['visitorAlerts'] }) });

  if (q.isLoading) return <Skeleton height={160} radius={12} />;
  if (q.isError) return <ErrorState message="알림을 불러오지 못했습니다." onRetry={() => void q.refetch()} />;
  const items = q.data ?? [];
  return (
    <div className="kx-acct__card">
      <div className="kx-acct__card-head">
        <h3 className="kx-acct__card-title">알림</h3>
        {items.some((n) => !n.read) && <Button variant="secondary" onClick={() => allMut.mutate()}>모두 읽음</Button>}
      </div>
      {items.length === 0 ? (
        <EmptyState title="알림이 없습니다." />
      ) : (
        <ul className="kx-acct__alerts">
          {items.map((n) => (
            <li key={n.id} className={`kx-alert${n.read ? '' : ' is-unread'}`} onClick={() => !n.read && readMut.mutate(n.id)}>
              <div className="kx-alert__info">
                <b>{n.title}</b>
                {n.body && <span>{n.body}</span>}
              </div>
              <time>{(n.createdAt ?? '').replace('T', ' ').slice(5, 16)}</time>
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

/** 미니 QR — 명함 공유 페이로드 결정적 매트릭스(시각). 실 스캔은 페이로드 텍스트 병기. */
function MiniQr({ payload }: { payload: string }) {
  const GRID = 21;
  let h = 2166136261;
  for (let i = 0; i < payload.length; i++) {
    h ^= payload.charCodeAt(i);
    h = Math.imul(h, 16777619);
  }
  const cells: boolean[] = [];
  for (let i = 0; i < GRID * GRID; i++) {
    h ^= i + 0x9e3779b9;
    h = Math.imul(h, 2654435761);
    cells.push(((h >>> (i % 31)) & 1) === 1);
  }
  const cell = 100 / GRID;
  return (
    <div className="kx-cc__qr">
      <svg viewBox="0 0 100 100" width="120" height="120" role="img" aria-label="내 명함 QR">
        <rect x="0" y="0" width="100" height="100" fill="#fff" />
        {cells.map((on, i) =>
          on ? <rect key={i} x={(i % GRID) * cell} y={Math.floor(i / GRID) * cell} width={cell} height={cell} fill="#101828" /> : null,
        )}
      </svg>
      <code>{payload}</code>
    </div>
  );
}
