/*
 * SCR-P7 입장권 예매 (M10·M9) — 비로그인 공개.
 * design.md §3B. 예매 플로우(권종→예매자→결제→완료) + 예매 조회(주문번호+연락처).
 * 라이브: GET /api/public/tickets/{eventId}, POST .../orders, GET .../lookup (ticketApi).
 * 결제는 Mock PG(백엔드 어댑터) — 데모 승인. 응답의 구매자 정보는 서버 마스킹 필드만 소비(PII 원문 없음).
 * 3상태(로딩/빈/에러) 준수. 목록은 NETWORK/NOT_FOUND 강등 시에만 샘플 폴백(배지 표기).
 */
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useParams } from 'react-router-dom';
import { useMutation, useQuery } from '@tanstack/react-query';
import { PublicShell } from './PublicShell';
import { ticketApi, type TicketProduct } from './ticketApi';
import { errorMessage } from './publicFormat';
import { ApiRequestError } from '../../api/client';
import { EmptyState, ErrorState, Skeleton } from '../../components/ui/States';
import {
  IconTicket,
  IconCalendar,
  IconPin,
  IconPlus,
  IconMinus,
  IconShield,
  IconInfo,
  IconCheckCircle,
  IconQr,
  IconArrowRight,
  IconPerson,
} from './publicIcons';

const DEFAULT_EVENT_ID = 'e-2026-live';
const STEP_KEYS = ['ticket.steps.s1', 'ticket.steps.s2', 'ticket.steps.s3', 'ticket.steps.s4'];
const won = (n: number) => `₩${n.toLocaleString('ko-KR')}`;

/** NETWORK/NOT_FOUND/NOT_IMPLEMENTED 강등 시에만 샘플 폴백을 허용한다. */
function isDegradable(e: unknown): boolean {
  return (
    e instanceof ApiRequestError &&
    (e.code === 'NETWORK' || e.code === 'NOT_FOUND' || e.code === 'NOT_IMPLEMENTED' || e.httpStatus === 404)
  );
}

const SAMPLE_PRODUCTS: TicketProduct[] = [
  { id: 'general', eventId: '', code: 'GEN', kind: 'GENERAL', name: '일반권', description: '일반 관람객 및 개인 참가자', price: 15000, currency: 'KRW', saleStart: null, saleEnd: null, totalQty: 5000, remaining: 3758, maxPerOrder: 10, onSale: true, soldOut: false, sortOrder: 0 },
  { id: 'student', eventId: '', code: 'STU', kind: 'STUDENT', name: '학생/군인 할인권', description: '학생·군인 대상 할인(현장 신분 확인)', price: 8000, currency: 'KRW', saleStart: null, saleEnd: null, totalQty: 2000, remaining: 1679, maxPerOrder: 6, onSale: true, soldOut: false, sortOrder: 1 },
  { id: 'group', eventId: '', code: 'GRP', kind: 'GROUP', name: '단체권 (10매 이상)', description: '기업·기관 단체 관람 전용', price: 9000, currency: 'KRW', saleStart: null, saleEnd: null, totalQty: 3000, remaining: 2840, maxPerOrder: 100, onSale: true, soldOut: false, sortOrder: 2 },
];

function EventBanner() {
  const { t } = useTranslation();
  return (
    <div className="kxp-ticket__banner">
      <div
        className="kxp-ticket__poster"
        style={{ background: 'linear-gradient(135deg, #0066b3 0%, #6d4aff 130%)' }}
        role="img"
        aria-label={t('ticket.posterAria')}
      />
      <div>
        <h1>{t('ticket.bannerTitle')}</h1>
        <div className="kxp-ticket__facts">
          <span>
            <IconCalendar width={16} height={16} /> {t('ticket.bannerDate')}
          </span>
          <span>
            <IconPin width={16} height={16} /> {t('ticket.bannerPlace')}
          </span>
        </div>
      </div>
    </div>
  );
}

interface Selection {
  id: string;
  qty: number;
}

