import { useState } from 'react';
import { Link } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import {
  Bar,
  BarChart,
  CartesianGrid,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from 'recharts';
import { CHART } from '../chartColors';
import { EmptyState, ErrorState, Skeleton } from '../../components/ui/States';
import { IconClock, IconOperations } from '../../components/ui/icons';
import { adminApi } from '../../api/endpoints';
import { ApiRequestError } from '../../api/client';
import { StatusPill } from '../work/workShared';
import type { AdminDashboardData, AdminStats } from '../../api/types';
import { ADMIN_KPIS, LIVE_EVENTS, TENANTS, VISITOR_TREND } from './sampleAdmin';
import './admin.css';

/*
 * SCR-14/16 관리자 백오피스 대시보드 (M18 랜딩). Stitch admin_dashboard 이식.
 * KPI: GET /api/admin/stats (실 집계 — 사용자·행사·테넌트·등록업체·오늘 체크인, 실 테이블 존재분만).
 * 라이브/추이: GET /api/admin/dashboard?tenant (진행 행사 점유). 관람객 시간대 추이는 센서 부재 → 빈 상태 유지.
 * 실시간 방문객·주차·라이브 IoT 지표는 M10/M14 이후 — 가짜 수치 생성 금지(게이트 유지).
 * 폴백: NETWORK/NOT_FOUND/NOT_IMPLEMENTED 시에만 샘플로 강등(degraded 배너 표기).
 */
export function AdminDashboardPage() {
  const { t } = useTranslation();
  const [tenant, setTenant] = useState<string | undefined>(undefined);

  const q = useQuery({
    queryKey: ['admin-dashboard', tenant],
    queryFn: () => adminApi.dashboard(tenant),
    retry: false,
  });

  const sq = useQuery({
    queryKey: ['admin-stats', tenant],
    queryFn: () => adminApi.stats(tenant),
    retry: false,
  });

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

  const statsDegraded = isDegradable(sq.error);
  const stats: AdminStats | null = sq.data ?? (statsDegraded ? STATS_FALLBACK : null);
  const statsHardError = sq.isError && !statsDegraded;

  const tenants = data?.tenants?.length ? data.tenants : TENANTS;
  const activeTenant = tenant ?? tenants[0];

  return (
    <div className="kx-admin">
      <header className="kx-admin__head">
        <div>
          <h1 className="kx-admin__title">{t('admin.overviewTitle')}</h1>
          <p className="kx-admin__subtitle">{t('admin.overviewSub')}</p>
        </div>
        <div className="kx-admin__head-actions">
          <Link to="/admin/login-slides" className="kx-btn kx-btn--secondary">
            {t('admin.loginSlides')}
          </Link>
          <select
            className="kx-select"
            aria-label={t('admin.tenantSwitch')}
            value={activeTenant}
            onChange={(e) => setTenant(e.target.value)}
          >
            {tenants.map((tn) => (
              <option key={tn} value={tn}>{tn}</option>
            ))}
          </select>
          <span className="kx-admin__status" role="status">
            <span className="kx-admin__status-dot" aria-hidden="true" /> {t('admin.systemNormal')}
          </span>
        </div>
      </header>

      <nav className="kx-admin__modules" aria-label={t('admin.moduleShortcuts')}>
        {ADMIN_MODULES.map(([labelKey, to]) => (
          <Link key={to} to={to} className="kx-btn kx-btn--secondary">{t(labelKey)}</Link>
        ))}
      </nav>

      {(degraded || statsDegraded) && (
        <div className="kx-admin__degraded-bar">
          <span className="kx-bi__degraded">{t('admin.offlineSample')}</span>
          {t('admin.degradedMsg')}
        </div>
      )}

      {/* KPI — 실 집계 지표(GET /api/admin/stats). 실 테이블 존재분만. */}
      <section className="kx-admin__kpis" aria-label={t('admin.kpisAria')}>
        {sq.isLoading ? (
          <>
            <Skeleton height={92} radius={12} />
            <Skeleton height={92} radius={12} />
            <Skeleton height={92} radius={12} />
          </>
        ) : statsHardError ? (
          <ErrorState
            message={t('admin.statsLoadError', { defaultValue: '집계 지표를 불러오지 못했습니다.' })}
            onRetry={() => sq.refetch()}
          />
        ) : stats ? (
          buildKpiCards(stats, t).map((k, i) => (
            <div key={`${k.label}-${i}`} className="kx-kpi kx-kpi--normal">
              <span className="kx-kpi__label">{k.label}</span>
              <strong className="kx-kpi__value tnum">{k.value}</strong>
              {k.sub && <span className="kx-kpi__sub">{k.sub}</span>}
            </div>
          ))
        ) : (
          <EmptyState title={t('admin.kpiEmpty')} />
        )}
      </section>

      {q.isLoading && <AdminSkeleton />}

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

      {data && (
        <>
          <div className="kx-admin__split">
            <section className="kx-card kx-admin__chart-card" aria-label={t('admin.visitorTrend')}>
              <div className="kx-card__head">
                <h2><IconClock className="kx-title-ic" size={18} />{t('admin.hourlyVisitors')}</h2>
              </div>
              <div className="kx-admin__chart">
                {data.visitorTrend.length === 0 ? (
                  <EmptyState
                    title={t('admin.visitorTrendEmptyTitle')}
                    description={t('admin.visitorTrendEmptyDesc')}
                  />
                ) : (
                  <ResponsiveContainer width="100%" height={300}>
                    <BarChart data={data.visitorTrend} margin={{ top: 8, right: 8, bottom: 0, left: -8 }}>
                      <CartesianGrid stroke={CHART.neutral200} strokeDasharray="3 3" vertical={false} />
                      <XAxis dataKey="hour" tick={{ fontSize: 12, fill: CHART.slate }} tickLine={false} axisLine={{ stroke: CHART.neutral200 }} />
                      <YAxis tick={{ fontSize: 12, fill: CHART.slate }} tickLine={false} axisLine={false} width={44} />
                      <Tooltip cursor={{ fill: CHART.primary050 }} contentStyle={TOOLTIP_STYLE} />
                      <Bar dataKey="count" name={t('admin.visitors')} fill={CHART.primary600} radius={[4, 4, 0, 0]} maxBarSize={34} />
                    </BarChart>
                  </ResponsiveContainer>
                )}
              </div>
            </section>

            <aside className="kx-admin__live" aria-label={t('admin.liveEvents')}>
              <div className="kx-card__head">
                <h2><IconOperations className="kx-title-ic" size={18} />{t('admin.liveEvents')}</h2>
              </div>
              {data.liveEvents.length === 0 ? (
                <EmptyState title={t('admin.noLiveEvents')} />
              ) : (
                <div className="kx-admin__live-list">
                  {data.liveEvents.map((e) => (
                    <article key={e.eventId} className="kx-livecard">
                      <div className="kx-livecard__body">
                        <div className="kx-livecard__top">
                          <span className="kx-livecard__dot is-live" aria-hidden="true" />
                          <StatusPill value={e.status} />
                        </div>
                        <h3 className="kx-livecard__title">{e.name}</h3>
                        <p className="kx-livecard__meta">{e.hall ?? t('admin.hallTbd')}</p>
                        <div className="kx-livecard__occ">
                          <div className="kx-barlist__track">
                            <span className="kx-barlist__fill is-warning" style={{ width: `${clamp(e.occupancy)}%` }} />
                          </div>
                          <span className="kx-livecard__occ-val tnum">{t('admin.occupancy', { n: clamp(e.occupancy) })}</span>
                        </div>
                      </div>
                    </article>
                  ))}
                </div>
              )}
            </aside>
          </div>
        </>
      )}
    </div>
  );
}

const TOOLTIP_STYLE = {
  fontSize: 12,
  borderRadius: 8,
  border: '1px solid #E4E7EC',
  boxShadow: '0 4px 12px rgba(16,24,40,0.1)',
} as const;

function AdminSkeleton() {
  return (
    <div aria-hidden="true" style={{ display: 'grid', gap: 16 }}>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12 }}>
        {[0, 1, 2].map((i) => (
          <Skeleton key={i} height={92} radius={12} />
        ))}
      </div>
      <Skeleton height={300} radius={12} />
    </div>
  );
}

