/*
 * F-C8 셀프 체크인 키오스크·즉석 배지 인쇄 — 전용 풀스크린 모드.
 * 체크인 로직은 SCR-31 체크인 API 재사용(visitorApi.checkin/search). 성공 시 배지 미리보기 → 인쇄(window.print).
 * ★ 보안 불변: 관람객 이름은 서버 마스킹 필드만 소비(원문 미노출). 3상태 준수.
 * 자체 스타일(kiosk.css, @media print 배지 규격) — 공유 css 무수정.
 */
import { useState } from 'react';
import { useMutation } from '@tanstack/react-query';
import { useResolvedEventId } from '../../hooks/useResolvedEventId';
import { ApiRequestError } from '../../api/client';
import { EmptyState } from '../../components/ui/States';
import { REG_TYPE_LABEL, type RegVisitorType } from './sampleVisitor';
import { visitorApi, type CheckinResultDto, type CheckinSearchItemDto } from './visitorApi';
import './kiosk.css';

const KNOWN_TYPES: RegVisitorType[] = ['visitor', 'buyer', 'vip'];
function typeLabel(type: string): string {
  const t = (KNOWN_TYPES as string[]).includes(type) ? (type as RegVisitorType) : 'visitor';
  return REG_TYPE_LABEL[t];
}