function PurchaseView({ eventId }: { eventId: string }) {
  const { t } = useTranslation();
  const [step, setStep] = useState(0);
  const [sel, setSel] = useState<Selection | null>(null);
  const [pay, setPay] = useState('card');
  const [name, setName] = useState('');
  const [contact, setContact] = useState('');
  const [email, setEmail] = useState('');
  const [agreePrivacy, setAgreePrivacy] = useState(false);
  const [formError, setFormError] = useState('');

  const productsQ = useQuery({
    queryKey: ['ticketProducts', eventId],
    queryFn: () => ticketApi.listProducts(eventId),
    retry: false,
  });

  const degraded = productsQ.isError && isDegradable(productsQ.error);
  const products: TicketProduct[] = degraded ? SAMPLE_PRODUCTS : (productsQ.data ?? []);

  const orderMut = useMutation({
    mutationFn: () =>
      ticketApi.createOrder(eventId, {
        productId: sel!.id,
        qty: sel!.qty,
        buyerName: name.trim(),
        buyerContact: contact.trim(),
        buyerEmail: email.trim() || undefined,
        agreePrivacy,
        payMethod: pay,
      }),
    onSuccess: () => setStep(3),
  });

  const selProduct = sel ? products.find((p) => p.id === sel.id) ?? null : null;
  const total = sel && selProduct ? selProduct.price * sel.qty : 0;
  const count = sel ? sel.qty : 0;
  const isFree = total === 0 && count > 0;

  const setCount = (p: TicketProduct, delta: number) => {
    if (p.soldOut || !p.onSale) return;
    setSel((prev) => {
      if (prev && prev.id === p.id) {
        const q = prev.qty + delta;
        if (q <= 0) return null;
        return { id: p.id, qty: Math.min(q, p.maxPerOrder) };
      }
      if (delta > 0) return { id: p.id, qty: 1 };
      return prev;
    });
  };

  const proceed = () => {
    setFormError('');
    if (step === 0) {
      if (!sel || count === 0) {
        setFormError(t('ticket.selectPrompt'));
        return;
      }
      setStep(1);
      return;
    }
    if (step === 1) {
      if (!name.trim()) {
        setFormError(t('ticket.errName'));
        return;
      }
      if (!contact.trim()) {
        setFormError(t('ticket.errContact'));
        return;
      }
      if (!agreePrivacy) {
        setFormError(t('ticket.errPrivacy'));
        return;
      }
      if (isFree) {
        orderMut.mutate();
        return;
      }
      setStep(2);
      return;
    }
    if (step === 2) {
      orderMut.mutate();
    }
  };

  const back = () => {
    setFormError('');
    if (step === 3) {
      setStep(1);
      return;
    }
    setStep((s) => Math.max(0, s - 1));
  };

  const result = orderMut.data;

  return (
    <>
      <EventBanner />

      <div className="kxp-ticket__steps" role="list" aria-label={t('ticket.stepsAria')}>
        {STEP_KEYS.map((l, i) => (
          <span
            key={l}
            className={`kxp-ticket__step${i === step ? ' is-active' : ''}`}
            role="listitem"
            aria-current={i === step ? 'step' : undefined}
          >
            {`0${i + 1} `}
            {t(l)}
          </span>
        ))}
      </div>

      <div className="kxp-loginbanner">
        <IconInfo width={18} height={18} /> {t('ticket.loginBanner')}
        <a href="#top">{t('ticket.loginLink')}</a>
      </div>

      <div className="kxp-ticket__grid">
        <div className="kxp-ticket__main">
          {/* Step 1: 권종 */}
          {step === 0 && (
            <section>
              <h2 className="kxp-ticket__h2">
                <IconTicket width={20} height={20} /> {t('ticket.h2Type')}
                {degraded && (
                  <span className="kxp-sample" style={{ marginLeft: 'auto' }}>
                    {t('ticket.sample')}
                  </span>
                )}
              </h2>

              {productsQ.isLoading ? (
                <div className="kxp-tickrows">
                  {[0, 1, 2].map((k) => (
                    <div key={k} className="kxp-tickrow">
                      <div className="kxp-tickrow__info">
                        <Skeleton height={18} width="40%" />
                        <Skeleton height={12} width="70%" />
                      </div>
                    </div>
                  ))}
                </div>
              ) : productsQ.isError && !degraded ? (
                <ErrorState message={errorMessage(productsQ.error)} onRetry={() => void productsQ.refetch()} />
              ) : products.length === 0 ? (
                <EmptyState title={t('ticket.emptyProducts')} icon={<IconTicket width={28} height={28} />} />
              ) : (
                <div className="kxp-tickrows">
                  {products.map((p) => {
                    const disabled = p.soldOut || !p.onSale;
                    const q = sel && sel.id === p.id ? sel.qty : 0;
                    return (
                      <div
                        key={p.id}
                        className={`kxp-tickrow${disabled ? ' kxp-tickrow--soldout' : ''}`}
                        style={{ borderLeftColor: disabled ? undefined : '#0066b3' }}
                      >
                        <div className="kxp-tickrow__info">
                          <h3>
                            {p.name}
                            {p.soldOut && <span className="kxp-status kxp-status--soldout">{t('ticket.soldout')}</span>}
                            {!p.soldOut && !p.onSale && (
                              <span className="kxp-status kxp-status--soldout">{t('ticket.saleClosed')}</span>
                            )}
                          </h3>
                          {p.description && <p>{p.description}</p>}
                          <div className="kxp-tickrow__price">
                            {p.price === 0 ? t('ticket.free') : won(p.price)}
                            <span style={{ marginLeft: 10, fontSize: 11, color: 'var(--color-neutral-500)' }}>
                              {t('ticket.remaining', { n: Math.max(0, p.remaining) })}
                            </span>
                          </div>
                        </div>
                        <div className="kxp-stepper" aria-label={t('ticket.qtyAria', { name: p.name })}>
                          <button
                            type="button"
                            aria-label={t('ticket.decrease')}
                            disabled={disabled}
                            onClick={() => setCount(p, -1)}
                          >
                            <IconMinus width={16} height={16} />
                          </button>
                          <span>{q}</span>
                          <button
                            type="button"
                            aria-label={t('ticket.increase')}
                            disabled={disabled}
                            onClick={() => setCount(p, 1)}
                          >
                            <IconPlus width={16} height={16} />
                          </button>
                        </div>
                      </div>
                    );
                  })}
                </div>
              )}
            </section>
          )}

          {/* Step 2: 예매자 */}
          {step === 1 && (
            <section>
              <h2 className="kxp-ticket__h2">
                <IconPerson width={20} height={20} /> {t('ticket.h2Booker')}
              </h2>
              <div className="kxp-formcard">
                <div className="kxp-formgrid kxp-formgrid--2">
                  <div className="kxp-field">
                    <label htmlFor="tk-name">{t('ticket.bookerName')}</label>
                    <input
                      id="tk-name"
                      className="kxp-input"
                      placeholder={t('ticket.bookerNamePh')}
                      value={name}
                      onChange={(e) => setName(e.target.value)}
                    />
                  </div>
                  <div className="kxp-field">
                    <label htmlFor="tk-tel">{t('ticket.bookerTel')}</label>
                    <input
                      id="tk-tel"
                      className="kxp-input"
                      type="tel"
                      placeholder="010-0000-0000"
                      value={contact}
                      onChange={(e) => setContact(e.target.value)}
                    />
                  </div>
                  <div className="kxp-field kxp-formgrid__full">
                    <label htmlFor="tk-email">{t('ticket.bookerEmail')}</label>
                    <input
                      id="tk-email"
                      className="kxp-input"
                      type="email"
                      placeholder="example@domain.com"
                      value={email}
                      onChange={(e) => setEmail(e.target.value)}
                    />
                  </div>
                </div>
                <div className="kxp-consent">
                  <label className="kxp-check">
                    <input type="checkbox" checked={agreePrivacy} onChange={(e) => setAgreePrivacy(e.target.checked)} />
                    <span>
                      {t('ticket.consentPrivacy')} <span className="kxp-check__req">{t('ticket.required')}</span>
                    </span>
                  </label>
                  <label className="kxp-check">
                    <input type="checkbox" />
                    <span>{t('ticket.consentMarketing')}</span>
                  </label>
                </div>
              </div>
            </section>
          )}

          {/* Step 3: 결제 */}
          {step === 2 && (
            <section>
              <h2 className="kxp-ticket__h2">
                <IconShield width={20} height={20} /> {t('ticket.h2Pay')}
              </h2>
              <div className="kxp-paychips" role="group" aria-label={t('ticket.payGroupAria')}>
                {[
                  ['card', t('ticket.payCard')],
                  ['easy', t('ticket.payEasy')],
                  ['bank', t('ticket.payBank')],
                ].map(([k, label]) => (
                  <button
                    key={k}
                    type="button"
                    className={`kxp-paychip${pay === k ? ' is-active' : ''}`}
                    aria-pressed={pay === k}
                    onClick={() => setPay(k)}
                  >
                    {label}
                  </button>
                ))}
              </div>
              <div className="kxp-pgnote">
                <IconShield width={18} height={18} />
                <span>{t('ticket.pgNote')}</span>
              </div>
            </section>
          )}

          {/* Step 4: 완료 */}
          {step === 3 && result && (
            <section className="kxp-tikdone">
              <div className="kxp-done__ic" style={{ margin: '0 auto 16px' }}>
                <IconCheckCircle width={40} height={40} />
              </div>
              <h2 className="kxp-regcard__title">{t('ticket.doneTitle')}</h2>
              <div className="kxp-tikdone__no">{result.orderNo}</div>
              <p className="kxp-regcard__sub">
                {t('ticket.doneSub', { count: result.qty, total: won(result.totalAmount) })}
              </p>
              <div className="kxp-tikdone__qr">
                <IconQr width={110} height={110} />
              </div>
              <div className="kxp-formcard" style={{ textAlign: 'left', maxWidth: 420, margin: '4px auto 0' }}>
                <div className="kxp-sumrow">
                  <span>{t('ticket.colType')}</span>
                  <span>{result.productName}</span>
                </div>
                {result.approvalNo && (
                  <div className="kxp-sumrow">
                    <span>{t('ticket.approvalNo')}</span>
                    <span>{result.approvalNo}</span>
                  </div>
                )}
                <div className="kxp-sumrow">
                  <span>{t('ticket.ticketCodes')}</span>
                  <span style={{ textAlign: 'right' }}>
                    {result.tickets.map((tk) => (
                      <span key={tk.ticketCode} style={{ display: 'block', fontFamily: 'monospace' }}>
                        {tk.ticketCode}
                      </span>
                    ))}
                  </span>
                </div>
              </div>
              <div className="kxp-tikdone__actions">
                <a className="kxp-btn kxp-btn--outline" href="#top">
                  {t('ticket.walletBtn')}
                </a>
                <a className="kxp-btn kxp-btn--primary" href="/tickets/lookup">
                  {t('ticket.manageBtn')} <IconArrowRight width={18} height={18} />
                </a>
              </div>
            </section>
          )}
        </div>

        {/* 우측 요약 */}
        {step < 3 && (
          <aside className="kxp-ticket__summary" aria-label={t('ticket.summaryAria')}>
            <h3>{t('ticket.summaryTitle')}</h3>
            <div className="kxp-sumrow">
              <span>{t('ticket.summaryCount')}</span>
              <span>{t('ticket.count', { n: count })}</span>
            </div>
            <div className="kxp-sumrow">
              <span>{t('ticket.subtotal')}</span>
              <span>{won(total)}</span>
            </div>
            <div className="kxp-sumtotal">
              <small>{t('ticket.finalTotal')}</small>
              <strong>{isFree ? t('ticket.free') : won(total)}</strong>
            </div>

            {(formError || orderMut.isError) && (
              <p className="kxp-formerror" role="alert" style={{ color: 'var(--color-danger-600, #d92d20)', fontSize: 12, margin: '10px 0 0' }}>
                {formError || errorMessage(orderMut.error)}
              </p>
            )}

            <button
              type="button"
              className="kxp-btn kxp-btn--primary kxp-btn--block kxp-btn--lg"
              disabled={count === 0 || orderMut.isPending}
              onClick={proceed}
            >
              {orderMut.isPending
                ? t('ticket.processing')
                : step === 0
                  ? t('ticket.nextStep')
                  : step === 1
                    ? isFree
                      ? t('ticket.freeDone')
                      : t('ticket.pay')
                    : t('ticket.payProceed')}
            </button>
            {step > 0 && (
              <button
                type="button"
                className="kxp-btn kxp-btn--outline kxp-btn--block"
                style={{ marginTop: 10 }}
                onClick={back}
                disabled={orderMut.isPending}
              >
                {t('common.actions.prev')}
              </button>
            )}
            <p style={{ marginTop: 14, fontSize: 11, textAlign: 'center', color: 'var(--color-neutral-500)' }}>
              {t('ticket.customerCenter')}
            </p>
          </aside>
        )}
      </div>
    </>
  );
}

