/*
 * SCR-25 반입/반출 도크 슬롯 예약 [M8]. Stitch scr_25_dock_reservation 이식.
 * 진입: 통합 일정 / 사이드바 "반입·반출" (design.md §3 SCR-25).
 * 구성: ①상단 필터(반입/반출 토글·일자) ②좌 하역장 도크 × 시간대 슬롯 그리드
 *       (예약 셀·중량물 우선·빈 셀 선택) ③우 예약 폼(차량·중량·품목·지게차·통행증 QR) + AI 대기열 예측.
 * ★ 실 API 배선(useQuery/useMutation) — GET /docks · POST /dock-reservations(409 충돌) · GET /dock-forecast.
 *   예측 카드는 실 집계이며, 데이터 부재 시 표준 패턴 폴백(폴백 배지 유지).
 */
import { useEffect, useMemo, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { AiLabel } from '../../components/ui/Badge';
import { EmptyState, ErrorState, Skeleton } from '../../components/ui/States';
import { IconSpark, IconTruck } from '../../components/ui/icons';
import { ApiRequestError } from '../../api/client';
import { useResolvedEventId } from '../../hooks/useResolvedEventId';
import { logisticsApi, type Dock, type GridReservation } from './logisticsApi';
import { EquipmentTab, InboundTab, RentalTab } from './LogisticsExtTabs';
import './movein.css';

type LogisticsTab = 'dock' | 'equipment' | 'rental' | 'inbound';

/**
 * SCR-25 물류 허브(/logistics) — M8. 탭 4종: 도크 예약(기존) · 장비 신청(F041) · 렌탈 주문(F042) · 선입고(F043).
 * 도크 예약 탭은 기존 스케줄 그리드를 그대로 유지, 확장 탭은 LogisticsExtTabs 로 위임.
 */
export function DockReservationPage() {
  const { t } = useTranslation();
  const eventId = useResolvedEventId();
  const [tab, setTab] = useState<LogisticsTab>('dock');
  const tabs: LogisticsTab[] = ['dock', 'equipment', 'rental', 'inbound'];

  return (
    <div className="kx-page">
      <header className="kx-dock__head">
        <div>
          <h1 className="kx-dock__title">{t('logistics.title')}</h1>
          <p className="kx-dock__subtitle">{t('logistics.subtitle')}</p>
        </div>
      </header>

      <div className="kx-seg kx-logi__tabs" role="tablist" aria-label={t('logistics.tabsAria')}>
        {tabs.map((key) => (
          <button
            key={key}
            role="tab"
            aria-selected={tab === key}
            className={`kx-seg__btn ${tab === key ? 'is-active' : ''}`}
            onClick={() => setTab(key)}
          >
            {t(`logistics.tabs.${key}`)}
          </button>
        ))}
      </div>

      {tab === 'dock' && <DockScheduleTab />}
      {tab === 'equipment' && <EquipmentTab eventId={eventId} />}
      {tab === 'rental' && <RentalTab eventId={eventId} />}
      {tab === 'inbound' && <InboundTab eventId={eventId} />}
    </div>
  );
}

const WEIGHTS = ['1t', '2.5t', '5t', '11t 이상'];

interface DockForm {
  vehicleNo: string;
  weight: string;
  item: string;
  forklift: boolean;
}
const EMPTY_FORM: DockForm = { vehicleNo: '', weight: '5t', item: '전시 부스 자재', forklift: false };

/** 시간대 라벨 배열(gridStartHour 부터 hours 개). */
function hourLabels(gridStartHour: number, hours: number): string[] {
  return Array.from({ length: hours }, (_, i) => `${String(gridStartHour + i).padStart(2, '0')}:00`);
}

function DockScheduleTab() {
  const eventId = useResolvedEventId();
  const queryClient = useQueryClient();
  const [direction, setDirection] = useState<'in' | 'out'>('in');
  const [date, setDate] = useState<string>(''); // '' → 서버 기본 일자
  const [form, setForm] = useState<DockForm>(EMPTY_FORM);
  const [selected, setSelected] = useState<{ dock: number; hour: number } | null>(null);
  const [toast, setToast] = useState<string | null>(null);

  useEffect(() => {
    if (!toast) return;
    const t = setTimeout(() => setToast(null), 2600);
    return () => clearTimeout(t);
  }, [toast]);

  const boardQ = useQuery({
    queryKey: ['dock-board', eventId, direction, date],
    queryFn: () => logisticsApi.board(eventId as string, direction, date || undefined),
    enabled: !!eventId,
    retry: false,
  });

  const board = boardQ.data;
  const boardDate = board?.date ?? '';
  const gridStartHour = board?.gridStartHour ?? 8;
  const hours = board?.hours ?? 12;
  const hourList = useMemo(() => hourLabels(gridStartHour, hours), [gridStartHour, hours]);
  const docks: Dock[] = board?.docks ?? [];

  const forecastQ = useQuery({
    queryKey: ['dock-forecast', eventId, boardDate],
    queryFn: () => logisticsApi.forecast(eventId as string, boardDate),
    enabled: !!eventId && !!boardDate,
    retry: false,
  });

  const reserve = useMutation({
    mutationFn: () => {
      if (!selected) throw new ApiRequestError('VALIDATION', '먼저 슬롯을 선택하세요.', 400);
      const span = Math.min(2, hours - selected.hour);
      return logisticsApi.reserve(eventId as string, {
        direction,
        date: boardDate,
        dockIndex: selected.dock,
        startHour: gridStartHour + selected.hour,
        span: Math.max(1, span),
        vehicleNo: form.vehicleNo || undefined,
        weight: form.weight,
        item: form.item || undefined,
        forklift: form.forklift,
      });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['dock-board', eventId, direction, date] });
      queryClient.invalidateQueries({ queryKey: ['dock-forecast', eventId, boardDate] });
      setSelected(null);
      setToast('슬롯 예약 완료 — 통행증(QR)을 발급하세요.');
    },
    onError: (e) => {
      if (e instanceof ApiRequestError && e.code === 'CONFLICT') {
        setToast('이미 예약된 슬롯과 겹칩니다. 다른 시간대를 선택하세요.');
        return;
      }
      const msg = e instanceof ApiRequestError ? e.message : '예약에 실패했습니다.';
      setToast(msg);
    },
  });

  // 그리드 예약을 도크 인덱스 기준으로 변환(DockRowCells 계약).
  const reservations = board?.reservations ?? [];

  function pickCell(dock: number, hour: number) {
    setSelected({ dock, hour });
    setToast(`${docks[dock]?.label ?? `도크 ${dock + 1}`} · ${hourList[hour]} 슬롯 선택`);
  }

  const set = <K extends keyof DockForm>(k: K, v: DockForm[K]) => setForm((f) => ({ ...f, [k]: v }));

  const status: 'loading' | 'error' | 'success' = boardQ.isPending
    ? 'loading'
    : boardQ.isError
      ? 'error'
      : 'success';

  return (
    <>
      {/* 필터 바 */}
      <div className="kx-dock__filters">
        <label className="kx-dock__field">
          <span className="kx-dock__label">일자</span>
          <input
            type="date"
            className="kx-select"
            aria-label="예약 일자"
            value={date || boardDate}
            onChange={(e) => {
              setDate(e.target.value);
              setSelected(null);
            }}
          />
        </label>
        <div className="kx-dock__filters-spacer" />
        <div className="kx-seg" role="tablist" aria-label="반입/반출 전환">
          <button
            role="tab"
            aria-selected={direction === 'in'}
            className={`kx-seg__btn ${direction === 'in' ? 'is-active' : ''}`}
            onClick={() => {
              setDirection('in');
              setSelected(null);
            }}
          >
            반입
          </button>
          <button
            role="tab"
            aria-selected={direction === 'out'}
            className={`kx-seg__btn ${direction === 'out' ? 'is-active' : ''}`}
            onClick={() => {
              setDirection('out');
              setSelected(null);
            }}
          >
            반출
          </button>
        </div>
      </div>

      {status === 'loading' && (
        <div className="kx-dock__split" aria-busy="true">
          <section className="kx-card">
            <Skeleton height={360} />
          </section>
          <section className="kx-card">
            <Skeleton height={240} />
          </section>
        </div>
      )}

      {status === 'error' && (
        <ErrorState message="도크 예약 현황을 불러오지 못했습니다." onRetry={() => boardQ.refetch()} />
      )}

      {status === 'success' && (
        <div className="kx-dock__split">
          {/* 좌: 스케줄 그리드 */}
          <section
            className="kx-card kx-dock__grid"
            aria-label={`${direction === 'in' ? '반입' : '반출'} 도크 슬롯 그리드`}
          >
            {docks.length === 0 ? (
              <EmptyState title="예약 가능한 슬롯이 없습니다" description="행사 배정 홀에 도크가 없습니다." />
            ) : (
              <>
                <div className="kx-dock__grid-scroll">
                  <div className="kx-dock__ghead">
                    <div className="kx-dock__ghead-dock">DOCK</div>
                    <div className="kx-dock__times">
                      {hourList.map((h) => (
                        <div key={h} className="kx-dock__time tnum">
                          {h}
                        </div>
                      ))}
                    </div>
                  </div>
                  {docks.map((dock, di) => (
                    <div key={dock.id} className="kx-dock__row">
                      <div className="kx-dock__row-label">{dock.label}</div>
                      <DockRowCells
                        dockIndex={di}
                        hours={hours}
                        dockLabel={dock.label}
                        hourList={hourList}
                        reservations={reservations}
                        selected={selected}
                        onPick={pickCell}
                      />
                    </div>
                  ))}
                </div>
                <div className="kx-dock__legend">
                  <span>
                    <span className="kx-dock__swatch kx-dock__swatch--booked" /> 예약됨
                  </span>
                  <span>
                    <span className="kx-dock__swatch kx-dock__swatch--priority" /> 중량물 우선(5t↑)
                  </span>
                  <span>
                    <span className="kx-dock__swatch kx-dock__swatch--open" /> 예약 가능
                  </span>
                </div>
              </>
            )}
          </section>

          {/* 우: 예약 폼 + AI */}
          <aside className="kx-dock__aside">
            <section className="kx-card">
              <span className="kx-dock__panel-title"><IconTruck className="kx-title-ic" size={18} />슬롯 예약</span>
              <div className="kx-dock__form">
                {selected && (
                  <p className="kx-dock__slot-note">
                    선택: {docks[selected.dock]?.label} · {hourList[selected.hour]} ·{' '}
                    {direction === 'in' ? '반입' : '반출'}
                  </p>
                )}
                <label className="kx-dock__field">
                  <span className="kx-dock__label">차량 번호</span>
                  <input
                    className="kx-dock__input"
                    placeholder="예: 12가 3456"
                    value={form.vehicleNo}
                    onChange={(e) => set('vehicleNo', e.target.value)}
                  />
                </label>
                <label className="kx-dock__field">
                  <span className="kx-dock__label">차량 중량</span>
                  <select
                    className="kx-dock__select"
                    value={form.weight}
                    onChange={(e) => set('weight', e.target.value)}
                  >
                    {WEIGHTS.map((w) => (
                      <option key={w} value={w}>
                        {w}
                      </option>
                    ))}
                  </select>
                </label>
                <label className="kx-dock__field">
                  <span className="kx-dock__label">{direction === 'in' ? '반입' : '반출'} 품목</span>
                  <input
                    className="kx-dock__input"
                    value={form.item}
                    onChange={(e) => set('item', e.target.value)}
                  />
                </label>
                <label className="kx-dock__check">
                  <input
                    type="checkbox"
                    checked={form.forklift}
                    onChange={(e) => set('forklift', e.target.checked)}
                  />
                  지게차 신청 (유료)
                </label>

                <button
                  type="button"
                  className="kx-dock__qr"
                  disabled={reserve.isPending}
                  onClick={() => {
                    if (!selected) {
                      setToast('먼저 슬롯을 선택하세요.');
                      return;
                    }
                    reserve.mutate();
                  }}
                >
                  <span className="kx-dock__qr-main">
                    <span className="kx-dock__qr-title">
                      {reserve.isPending ? '예약 중…' : '예약 · 통행증 발급 (QR)'}
                    </span>
                    <span className="kx-dock__qr-sub">Reserve &amp; Generate Logistics Pass</span>
                  </span>
                  <span className="kx-dock__qr-glyph" aria-hidden="true">
                    <QrGlyph />
                  </span>
                </button>
              </div>
            </section>

            <section className="kx-dock__ai" aria-label="대기열 예측">
              <div className="kx-dock__ai-head">
                <span className="kx-dock__ai-title">
                  <IconSpark size={18} /> {direction === 'out' ? '철거일' : '반입일'} 대기열 예측
                </span>
                <AiLabel>{forecastQ.data?.fallback ? 'AI 예측 · 폴백' : 'AI 예측'}</AiLabel>
              </div>
              {forecastQ.isPending ? (
                <Skeleton height={120} />
              ) : (
                <>
                  <div
                    className="kx-dock__chart"
                    role="img"
                    aria-label={`시간대별 차량 밀집도 예측 — ${forecastQ.data?.peakLabel ?? ''}경 피크`}
                  >
                    {(forecastQ.data?.hourly ?? []).map((h, i) => (
                      <span
                        key={i}
                        className="kx-dock__bar"
                        style={{ height: `${h}%`, opacity: 0.35 + (h / 100) * 0.65 }}
                      />
                    ))}
                  </div>
                  <div className="kx-dock__chart-axis tnum">
                    <span>{hourList[0]}</span>
                    <span>{hourList[Math.floor(hours / 3)]}</span>
                    <span>{hourList[Math.floor((hours * 2) / 3)]}</span>
                    <span>{hourList[hours - 1]}</span>
                  </div>
                  <div className="kx-dock__ai-callout">
                    {forecastQ.data?.fallback
                      ? '예약 데이터가 아직 없어 표준 패턴을 표시합니다. '
                      : ''}
                    <strong>{forecastQ.data?.peakLabel ?? '오후'}</strong>경 차량 밀집도가 가장 높을
                    것으로 예상됩니다. 예약 분산을 권장합니다.
                  </div>
                </>
              )}
            </section>
          </aside>
        </div>
      )}

      {toast && (
        <div className="kx-dock__toast" role="status">
          {toast}
        </div>
      )}
    </>
  );
}