export function KioskCheckinPage() {
  const eventId = useResolvedEventId();
  const [token, setToken] = useState('');
  const [search, setSearch] = useState('');
  const [results, setResults] = useState<CheckinSearchItemDto[] | null>(null);
  const [card, setCard] = useState<CheckinResultDto | null>(null);
  const [error, setError] = useState<string | null>(null);

  const checkinMut = useMutation({
    mutationFn: (body: { token?: string; registrationId?: string }) => visitorApi.checkin(eventId as string, body),
    onSuccess: (res) => {
      setCard(res);
      setError(null);
      setToken('');
      setSearch('');
      setResults(null);
    },
    onError: (e) =>
      setError(
        e instanceof ApiRequestError && e.code === 'NOT_FOUND'
          ? '등록 정보를 찾을 수 없습니다. 안내데스크에서 현장 등록해 주세요.'
          : '체크인 처리 중 오류가 발생했습니다. 다시 시도해 주세요.',
      ),
  });

  const reissueMut = useMutation({
    mutationFn: (registrationId: string) => visitorApi.reissueBadge(eventId as string, registrationId),
    onSuccess: (res) => setCard((c) => (c ? { ...c, badgeCode: res.badgeCode, badgeIssued: true } : c)),
  });

  const runSearch = async () => {
    if (!eventId || search.trim().length < 2) {
      setError('검색어를 2자 이상 입력해 주세요.');
      return;
    }
    setError(null);
    try {
      setResults(await visitorApi.checkinSearch(eventId, search.trim()));
    } catch {
      setResults([]);
      setError('검색 중 오류가 발생했습니다.');
    }
  };

  const reset = () => {
    setCard(null);
    setError(null);
    setToken('');
    setSearch('');
    setResults(null);
  };

  if (!eventId) {
    return (
      <div className="kx-kiosk">
        <EmptyState title="행사를 선택해 주세요" description="체크인을 진행할 행사가 지정되지 않았습니다." />
      </div>
    );
  }

  // 성공: 배지 미리보기 + 인쇄
  if (card) {
    return (
      <div className="kx-kiosk kx-kiosk--done">
        <div className="kx-kiosk__badge" id="kioskBadge">
          <div className="kx-kbadge">
            <div className="kx-kbadge__top">
              <span className="kx-kbadge__event">KINTEX · {eventId}</span>
              <span className={`kx-kbadge__type is-${(KNOWN_TYPES as string[]).includes(card.type) ? card.type : 'visitor'}`}>
                {typeLabel(card.type)}
              </span>
            </div>
            <div className="kx-kbadge__name">{card.nameMasked}</div>
            <div className="kx-kbadge__company">{card.company ?? ' '}</div>
            <div className="kx-kbadge__qr" aria-hidden="true">
              <BadgeQr code={card.badgeCode ?? ''} />
            </div>
            <div className="kx-kbadge__code">{card.badgeCode ?? '-'}</div>
          </div>
        </div>

        <div className="kx-kiosk__done-actions">
          <p className="kx-kiosk__done-msg">
            {card.alreadyCheckedIn ? '이미 체크인된 방문객입니다.' : '체크인이 완료되었습니다.'}
          </p>
          <button type="button" className="kx-kiosk__btn kx-kiosk__btn--primary" onClick={() => window.print()}>
            배지 인쇄
          </button>
          {!card.badgeIssued && (
            <button
              type="button"
              className="kx-kiosk__btn"
              onClick={() => reissueMut.mutate(card.registrationId)}
              disabled={reissueMut.isPending}
            >
              {reissueMut.isPending ? '발급 중…' : '배지 발급'}
            </button>
          )}
          <button type="button" className="kx-kiosk__btn kx-kiosk__btn--ghost" onClick={reset}>
            처음으로
          </button>
          <p className="kx-kiosk__pii">개인정보 보호 · 이름 마스킹 표기</p>
        </div>
      </div>
    );
  }

  // 입력: 토큰 스캔 + 수동 검색
  return (
    <div className="kx-kiosk">
      <header className="kx-kiosk__head">
        <h1>셀프 체크인</h1>
        <p>배지 QR 토큰을 입력하거나 이름·연락처로 검색하세요.</p>
      </header>

      <form
        className="kx-kiosk__scan"
        onSubmit={(e) => {
          e.preventDefault();
          if (!token.trim()) {
            setError('QR 토큰(배지 코드)을 입력해 주세요.');
            return;
          }
          checkinMut.mutate({ token: token.trim() });
        }}
      >
        <label htmlFor="kiosk-token">QR 토큰 / 배지 코드</label>
        <input
          id="kiosk-token"
          className="kx-kiosk__input"
          value={token}
          onChange={(e) => setToken(e.target.value)}
          placeholder="예: QR-XXXX 또는 KTX-V-0001"
          autoComplete="off"
          autoFocus
        />
        <button type="submit" className="kx-kiosk__btn kx-kiosk__btn--primary" disabled={checkinMut.isPending}>
          {checkinMut.isPending ? '확인 중…' : '체크인'}
        </button>
      </form>

      <div className="kx-kiosk__or"><span>또는 이름·연락처로 검색</span></div>

      <div className="kx-kiosk__search">
        <input
          className="kx-kiosk__input"
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === 'Enter') {
              e.preventDefault();
              runSearch();
            }
          }}
          placeholder="이름 · 연락처 · 등록번호 (2자 이상)"
          autoComplete="off"
        />
        <button type="button" className="kx-kiosk__btn" onClick={runSearch}>검색</button>
      </div>

      {error && <p className="kx-kiosk__err" role="alert">{error}</p>}

      {results && results.length > 0 && (
        <ul className="kx-kiosk__results">
          {results.map((r) => (
            <li key={r.registrationId} className="kx-kiosk__result">
              <div>
                <span className="kx-kiosk__result-name">{r.nameMasked}</span>
                <span className="kx-kiosk__result-meta">{r.company ?? '-'} · {typeLabel(r.type)}</span>
              </div>
              {r.checkinState === 'done' ? (
                <span className="kx-kiosk__done-tag">완료</span>
              ) : (
                <button
                  type="button"
                  className="kx-kiosk__btn"
                  onClick={() => checkinMut.mutate({ registrationId: r.registrationId })}
                  disabled={checkinMut.isPending}
                >
                  체크인
                </button>
              )}
            </li>
          ))}
        </ul>
      )}
      {results && results.length === 0 && !error && (
        <p className="kx-kiosk__empty">검색 결과가 없습니다 — 안내데스크에서 현장 등록해 주세요.</p>
      )}
    </div>
  );
}

/** 배지 QR — 결정적 매트릭스(배지코드 기반, 인쇄용). 실 스캐너는 배지코드 텍스트 병기 소비. */
function BadgeQr({ code }: { code: string }) {
  const GRID = 21;
  let h = 2166136261;
  for (let i = 0; i < code.length; i++) {
    h ^= code.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 (
    <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>
  );
}