function clamp(n: number): number {
  return Math.max(0, Math.min(100, Math.round(n)));
}

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 시에만 사용.
 * 근거: 기존 sampleAdmin.ts(집계·센서 미구축 시연 데이터)를 AdminDashboardData 로 강등 변환.
 */
const FALLBACK: AdminDashboardData = {
  kpis: ADMIN_KPIS.map((k) => ({ label: k.label, value: k.value, sub: k.delta ?? null })),
  visitorTrend: VISITOR_TREND.map((p) => ({ hour: p.hour, count: p.today })),
  liveEvents: LIVE_EVENTS.filter((e) => e.live).map((e) => ({
    eventId: e.id,
    name: e.title,
    hall: e.hallTime,
    occupancy: e.progress ?? 60,
    status: 'ongoing',
  })),
  tenants: TENANTS,
};

/** 집계 지표 강등 폴백 — NETWORK/NOT_FOUND 시에만(정상 경로는 실 API). degraded 배너와 함께 노출. */
const STATS_FALLBACK: AdminStats = {
  totalUsers: 0,
  activeUsers: 0,
  totalEvents: 0,
  ongoingEvents: 0,
  upcomingEvents: 0,
  tenantCount: 0,
  companyCount: 0,
  todayCheckins: 0,
};

type Translate = (key: string, opts?: Record<string, unknown>) => string;