/** 단일 도크 행의 시간대 셀 — 예약 블록은 span, 빈 칸은 선택 가능한 셀. */
function DockRowCells({
  dockIndex,
  hours,
  dockLabel,
  hourList,
  reservations,
  selected,
  onPick,
}: {
  dockIndex: number;
  hours: number;
  dockLabel: string;
  hourList: string[];
  reservations: GridReservation[];
  selected: { dock: number; hour: number } | null;
  onPick: (dock: number, hour: number) => void;
}) {
  const cells = useMemo(() => {
    const rowRes = reservations
      .filter((r) => r.dockIndex === dockIndex)
      .sort((a, b) => a.start - b.start);
    const out: JSX.Element[] = [];
    let col = 0;
    while (col < hours) {
      const res = rowRes.find((r) => r.start === col);
      if (res) {
        out.push(
          <div
            key={`r${col}`}
            className={`kx-dock__block kx-dock__block--${res.tone}`}
            style={{ gridColumn: `span ${res.span}` }}
            title={res.label}
          >
            {res.tone === 'priority' && <IconSpark size={12} />}
            <span className="kx-dock__block-text">{res.label}</span>
          </div>,
        );
        col += res.span;
      } else {
        const isSel = selected?.dock === dockIndex && selected?.hour === col;
        const hour = col;
        out.push(
          <div
            key={`c${col}`}
            className={`kx-dock__cell ${isSel ? 'is-selected' : ''}`}
            role="button"
            tabIndex={0}
            aria-label={`${dockLabel} ${hourList[hour]} 예약 가능`}
            onClick={() => onPick(dockIndex, hour)}
            onKeyDown={(e) => {
              if (e.key === 'Enter' || e.key === ' ') {
                e.preventDefault();
                onPick(dockIndex, hour);
              }
            }}
          />,
        );
        col += 1;
      }
    }
    return out;
  }, [dockIndex, hours, dockLabel, hourList, reservations, selected, onPick]);

  return <div className="kx-dock__cells">{cells}</div>;
}

/** 통행증 미리보기용 QR 형태 SVG(인라인·이모지 금지). */
function QrGlyph() {
  return (
    <svg width={40} height={40} viewBox="0 0 40 40" fill="none" aria-hidden="true">
      <rect x="2" y="2" width="12" height="12" rx="1" stroke="#101828" strokeWidth="2.5" />
      <rect x="26" y="2" width="12" height="12" rx="1" stroke="#101828" strokeWidth="2.5" />
      <rect x="2" y="26" width="12" height="12" rx="1" stroke="#101828" strokeWidth="2.5" />
      <rect x="6" y="6" width="4" height="4" fill="#101828" />
      <rect x="30" y="6" width="4" height="4" fill="#101828" />
      <rect x="6" y="30" width="4" height="4" fill="#101828" />
      <rect x="20" y="20" width="4" height="4" fill="#101828" />
      <rect x="28" y="20" width="4" height="4" fill="#101828" />
      <rect x="34" y="26" width="4" height="4" fill="#101828" />
      <rect x="20" y="30" width="4" height="4" fill="#101828" />
      <rect x="28" y="34" width="4" height="4" fill="#101828" />
      <rect x="20" y="6" width="4" height="10" fill="#101828" />
    </svg>
  );
}
