import { useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { Trans, useTranslation } from 'react-i18next';
import { EmptyState, ErrorState, Skeleton } from '../../components/ui/States';
import { IconBolt, IconClock, IconGrid, IconOperations } from '../../components/ui/icons';
import { opsApiLocal, type OpsDataExt } from './opsApi';
import { ApiRequestError } from '../../api/client';
import { useResolvedEventId } from '../../hooks/useResolvedEventId';
import {
  HALL_CELLS,
  HVAC as SAMPLE_HVAC,
  LIGHTING_ZONES,
  PARKING_ZONES,
} from './sampleOps';
import './ops.css';

/*
 * SCR-14 홀 현장운영 대시보드 (M14). Stitch hall_operations 이식.
 * 실데이터 경로: GET /api/events/{eventId}/ops (백엔드 OpsDto 확장).
 *   ├ 혼잡(halls.estPeople/heat) = M10 체크인 실집계 → 홀 판매면적 비중 분배(추정).
 *   ├ 전력(halls.powerKw/powerTotalKw) = M4 유틸리티 신청 부하(requestedKw) 홀별 합.
 *   └ checkinSeries = 시간대별 체크인 추이(혼잡 프로파일).
 * ★ HVAC/조명/주차 = 센서·IoT 미연동(PLANNING M14) → null/빈배열 정직 반환 → "센서(M14) 연동 시 표시".
 * 폴백: NETWORK/NOT_FOUND/NOT_IMPLEMENTED 시에만 sampleOps 로 강등 + "오프라인 — 샘플" 표기.
 */
export function HallOperationsPage() {
  const { t } = useTranslation();
  const [mode, setMode] = useState<'live' | 'history'>('live');
  const eventId = useResolvedEventId();

  const q = useQuery({
    queryKey: ['ops', eventId],
    queryFn: () => opsApiLocal.get(eventId as string),
    enabled: !!eventId,
    retry: false,
  });

  const degraded = isDegradable(q.error);
  const data: OpsDataExt | null = q.data ?? (degraded ? FALLBACK : null);
  const hardError = q.isError && !degraded;

  const hvac = data?.hvac;
  const hasHvac = !!hvac && (hvac.tempC != null || hvac.humidityPercent != null || hvac.co2Ppm != null);
  const onSite = data?.onSiteCount ?? 0;
  const hasPeople = onSite > 0;
  const powerTotal = data?.powerTotalKw ?? null;
  const powerHalls = (data?.halls ?? []).filter((h) => h.powerKw != null && h.powerKw > 0);
  const maxPowerKw = powerHalls.reduce((m, h) => Math.max(m, h.powerKw ?? 0), 0);
  const series = data?.checkinSeries ?? [];
  const maxSeries = series.reduce((m, p) => Math.max(m, p.count), 0);

  return (
    <div className="kx-ops">
      <header className="kx-ops__head">
        <div>
          <h1 className="kx-ops__title">{t('ops.title')}</h1>
          <p className="kx-ops__subtitle">{t('ops.subtitle')}</p>
        </div>
        <div className="kx-seg" role="tablist" aria-label={t('ops.modeAria')}>
          <button role="tab" aria-selected={mode === 'live'} className={`kx-seg__btn ${mode === 'live' ? 'is-active' : ''}`} onClick={() => setMode('live')}>
            {t('ops.live')}
          </button>
          <button role="tab" aria-selected={mode === 'history'} className={`kx-seg__btn ${mode === 'history' ? 'is-active' : ''}`} onClick={() => setMode('history')}>
            {t('ops.history')}
          </button>
        </div>
      </header>

      {!eventId && (
        <EmptyState title={t('ops.noEventTitle')} description={t('ops.noEventDesc')} />
      )}

      {degraded && (
        <div className="kx-ops__degraded-bar">
          <span className="kx-ops__degraded-badge">{t('ops.offlineSample')}</span>
          {t('ops.degradedMsg')}
        </div>
      )}

      {q.isLoading && <OpsSkeleton />}

      {hardError && (
        <ErrorState message={t('ops.loadError')} onRetry={() => q.refetch()} />
      )}

      {data && (
        <div className="kx-ops__grid">
          {/* 히어로: 홀 혼잡(체크인 파생) */}
          <section className="kx-card kx-ops__heat" aria-label={t('ops.hallStatus')}>
            <div className="kx-card__head">
              <h2><IconGrid className="kx-title-ic" size={18} />{t('ops.hallStatus')}</h2>
            </div>
            <span className="kx-ops__sensor-badge">
              {hasPeople ? t('ops.checkinDerived') : t('ops.sensorNoneHalls')}
            </span>

            {data.halls.length === 0 ? (
              <EmptyState title={t('ops.noHallsTitle')} description={t('ops.noHallsDesc')} />
            ) : (
              <>
                <div className="kx-ops__halls">
                  {data.halls.map((c) => (
                    <div key={c.hallId} className={`kx-ops__hall is-${heatClass(c.heat)}`}>
                      <span className="kx-ops__hall-label">{c.label}</span>
                      {c.heat === 'busy' && <span className="kx-ops__hall-tag">{t('ops.busy')}</span>}
                      <span className="kx-ops__hall-people tnum">
                        {c.estPeople > 0 ? t('ops.people', { n: c.estPeople.toLocaleString() }) : '—'}
                      </span>
                    </div>
                  ))}
                </div>
                <div className="kx-ops__heat-foot">
                  <ul className="kx-ops__legend">
                    <li><span className="kx-dot is-smooth" /> {t('ops.smooth')}</li>
                    <li><span className="kx-dot is-moderate" /> {t('ops.moderate')}</li>
                    <li><span className="kx-dot is-busy" /> {t('ops.busy')}</li>
                  </ul>
                  <span className="kx-ops__total">
                    {hasPeople ? (
                      <Trans i18nKey="ops.onSiteCheckin" values={{ n: onSite.toLocaleString() }} components={[<strong className="tnum" key="s" />]} />
                    ) : (
                      <>{t('ops.noCheckinAgg')}</>
                    )}
                  </span>
                </div>
              </>
            )}
          </section>

          {/* 우측: 전력 부하(M4 실집계) + 시간대 추이 */}
          <aside className="kx-ops__aside">
            <section className="kx-card" aria-label={t('ops.powerLoad')}>
              <div className="kx-card__head">
                <h2><IconBolt className="kx-title-ic" size={18} />{t('ops.powerLoad')}</h2>
                {powerTotal != null && (
                  <span className="kx-ops__total"><Trans i18nKey="ops.totalKw" values={{ v: formatKw(powerTotal) }} components={[<strong className="tnum" key="s" />]} /></span>
                )}
              </div>
              <span className="kx-ops__sensor-badge">{t('ops.utilLoadAgg')}</span>
              {powerHalls.length === 0 ? (
                <EmptyState title={t('ops.noLoadTitle')} description={t('ops.noLoadDesc')} />
              ) : (
                <ul className="kx-barlist">
                  {powerHalls.map((h) => {
                    const kw = h.powerKw ?? 0;
                    const pct = maxPowerKw > 0 ? Math.round((kw / maxPowerKw) * 100) : 0;
                    return (
                      <li key={h.hallId} className="kx-barlist__item">
                        <div className="kx-barlist__top">
                          <span>{h.label}</span>
                          <span className="tnum">{t('ops.kw', { v: formatKw(kw) })}</span>
                        </div>
                        <div className="kx-barlist__track">
                          <span className="kx-barlist__fill" style={{ width: `${pct}%` }} />
                        </div>
                      </li>
                    );
                  })}
                </ul>
              )}
            </section>

            <section className="kx-card" aria-label={t('ops.hourlyCheckin')}>
              <div className="kx-card__head">
                <h2><IconClock className="kx-title-ic" size={18} />{t('ops.hourlyCheckin')}</h2>
              </div>
              <span className="kx-ops__sensor-badge">{t('ops.hourlyAgg')}</span>
              {series.length === 0 ? (
                <EmptyState title={t('ops.noSeriesTitle')} description={t('ops.noSeriesDesc')} />
              ) : (
                <ul className="kx-barlist kx-ops__series">
                  {series.map((p) => {
                    const pct = maxSeries > 0 ? Math.round((p.count / maxSeries) * 100) : 0;
                    return (
                      <li key={p.hour} className="kx-barlist__item">
                        <div className="kx-barlist__top">
                          <span className="tnum">{p.hour}</span>
                          <span className="tnum">{p.count.toLocaleString()}</span>
                        </div>
                        <div className="kx-barlist__track">
                          <span className="kx-barlist__fill" style={{ width: `${pct}%` }} />
                        </div>
                      </li>
                    );
                  })}
                </ul>
              )}
            </section>
          </aside>

          {/* 하단: 시설 센서(미연동) — 정직한 빈 상태 */}
          <section className="kx-card kx-ops__parking" aria-label={t('ops.facilitySensor')}>
            <div className="kx-card__head">
              <h2><IconOperations className="kx-title-ic" size={18} />{t('ops.facilitySensorTitle')}</h2>
            </div>
            {!hasHvac && data.lighting.length === 0 && data.parking.length === 0 ? (
              <EmptyState
                title={t('ops.sensorNoneTitle')}
                description={t('ops.sensorNoneDesc')}
              />
            ) : (
              <div className="kx-ops__sensor-grid">
                {hasHvac && (
                  <div className="kx-ops__hvac-meta">
                    <div>
                      <span className="kx-ops__meta-k">{t('ops.temp')}</span>
                      <strong className="tnum">{hvac!.tempC != null ? `${hvac!.tempC}°C` : '—'}</strong>
                    </div>
                    <div>
                      <span className="kx-ops__meta-k">{t('ops.humidity')}</span>
                      <strong className="tnum">{hvac!.humidityPercent != null ? `${hvac!.humidityPercent}%` : '—'}</strong>
                    </div>
                    <div>
                      <span className="kx-ops__meta-k">CO₂</span>
                      <strong className="tnum">{hvac!.co2Ppm != null ? `${hvac!.co2Ppm}ppm` : '—'}</strong>
                    </div>
                  </div>
                )}
                {data.lighting.map((z) => (
                  <div key={z.zone} className="kx-ops__meta-k">{z.zone}: {z.onPercent}%</div>
                ))}
                {data.parking.map((z) => (
                  <div key={z.zone} className="kx-ops__meta-k">
                    {t('ops.parkingSlots', { zone: z.zone, occ: z.occupancy.toLocaleString(), cap: z.capacity.toLocaleString() })}
                  </div>
                ))}
              </div>
            )}
          </section>
        </div>
      )}
    </div>
  );
}

function OpsSkeleton() {
  return (
    <div aria-hidden="true" style={{ display: 'grid', gap: 16 }}>
      <Skeleton height={220} radius={12} />
      <Skeleton height={160} radius={12} />
    </div>
  );
}

function heatClass(heat: string): string {
  if (heat === 'busy' || heat === 'moderate' || heat === 'smooth') return heat;
  return 'smooth';
}

function formatKw(kw: number): string {
  return kw % 1 === 0 ? kw.toLocaleString() : kw.toFixed(1);
}

function isDegradable(error: unknown): boolean {
  return (
    error instanceof ApiRequestError &&
    (error.code === 'NETWORK' || error.code === 'NOT_FOUND' || error.code === 'NOT_IMPLEMENTED')
  );
}

/**
 * 샘플 폴백(백엔드 확장 shape 매핑) — 정상 경로는 실 API. NETWORK/NOT_FOUND/NOT_IMPLEMENTED 시에만 사용.
 * 근거: 기존 sampleOps.ts(시연 데이터)를 OpsDataExt 로 강등 변환. 하드웨어 위젯은 미연동 상태를 보존.
 */
const FALLBACK: OpsDataExt = {
  halls: HALL_CELLS.map((c) => ({
    hallId: c.id,
    label: c.label,
    estPeople: c.estPeople,
    heat: c.level,
    powerKw: null,
  })),
  hvac: { tempC: SAMPLE_HVAC.avgTempC, humidityPercent: null, co2Ppm: null },
  lighting: LIGHTING_ZONES.map((z) => ({ zone: z.label, onPercent: z.pct })),
  parking: PARKING_ZONES.map((z) => ({ zone: z.label, occupancy: z.occupied, capacity: z.total })),
  onSiteCount: HALL_CELLS.reduce((s, c) => s + c.estPeople, 0),
  powerTotalKw: null,
  checkinSeries: [],
};