/**
 * 실 집계 지표(AdminStats) → KPI 카드. 라벨은 shared 로케일 미수정(t defaultValue 인라인).
 * 실시간 방문객·주차·라이브 IoT 지표는 미포함(가짜 수치 금지) — 별도 카드/게이트 유지.
 */
function buildKpiCards(s: AdminStats, t: Translate): { label: string; value: string; sub: string | null }[] {
  const n = (v: number) => v.toLocaleString();
  return [
    {
      label: t('admin.kpiOngoing', { defaultValue: '진행 행사' }),
      value: n(s.ongoingEvents),
      sub: t('admin.kpiOngoingSub', { defaultValue: '전체 {{n}}건', n: n(s.totalEvents) }),
    },
    {
      label: t('admin.kpiUpcoming', { defaultValue: '예정 행사' }),
      value: n(s.upcomingEvents),
      sub: null,
    },
    {
      label: t('admin.kpiActiveUsers', { defaultValue: '활성 사용자' }),
      value: n(s.activeUsers),
      sub: t('admin.kpiActiveUsersSub', { defaultValue: '총 {{n}}명', n: n(s.totalUsers) }),
    },
    {
      label: t('admin.kpiCompanies', { defaultValue: '등록업체' }),
      value: n(s.companyCount),
      sub: null,
    },
    {
      label: t('admin.kpiTodayCheckins', { defaultValue: '오늘 체크인' }),
      value: n(s.todayCheckins),
      sub: null,
    },
    {
      label: t('admin.kpiTenants', { defaultValue: '테넌트' }),
      value: n(s.tenantCount),
      sub: null,
    },
  ];
}

/** 관리 모듈 바로가기(M18) — 라우트는 App.tsx AdminGuard 배선과 동일. 첫 항목은 i18n 키. */
const ADMIN_MODULES: [string, string][] = [
  ['admin.modUsers', '/admin/users'],
  ['admin.modRoles', '/admin/roles'],
  ['admin.modCodes', '/admin/codes'],
  ['admin.modMenus', '/admin/menus'],
  ['admin.modMessages', '/admin/messages'],
  ['admin.modAudit', '/admin/audit'],
  ['admin.modSettings', '/admin/settings'],
  ['admin.modRulesets', '/admin/masterdata/rulesets'],
  ['admin.modTenants', '/admin/tenants'],
];
