import { useState, useCallback, useEffect } from 'react';
import {
  batchApi,
  type SyncStatusResponse,
  type SyncTableStatus,
  type SyncDataPreviewResponse,
} from '../api/batchApi';
import { useToastContext } from '../contexts/ToastContext';
import LoadingSpinner from '../components/LoadingSpinner';
import EmptyState from '../components/EmptyState';
import ConfirmModal from '../components/ConfirmModal';
import GuideModal, { HelpButton } from '../components/GuideModal';

const DOMAIN_ICONS: Record<string, string> = {
  ship: '🚢',
  company: '🏢',
  event: '⚠️',
  facility: '🏭',
  psc: '🔍',
  movements: '📍',
  code: '🏷️',
  'risk-compliance': '🛡️',
};

const GUIDE_ITEMS = [
  {
    title: '도메인 탭',
    content: 'Ship, PSC 등 도메인별로 테이블을 그룹핑하여 조회합니다.\nP 고착 테이블이 있는 도메인에는 경고 뱃지가 표시됩니다.',
  },
  {
    title: '테이블 아코디언',
    content: '각 테이블을 펼치면 대기(N)/진행(P)/완료(S) 건수와 상세 데이터를 확인할 수 있습니다.\n⚠️ 표시는 P 상태에 고착된 레코드가 있음을 의미합니다.',
  },
  {
    title: '동기화 데이터 / P 상태 레코드',
    content: '동기화 데이터 탭: 타겟 스키마(std_snp_svc)의 최근 동기화 데이터를 보여줍니다.\nP 상태 레코드 탭: Writer 실패로 P 상태에 멈춘 레코드를 확인하고 리셋할 수 있습니다.',
  },
];