function ManageView() {
  const { t } = useTranslation();
  const [orderNo, setOrderNo] = useState('');
  const [contact, setContact] = useState('');
  const [formError, setFormError] = useState('');

  const lookupMut = useMutation({
    mutationFn: () => ticketApi.lookup(orderNo.trim(), contact.trim()),
  });

  const submit = () => {
    setFormError('');
    if (!orderNo.trim() || !contact.trim()) {
      setFormError(t('ticket.lookupHint'));
      return;
    }
    lookupMut.mutate();
  };

  const r = lookupMut.data;

  return (
    <>
      <header style={{ textAlign: 'center', marginBottom: 24 }}>
        <h1 className="kxp-regcard__title">{t('ticket.manageTitle')}</h1>
        <p className="kxp-regcard__sub" style={{ marginBottom: 0 }}>
          {t('ticket.manageSub')}
        </p>
      </header>

      <div className="kxp-manage__lookup">
        <div className="kxp-manage__lookrow">
          <div className="kxp-field">
            <label htmlFor="mg-no">{t('ticket.lookNo')}</label>
            <input
              id="mg-no"
              className="kxp-input"
              placeholder={t('ticket.lookNoPh')}
              value={orderNo}
              onChange={(e) => setOrderNo(e.target.value)}
            />
          </div>
          <div className="kxp-field">
            <label htmlFor="mg-contact">{t('ticket.lookContact')}</label>
            <input
              id="mg-contact"
              className="kxp-input"
              type="tel"
              placeholder={t('ticket.lookContactPh')}
              value={contact}
              onChange={(e) => setContact(e.target.value)}
            />
          </div>
          <button type="button" className="kxp-btn kxp-btn--primary" onClick={submit} disabled={lookupMut.isPending}>
            {lookupMut.isPending ? t('ticket.processing') : t('ticket.lookBtn')}
          </button>
        </div>
        {(formError || lookupMut.isError) && (
          <p role="alert" style={{ textAlign: 'center', marginTop: 12, color: 'var(--color-danger-600, #d92d20)', fontSize: 13 }}>
            {formError || (lookupMut.isError ? t('ticket.notFound') : '')}
          </p>
        )}
      </div>

      {!r ? (
        <p className="kxp-empty">{t('ticket.lookupHint')}</p>
      ) : (
        <div className="kxp-manage__grid">
          <div>
            <article className="kxp-bookcard">
              <div className="kxp-bookcard__head">
                <div>
                  <span className="kxp-status kxp-status--done">{t('ticket.booked')}</span>
                  <h2>{r.productName}</h2>
                  <span className="kxp-bookcard__no">
                    {t('ticket.bookNoLabel')} <b>{r.orderNo}</b>
                  </span>
                </div>
                <div className="kxp-bookcard__paid">
                  <small>{t('ticket.paidAt')}</small>
                  <br />
                  <b>{(r.paidAt ?? r.orderedAt ?? '').replace('T', ' ').slice(0, 16) || '-'}</b>
                </div>
              </div>

              <table className="kxp-ticktable">
                <thead>
                  <tr>
                    <th>{t('ticket.colType')}</th>
                    <th>{t('ticket.colQty')}</th>
                    <th>{t('ticket.colAmount')}</th>
                  </tr>
                </thead>
                <tbody>
                  {r.tickets.map((tk) => (
                    <tr key={tk.ticketCode}>
                      <td>
                        <div className="kxp-ticktable__cell">
                          <span className="kxp-ticktable__qr">
                            <IconQr width={22} height={22} />
                          </span>
                          <span style={{ fontFamily: 'monospace' }}>{tk.ticketCode}</span>
                        </div>
                      </td>
                      <td>{t('ticket.count', { n: 1 })}</td>
                      <td>{won(r.unitPrice)}</td>
                    </tr>
                  ))}
                </tbody>
              </table>

              <div className="kxp-booker">
                <div className="kxp-booker__id">
                  <IconPerson width={20} height={20} />
                  <div>
                    <small>{t('ticket.bookerInfo')}</small>
                    <br />
                    <b>
                      {r.buyerNameMasked} · {r.buyerContactMasked}
                      {r.buyerEmailMasked ? ` · ${r.buyerEmailMasked}` : ''}
                    </b>
                  </div>
                </div>
                <div style={{ textAlign: 'right' }}>
                  <small style={{ fontSize: 'var(--fs-caption)', color: 'var(--color-neutral-500)' }}>{t('ticket.totalPaid')}</small>
                  <div style={{ fontSize: 'var(--fs-h2)', fontWeight: 800, color: 'var(--color-primary-700)' }}>
                    {won(r.totalAmount)}
                  </div>
                </div>
              </div>
            </article>
          </div>

          <aside>
            <div className="kxp-refund">
              <h3>
                <IconInfo width={18} height={18} /> {t('ticket.refundTitle')}
              </h3>
              <div className="kxp-refund__table">
                <div className="kxp-refund__row kxp-refund__row--full">
                  <span>{t('ticket.refundD7')}</span>
                  <b>{t('ticket.refundD7Val')}</b>
                </div>
                <div className="kxp-refund__row kxp-refund__row--half">
                  <span>{t('ticket.refundD3')}</span>
                  <b>{t('ticket.refundD3Val')}</b>
                </div>
                <div className="kxp-refund__row kxp-refund__row--none">
                  <span>{t('ticket.refundDay')}</span>
                  <b>{t('ticket.refundDayVal')}</b>
                </div>
              </div>
              <p className="kxp-refund__note">{t('ticket.refundNote')}</p>
            </div>
          </aside>
        </div>
      )}
    </>
  );
}

