import { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { AlertOctagon, RefreshCw } from 'lucide-react';

import { PageContainer, PageHeader, Section } from '@shared/components/layout';
import { Badge } from '@shared/components/ui/badge';
import { Button } from '@shared/components/ui/button';
import { Input } from '@shared/components/ui/input';
import { Select } from '@shared/components/ui/select';
import { Textarea } from '@shared/components/ui/textarea';
import { Card, CardContent } from '@shared/components/ui/card';
import { DataTable, type DataColumn } from '@shared/components/common/DataTable';

import { formatDateTime } from '@shared/utils/dateFormat';
import { getAlertLevelIntent, getAlertLevelLabel } from '@shared/constants/alertLevels';
import {
  GEAR_COLLISION_STATUS_ORDER,
  getGearCollisionStatusIntent,
  getGearCollisionStatusLabel,
} from '@shared/constants/gearCollisionStatuses';
import {
  getGearCollisionStats,
  listGearCollisions,
  resolveGearCollision,
  type GearCollision,
  type GearCollisionResolveAction,
  type GearCollisionStats,
} from '@/services/gearCollisionApi';
import { useSettingsStore } from '@stores/settingsStore';

/**
 * 어구 정체성 충돌(GEAR_IDENTITY_COLLISION) 탐지 페이지.
 *
 * 동일 어구 이름이 서로 다른 MMSI 로 같은 cycle 에 공존 송출되는 경우를 목록화하고
 * 운영자가 REVIEWED / CONFIRMED_ILLEGAL / FALSE_POSITIVE 로 분류할 수 있게 한다.
 */

type SeverityCode = 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW';
const SEVERITY_OPTIONS: SeverityCode[] = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW'];
const DEFAULT_HOURS = 48;

export function GearCollisionDetection() {
  const { t } = useTranslation('detection');
  const { t: tc } = useTranslation('common');
  const lang = useSettingsStore((s) => s.language) as 'ko' | 'en';

  const [rows, setRows] = useState<GearCollision[]>([]);
  const [stats, setStats] = useState<GearCollisionStats | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState('');
  const [statusFilter, setStatusFilter] = useState<string>('');
  const [severityFilter, setSeverityFilter] = useState<string>('');
  const [nameFilter, setNameFilter] = useState<string>('');
  const [selected, setSelected] = useState<GearCollision | null>(null);
  const [resolveAction, setResolveAction] = useState<GearCollisionResolveAction>('REVIEWED');
  const [resolveNote, setResolveNote] = useState('');
  const [resolving, setResolving] = useState(false);

  const loadData = useCallback(async () => {
    setLoading(true);
    setError('');
    try {
      const [page, summary] = await Promise.all([
        listGearCollisions({
          status: statusFilter || undefined,
          severity: severityFilter || undefined,
          name: nameFilter || undefined,
          hours: DEFAULT_HOURS,
          size: 200,
        }),
        getGearCollisionStats(DEFAULT_HOURS),
      ]);
      setRows(page.content);
      setStats(summary);
    } catch (e: unknown) {
      setError(e instanceof Error ? e.message : t('gearCollision.error.loadFailed'));
    } finally {
      setLoading(false);
    }
  }, [statusFilter, severityFilter, nameFilter, t]);

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

  // 선택된 row 와 현재 목록의 동기화
  const syncedSelected = useMemo(
    () => selected ? rows.find((r) => r.id === selected.id) ?? selected : null,
    [rows, selected],
  );

  const cols: DataColumn<GearCollision & Record<string, unknown>>[] = useMemo(() => [
    {
      key: 'name', label: t('gearCollision.columns.name'), minWidth: '120px', sortable: true,
      render: (v) => <span className="text-cyan-600 dark:text-cyan-400 font-medium">{v as string}</span>,
    },
    {
      key: 'mmsiLo', label: t('gearCollision.columns.mmsiPair'), minWidth: '160px',
      render: (_, row) => (
        <span className="font-mono text-[10px] text-label">
          {row.mmsiLo} ↔ {row.mmsiHi}
        </span>
      ),
    },
    {
      key: 'parentName', label: t('gearCollision.columns.parentName'), minWidth: '110px',
      render: (v) => <span className="text-hint text-[10px]">{(v as string) || '-'}</span>,
    },
    {
      key: 'coexistenceCount', label: t('gearCollision.columns.coexistenceCount'),
      width: '90px', align: 'center', sortable: true,
      render: (v) => <span className="font-mono text-label">{v as number}</span>,
    },
    {
      key: 'maxDistanceKm', label: t('gearCollision.columns.maxDistance'),
      width: '110px', align: 'right', sortable: true,
      render: (v) => {
        const n = typeof v === 'number' ? v : Number(v ?? 0);
        return <span className="font-mono text-[10px] text-label">{n.toFixed(2)}</span>;
      },
    },
    {
      key: 'severity', label: t('gearCollision.columns.severity'),
      width: '90px', align: 'center', sortable: true,
      render: (v) => (
        <Badge intent={getAlertLevelIntent(v as string)} size="sm">
          {getAlertLevelLabel(v as string, tc, lang)}
        </Badge>
      ),
    },
    {
      key: 'status', label: t('gearCollision.columns.status'),
      width: '110px', align: 'center', sortable: true,
      render: (v) => (
        <Badge intent={getGearCollisionStatusIntent(v as string)} size="sm">
          {getGearCollisionStatusLabel(v as string, t, lang)}
        </Badge>
      ),
    },
    {
      key: 'lastSeenAt', label: t('gearCollision.columns.lastSeen'),
      width: '130px', sortable: true,
      render: (v) => (
        <span className="text-muted-foreground text-[10px]">{formatDateTime(v as string)}</span>
      ),
    },
  ], [t, tc, lang]);

  const handleResolve = useCallback(async () => {
    if (!syncedSelected) return;
    const ok = window.confirm(t('gearCollision.resolve.confirmPrompt'));
    if (!ok) return;
    setResolving(true);
    try {
      const updated = await resolveGearCollision(syncedSelected.id, {
        action: resolveAction,
        note: resolveNote || undefined,
      });
      setSelected(updated);
      setResolveNote('');
      await loadData();
    } catch (e: unknown) {
      setError(e instanceof Error ? e.message : t('gearCollision.error.resolveFailed'));
    } finally {
      setResolving(false);
    }
  }, [syncedSelected, resolveAction, resolveNote, loadData, t]);

  const statusCount = (code: string) => stats?.byStatus?.[code] ?? 0;

  return (
    <PageContainer>
      <PageHeader
        icon={AlertOctagon}
        iconColor="text-orange-600 dark:text-orange-400"
        title={t('gearCollision.title')}
        description={t('gearCollision.desc')}
        actions={
          <Button
            variant="outline"
            size="sm"
            onClick={loadData}
            disabled={loading}
            icon={<RefreshCw className="w-3.5 h-3.5" />}
          >
            {t('gearCollision.list.refresh')}
          </Button>
        }
      />

      {error && (
        <Card variant="default">
          <CardContent className="text-destructive text-xs py-2">{error}</CardContent>
        </Card>
      )}

      <Section title={t('gearCollision.stats.title')}>
        <div className="grid grid-cols-2 md:grid-cols-5 gap-2">
          <StatCard label={t('gearCollision.stats.total')} value={stats?.total ?? 0} />
          <StatCard
            label={t('gearCollision.stats.open')}
            value={statusCount('OPEN')}
            intent="warning"
          />
          <StatCard
            label={t('gearCollision.stats.reviewed')}
            value={statusCount('REVIEWED')}
            intent="info"
          />
          <StatCard
            label={t('gearCollision.stats.confirmed')}
            value={statusCount('CONFIRMED_ILLEGAL')}
            intent="critical"
          />
          <StatCard
            label={t('gearCollision.stats.falsePositive')}
            value={statusCount('FALSE_POSITIVE')}
            intent="muted"
          />
        </div>
      </Section>

      <Section title={t('gearCollision.list.title')}>
        <div className="grid grid-cols-1 md:grid-cols-4 gap-2 mb-3">
          <Select
            aria-label={t('gearCollision.filters.status')}
            value={statusFilter}
            onChange={(e) => setStatusFilter(e.target.value)}
          >
            <option value="">{t('gearCollision.filters.allStatus')}</option>
            {GEAR_COLLISION_STATUS_ORDER.map((s) => (
              <option key={s} value={s}>{getGearCollisionStatusLabel(s, t, lang)}</option>
            ))}
          </Select>
          <Select
            aria-label={t('gearCollision.filters.severity')}
            value={severityFilter}
            onChange={(e) => setSeverityFilter(e.target.value)}
          >
            <option value="">{t('gearCollision.filters.allSeverity')}</option>
            {SEVERITY_OPTIONS.map((sv) => (
              <option key={sv} value={sv}>{getAlertLevelLabel(sv, tc, lang)}</option>
            ))}
          </Select>
          <Input
            aria-label={t('gearCollision.filters.name')}
            placeholder={t('gearCollision.filters.name')}
            value={nameFilter}
            onChange={(e) => setNameFilter(e.target.value)}
          />
          <div className="flex items-center justify-end">
            <Badge intent="info" size="sm">
              {t('gearCollision.filters.hours')} · {DEFAULT_HOURS}h
            </Badge>
          </div>
        </div>

        {rows.length === 0 && !loading ? (
          <p className="text-hint text-xs py-4 text-center">
            {t('gearCollision.list.empty', { hours: DEFAULT_HOURS })}
          </p>
        ) : (
          <DataTable
            data={rows as (GearCollision & Record<string, unknown>)[]}
            columns={cols}
            pageSize={20}
            showSearch={false}
            showExport={false}
            showPrint={false}
            onRowClick={(row) => setSelected(row as GearCollision)}
          />
        )}
      </Section>

      {syncedSelected && (
        <Section title={t('gearCollision.detail.title')}>
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <div className="space-y-1.5 text-xs">
              <DetailRow label={t('gearCollision.columns.name')} value={syncedSelected.name} mono />
              <DetailRow
                label={t('gearCollision.columns.mmsiPair')}
                value={`${syncedSelected.mmsiLo} ↔ ${syncedSelected.mmsiHi}`}
                mono
              />
              <DetailRow
                label={t('gearCollision.columns.parentName')}
                value={syncedSelected.parentName ?? '-'}
              />
              <DetailRow
                label={t('gearCollision.detail.firstSeenAt')}
                value={formatDateTime(syncedSelected.firstSeenAt)}
              />
              <DetailRow
                label={t('gearCollision.detail.lastSeenAt')}
                value={formatDateTime(syncedSelected.lastSeenAt)}
              />
              <DetailRow
                label={t('gearCollision.columns.coexistenceCount')}
                value={String(syncedSelected.coexistenceCount)}
              />
              <DetailRow
                label={t('gearCollision.detail.swapCount')}
                value={String(syncedSelected.swapCount)}
              />
              <DetailRow
                label={t('gearCollision.columns.maxDistance')}
                value={
                  syncedSelected.maxDistanceKm != null
                    ? Number(syncedSelected.maxDistanceKm).toFixed(2)
                    : '-'
                }
              />
            </div>
            <div className="space-y-2">
              <div className="flex items-center gap-2">
                <span className="text-xs text-label">
                  {t('gearCollision.columns.severity')}:
                </span>
                <Badge intent={getAlertLevelIntent(syncedSelected.severity)} size="sm">
                  {getAlertLevelLabel(syncedSelected.severity, tc, lang)}
                </Badge>
                <span className="text-xs text-label ml-3">
                  {t('gearCollision.columns.status')}:
                </span>
                <Badge intent={getGearCollisionStatusIntent(syncedSelected.status)} size="sm">
                  {getGearCollisionStatusLabel(syncedSelected.status, t, lang)}
                </Badge>
              </div>
              {syncedSelected.resolutionNote && (
                <p className="text-xs text-hint border-l-2 border-border pl-2">
                  {syncedSelected.resolutionNote}
                </p>
              )}
              <div className="space-y-1.5">
                <label
                  htmlFor="gc-resolve-action"
                  className="block text-xs text-label"
                >
                  {t('gearCollision.resolve.title')}
                </label>
                <Select
                  id="gc-resolve-action"
                  aria-label={t('gearCollision.resolve.title')}
                  value={resolveAction}
                  onChange={(e) => setResolveAction(e.target.value as GearCollisionResolveAction)}
                >
                  <option value="REVIEWED">{t('gearCollision.resolve.reviewed')}</option>
                  <option value="CONFIRMED_ILLEGAL">
                    {t('gearCollision.resolve.confirmedIllegal')}
                  </option>
                  <option value="FALSE_POSITIVE">
                    {t('gearCollision.resolve.falsePositive')}
                  </option>
                  <option value="REOPEN">{t('gearCollision.resolve.reopen')}</option>
                </Select>
                <Textarea
                  aria-label={t('gearCollision.resolve.note')}
                  placeholder={t('gearCollision.resolve.notePlaceholder')}
                  value={resolveNote}
                  onChange={(e) => setResolveNote(e.target.value)}
                  rows={3}
                />
                <div className="flex gap-2 justify-end">
                  <Button
                    variant="ghost"
                    size="sm"
                    onClick={() => { setSelected(null); setResolveNote(''); }}
                  >
                    {t('gearCollision.resolve.cancel')}
                  </Button>
                  <Button
                    variant="primary"
                    size="sm"
                    onClick={handleResolve}
                    disabled={resolving}
                  >
                    {t('gearCollision.resolve.submit')}
                  </Button>
                </div>
              </div>
            </div>
          </div>
        </Section>
      )}
    </PageContainer>
  );
}

// ─── 내부 컴포넌트 ─────────────

interface StatCardProps {
  label: string;
  value: number;
  intent?: 'warning' | 'info' | 'critical' | 'muted';
}

function StatCard({ label, value, intent }: StatCardProps) {
  return (
    <Card variant="default">
      <CardContent className="py-3 flex flex-col items-center gap-1">
        <span className="text-[10px] text-hint">{label}</span>
        {intent ? (
          <Badge intent={intent} size="md">
            {value}
          </Badge>
        ) : (
          <span className="text-lg font-bold text-heading">{value}</span>
        )}
      </CardContent>
    </Card>
  );
}

interface DetailRowProps {
  label: string;
  value: string;
  mono?: boolean;
}

function DetailRow({ label, value, mono }: DetailRowProps) {
  return (
    <div className="flex items-center gap-2">
      <span className="text-hint w-24 shrink-0">{label}</span>
      <span className={mono ? 'font-mono text-label' : 'text-label'}>{value}</span>
    </div>
  );
}

export default GearCollisionDetection;