export default function SyncStatus() {
  const { showToast } = useToastContext();
  const [data, setData] = useState<SyncStatusResponse | null>(null);
  const [loading, setLoading] = useState(true);
  const [guideOpen, setGuideOpen] = useState(false);

  // Tab & accordion state
  const [activeDomain, setActiveDomain] = useState<string>('ship');
  const [expandedTable, setExpandedTable] = useState<string>('ship-001');
  const [detailTabs, setDetailTabs] = useState<Record<string, 'preview' | 'stuck'>>({});

  // Reset confirm
  const [resetTableKey, setResetTableKey] = useState('');
  const [resetConfirmOpen, setResetConfirmOpen] = useState(false);
  const [resetting, setResetting] = useState(false);

  const [refreshing, setRefreshing] = useState(false);

  const loadData = useCallback(async (refresh = false) => {
    try {
      const result = await batchApi.getSyncStatus(refresh);
      setData(result);
    } catch {
      showToast('동기화 현황 조회 실패', 'error');
    } finally {
      setLoading(false);
      setRefreshing(false);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  useEffect(() => { loadData(); }, [loadData]);

  const handleRefresh = () => {
    setRefreshing(true);
    loadData(true);
  };

  const toggleAccordion = (tableKey: string) => {
    setExpandedTable((prev) => (prev === tableKey ? '' : tableKey));
  };

  const getDetailTab = (tableKey: string) => detailTabs[tableKey] || 'preview';
  const setDetailTab = (tableKey: string, tab: 'preview' | 'stuck') => {
    setDetailTabs((prev) => ({ ...prev, [tableKey]: tab }));
  };

  const handleReset = async () => {
    setResetting(true);
    try {
      const result = await batchApi.resetStuckRecords(resetTableKey);
      const allTables = data?.domains.flatMap((d) => d.tables) ?? [];
      const table = allTables.find((t) => t.tableKey === resetTableKey);
      showToast(`${table?.sourceTable ?? resetTableKey}: ${result.resetCount}건 리셋 완료`, 'success');
      setResetConfirmOpen(false);
      loadData();
    } catch {
      showToast('리셋 실패', 'error');
    } finally {
      setResetting(false);
    }
  };

  const activeDomainGroup = data?.domains.find((d) => d.domain === activeDomain);
  const resetTable = data?.domains.flatMap((d) => d.tables).find((t) => t.tableKey === resetTableKey);

  if (loading) return <LoadingSpinner />;
  if (!data) return <EmptyState message="데이터를 불러올 수 없습니다" />;

  return (
    <div>
      {/* Header */}
      <div className="flex items-center justify-between mb-6">
        <h1 className="text-2xl font-bold text-wing-text">동기화 현황</h1>
        <div className="flex items-center gap-2">
          <button
            onClick={handleRefresh}
            disabled={refreshing}
            className={`inline-flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium rounded-lg border border-wing-border transition-colors
              ${refreshing
                ? 'text-wing-muted cursor-not-allowed'
                : 'text-wing-text hover:bg-wing-hover'
              }`}
          >
            <span className={refreshing ? 'animate-spin' : ''}>↻</span>
            {refreshing ? '조회 중...' : '새로고침'}
          </button>
          <HelpButton onClick={() => setGuideOpen(true)} />
        </div>
      </div>

      {/* ── Domain Tabs ── */}
      <div className="flex gap-0 overflow-x-auto border-b border-wing-border mb-4">
        {data.domains.map((d) => {
          const stuckCount = d.tables.filter((t) => t.stuck).length;
          return (
            <button
              key={d.domain}
              onClick={() => setActiveDomain(d.domain)}
              className={`px-4 py-2.5 text-sm font-medium whitespace-nowrap border-b-2 transition-colors
                ${activeDomain === d.domain
                  ? 'border-wing-accent text-wing-accent'
                  : 'border-transparent text-wing-muted hover:text-wing-text hover:border-wing-border'
                }`}
            >
              <span className="mr-1">{DOMAIN_ICONS[d.domain] || ''}</span>
              {d.domainLabel}
              <span className="ml-1 text-xs opacity-60">({d.tables.length})</span>
              {stuckCount > 0 && (
                <span className="ml-1.5 inline-flex items-center justify-center w-5 h-5 text-[10px] font-bold text-white bg-red-500 rounded-full">
                  {stuckCount}
                </span>
              )}
            </button>
          );
        })}
      </div>

      {/* ── Table Accordions ── */}
      {activeDomainGroup && (
        <div className="space-y-2">
          {activeDomainGroup.tables.map((table) => (
            <TableAccordion
              key={table.tableKey}
              table={table}
              expanded={expandedTable === table.tableKey}
              detailTab={getDetailTab(table.tableKey)}
              onToggle={() => toggleAccordion(table.tableKey)}
              onDetailTabChange={(tab) => setDetailTab(table.tableKey, tab)}
              onReset={() => { setResetTableKey(table.tableKey); setResetConfirmOpen(true); }}
            />
          ))}
        </div>
      )}

      {/* Reset Confirm Modal */}
      <ConfirmModal
        open={resetConfirmOpen}
        title="P→N 리셋 확인"
        message={`${resetTable?.sourceTable ?? ''}의 P 상태 레코드를 모두 N(대기)으로 리셋하시겠습니까?\n리셋된 레코드는 다음 동기화 실행 시 재처리됩니다.`}
        confirmLabel={resetting ? '리셋 중...' : '리셋'}
        onConfirm={handleReset}
        onCancel={() => setResetConfirmOpen(false)}
      />

      <GuideModal
        open={guideOpen}
        pageTitle="동기화 현황"
        sections={GUIDE_ITEMS}
        onClose={() => setGuideOpen(false)}
      />
    </div>
  );
}

// ── Sub Components ────────────────────────────────────────────

interface TableAccordionProps {
  table: SyncTableStatus;
  expanded: boolean;
  detailTab: 'preview' | 'stuck';
  onToggle: () => void;
  onDetailTabChange: (tab: 'preview' | 'stuck') => void;
  onReset: () => void;
}

function TableAccordion({ table, expanded, detailTab, onToggle, onDetailTabChange, onReset }: TableAccordionProps) {
  return (
    <div className={`bg-wing-card rounded-xl border overflow-hidden
      ${table.stuck ? 'border-amber-400 ring-1 ring-amber-100' : 'border-wing-border'}`}>
      {/* Accordion header */}
      <button
        onClick={onToggle}
        className="w-full flex items-center justify-between px-5 py-3 hover:bg-wing-hover transition-colors text-left"
      >
        <div className="flex items-center gap-3">
          {table.stuck && <span className="text-red-500">⚠️</span>}
          <div>
            <span className="text-wing-text font-semibold text-sm">{table.targetTable}</span>
            <span className="text-xs text-wing-muted ml-2">{table.tableKey}</span>
          </div>
        </div>
        <div className="flex items-center gap-2 text-xs">
          <span className="inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full font-semibold tabular-nums bg-amber-100 text-amber-700">
            {table.pendingCount.toLocaleString()}
          </span>
          <span className={`inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full font-semibold tabular-nums
            ${table.stuck ? 'bg-red-100 text-red-700' : 'bg-blue-100 text-blue-700'}`}>
            {table.processingCount.toLocaleString()}
          </span>
          <span className="inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full font-semibold tabular-nums bg-emerald-100 text-emerald-700">
            {table.completedCount.toLocaleString()}
          </span>
          <span className="text-wing-muted w-16 text-right ml-1">{formatRelativeTime(table.lastSyncTime)}</span>
          <span className="text-wing-muted">{expanded ? '▲' : '▼'}</span>
        </div>
      </button>

      {/* Accordion body */}
      {expanded && (
        <div className="border-t border-wing-border p-5">
          {/* Stats row */}
          <div className="grid grid-cols-2 md:grid-cols-4 gap-3 mb-4">
            <MiniStat label="대기 (N)" value={table.pendingCount} color="text-amber-600 dark:text-amber-400" />
            <MiniStat label="진행 (P)" value={table.processingCount} color="text-blue-600 dark:text-blue-400"
              warn={table.stuck} />
            <MiniStat label="완료 (S)" value={table.completedCount} color="text-emerald-600 dark:text-emerald-400" />
            <div className="bg-wing-bg rounded-lg p-3">
              <p className="text-xs text-wing-muted">최근 동기화</p>
              <p className="text-sm font-medium text-wing-text mt-0.5">{formatRelativeTime(table.lastSyncTime)}</p>
            </div>
          </div>

          {/* Detail sub-tabs */}
          <div className="flex items-center justify-between mb-3">
            <div className="flex gap-1">
              <button
                onClick={() => onDetailTabChange('preview')}
                className={`px-3 py-1.5 rounded-lg text-xs font-medium transition-colors
                  ${detailTab === 'preview'
                    ? 'bg-wing-accent text-white'
                    : 'bg-wing-bg text-wing-muted hover:bg-wing-hover'
                  }`}
              >
                동기화 데이터
              </button>
              <button
                onClick={() => onDetailTabChange('stuck')}
                className={`px-3 py-1.5 rounded-lg text-xs font-medium transition-colors
                  ${detailTab === 'stuck'
                    ? 'bg-wing-accent text-white'
                    : 'bg-wing-bg text-wing-muted hover:bg-wing-hover'
                  }`}
              >
                P 상태 레코드
                {table.processingCount > 0 && (
                  <span className="ml-1 text-red-300">({table.processingCount.toLocaleString()})</span>
                )}
              </button>
            </div>
            {detailTab === 'stuck' && table.stuck && (
              <button
                onClick={onReset}
                className="px-3 py-1.5 text-xs font-medium text-white bg-red-500 hover:bg-red-600 rounded-lg transition-colors"
              >
                전체 P→N 리셋
              </button>
            )}
          </div>

          {/* Tab content */}
          {detailTab === 'preview' && (
            <InlineDataTable tableKey={table.tableKey} fetchFn={batchApi.getSyncDataPreview} />
          )}
          {detailTab === 'stuck' && (
            <InlineDataTable tableKey={table.tableKey} fetchFn={batchApi.getStuckRecords} />
          )}
        </div>
      )}
    </div>
  );
}

interface MiniStatProps {
  label: string;
  value: number;
  color: string;
  warn?: boolean;
}

function MiniStat({ label, value, color, warn }: MiniStatProps) {
  return (
    <div className={`bg-wing-bg rounded-lg p-3 ${warn ? 'ring-1 ring-red-400' : ''}`}>
      <p className="text-xs text-wing-muted">{label}</p>
      <p className={`text-lg font-bold mt-0.5 tabular-nums ${color}`}>
        {value.toLocaleString()}
        {warn && <span className="ml-1 text-xs text-red-500">고착</span>}
      </p>
    </div>
  );
}

interface InlineDataTableProps {
  tableKey: string;
  fetchFn: (tableKey: string, limit: number) => Promise<SyncDataPreviewResponse>;
}

function InlineDataTable({ tableKey, fetchFn }: InlineDataTableProps) {
  const [data, setData] = useState<SyncDataPreviewResponse | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    setLoading(true);
    setError(null);
    setData(null);
    fetchFn(tableKey, 20)
      .then(setData)
      .catch((e) => setError(e.message))
      .finally(() => setLoading(false));
  }, [tableKey, fetchFn]);

  if (loading) return <div className="py-8"><LoadingSpinner /></div>;
  if (error) return <div className="text-center py-8 text-red-400 text-sm">조회 실패: {error}</div>;
  if (!data || data.rows.length === 0) {
    return <div className="text-center py-8 text-wing-muted text-sm">데이터가 없습니다</div>;
  }

  return (
    <div>
      <div className="overflow-x-auto rounded-lg border border-wing-border">
        <table className="w-full text-xs">
          <thead>
            <tr className="border-b border-wing-border">
              {data.columns.map((col) => (
                <th
                  key={col}
                  className={`px-3 py-2 text-left font-medium whitespace-nowrap bg-wing-bg
                    ${col === 'batch_flag' ? 'text-blue-500' : 'text-wing-muted'}`}
                >
                  {col}
                </th>
              ))}
            </tr>
          </thead>
          <tbody>
            {data.rows.map((row, idx) => (
              <tr key={idx} className="border-b border-wing-border/50 hover:bg-wing-hover">
                {data.columns.map((col) => (
                  <td
                    key={col}
                    className={`px-3 py-1.5 whitespace-nowrap max-w-[200px] truncate
                      ${col === 'batch_flag' ? 'font-bold text-blue-600 dark:text-blue-400' : 'text-wing-text'}`}
                  >
                    {formatCellValue(row[col])}
                  </td>
                ))}
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      <p className="text-xs text-wing-muted mt-2">
        {data.rows.length}건 표시 (전체 {data.totalCount.toLocaleString()}건) &middot; {data.targetSchema}.{data.targetTable}
      </p>
    </div>
  );
}

function formatCellValue(value: unknown): string {
  if (value === null || value === undefined) return '-';
  if (typeof value === 'object') return JSON.stringify(value);
  return String(value);
}

function formatRelativeTime(dateStr: string | null): string {
  if (!dateStr) return '-';
  try {
    const date = new Date(dateStr);
    if (isNaN(date.getTime())) return '-';
    const now = new Date();
    const diffMs = now.getTime() - date.getTime();
    const diffMin = Math.floor(diffMs / 60000);
    if (diffMin < 1) return '방금 전';
    if (diffMin < 60) return `${diffMin}분 전`;
    const diffHour = Math.floor(diffMin / 60);
    if (diffHour < 24) return `${diffHour}시간 전`;
    const diffDay = Math.floor(diffHour / 24);
    return `${diffDay}일 전`;
  } catch {
    return '-';
  }
}