export function PublicTicketPage() {
  const { t } = useTranslation();
  const { eventId } = useParams<{ eventId: string }>();
  const [view, setView] = useState<'purchase' | 'manage'>(eventId ? 'purchase' : 'manage');

  return (
    <PublicShell active="visit" cta={t('ticket.viewPurchase')} search={false}>
      <div className={view === 'purchase' ? 'kxp-ticket' : 'kxp-manage'}>
        <div className="kxp-daytabs" style={{ justifyContent: 'center', marginBottom: 24 }} role="tablist" aria-label={t('ticket.viewSwitchAria')}>
          <button
            type="button"
            role="tab"
            aria-selected={view === 'purchase'}
            className={`kxp-daytab${view === 'purchase' ? ' is-active' : ''}`}
            onClick={() => setView('purchase')}
          >
            {t('ticket.viewPurchase')}
          </button>
          <button
            type="button"
            role="tab"
            aria-selected={view === 'manage'}
            className={`kxp-daytab${view === 'manage' ? ' is-active' : ''}`}
            onClick={() => setView('manage')}
          >
            {t('ticket.viewManage')}
          </button>
        </div>

        {view === 'purchase' ? <PurchaseView eventId={eventId ?? DEFAULT_EVENT_ID} /> : <ManageView />}
      </div>
    </PublicShell>
  );
}
