'use client';
// @design-system: admin/TmReviewTable/TmReviewTable

/**
 * TmReviewTable — admin component for /admin/translations/memory
 * Shows TM entries with quality-score controls and eviction.
 */

import { useState, useEffect, useCallback, useMemo } from 'react';
import { useUrlFilterState } from '@/lib/url/useUrlFilterState';
import { makeTmReviewCodec, type TmReviewFilter } from '@/lib/url/codecs/tmReviewCodec';
import { HISTORY } from '@/lib/url/historyPolicy';
import { AdminTable } from '@/components/ui/domain/admin/AdminTable';
import { Button } from '@/components/ui/primitives/Button';
import { Badge } from '@/components/ui/primitives/Badge';
import { useT } from '@/lib/i18n/react';
import { interpolate } from '@/lib/i18n/interpolate';
import { getCsrfToken } from '@/lib/csrf';
import { captureCaught } from '@/lib/observability';
import { fetchWithRefresh } from '@/lib/api/refresh-on-401';
import type { StringBundle } from '@/lib/i18n/types';

export interface TmEntry {
  sourceHash: string;
  sourceLocale: string;
  targetLocale: string;
  sourceText: string;
  translatedText: string;
  modelId: string;
  qualityScore: number | null;
  usageCount: number;
  lastUsedAt: string;
}

export interface TmReviewTableProps {
  initialFilter?: 'low-quality' | 'most-reused' | 'recent';
}

type FilterType = TmReviewFilter;

type AdminTranslationsT = ReturnType<typeof useT<keyof StringBundle & 'admin_translations'>>;

function localeLabel(t: AdminTranslationsT, code: string): string {
  const langKey = `lang_${code}` as Parameters<AdminTranslationsT>[0];
  const name = t(langKey);
  return name !== langKey ? name : code;
}

export function TmReviewTable({ initialFilter = 'recent' }: TmReviewTableProps) {
  const t = useT('admin_translations');
  const codec = useMemo(() => makeTmReviewCodec('/admin/translations/memory'), []);
  const { state: urlState, setUrlState } = useUrlFilterState({
    initial: { filter: initialFilter },
    codec,
  });
  const filter = urlState.filter;
  const [rows, setRows] = useState<TmEntry[]>([]);
  const [loading, setLoading] = useState(true);
  const [loadError, setLoadError] = useState<string | null>(null);
  const [updating, setUpdating] = useState<string | null>(null);

  const load = useCallback(async () => {
    setLoading(true);
    setLoadError(null);
    try {
      const res = await fetchWithRefresh(
        `/api/admin/translations/memory?filter=${filter}&limit=50`,
      );
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      const json = (await res.json()) as { ok: boolean; rows?: TmEntry[] };
      if (json.ok) {
        setRows(json.rows ?? []);
      } else {
        throw new Error('Failed to load');
      }
    } catch (err) {
      captureCaught(err, { scope: 'TmReviewTable.load', severity: 'warning' });
      setLoadError(t('tm_load_error'));
    } finally {
      setLoading(false);
    }
  }, [filter, t]);

  // Fetch on mount and when filter changes — async setState is intentional here.
  useEffect(() => {
    queueMicrotask(() => void load());
  }, [load]);

  const [actionError, setActionError] = useState<string | null>(null);

  async function handleScore(entry: TmEntry, score: number) {
    const key = `${entry.sourceHash}:${entry.targetLocale}`;
    setUpdating(key);
    setActionError(null);
    try {
      const res = await fetchWithRefresh('/api/admin/translations/memory', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json', 'x-csrf-token': getCsrfToken() },
        body: JSON.stringify({
          sourceHash: entry.sourceHash,
          sourceLocale: entry.sourceLocale,
          targetLocale: entry.targetLocale,
          qualityScore: score,
        }),
      });
      const json = (await res.json().catch((err) => {
        captureCaught(err, { scope: 'TmReviewTable.handleScore.parse', severity: 'info' });
        return {};
      })) as { ok?: boolean };
      if (!res.ok || json.ok === false) {
        setActionError(t('tm_load_error'));
        return;
      }
      if (score === -1) {
        setRows((prev) =>
          prev.filter(
            (r) => !(r.sourceHash === entry.sourceHash && r.targetLocale === entry.targetLocale),
          ),
        );
      } else {
        setRows((prev) =>
          prev.map((r) =>
            r.sourceHash === entry.sourceHash && r.targetLocale === entry.targetLocale
              ? { ...r, qualityScore: score }
              : r,
          ),
        );
      }
    } catch (err) {
      captureCaught(err, { scope: 'TmReviewTable.handleScore', severity: 'warning' });
      setActionError(t('tm_load_error'));
    } finally {
      setUpdating(null);
    }
  }

  const filters: FilterType[] = ['recent', 'low-quality', 'most-reused'];

  const columns = [
    {
      key: 'localePair',
      label: t('tm_col_locale_pair'),
      headerTooltip: t('locale_pair_tooltip'),
      render: (row: TmEntry) =>
        `${localeLabel(t, row.sourceLocale)} → ${localeLabel(t, row.targetLocale)}`,
    },
    {
      key: 'sourceText',
      label: t('tm_col_source'),
      render: (row: TmEntry) => (
        <span className="block max-w-xs truncate" title={row.sourceText}>
          {row.sourceText.slice(0, 80)}
        </span>
      ),
    },
    {
      key: 'translatedText',
      label: t('tm_col_translation'),
      render: (row: TmEntry) => (
        <span className="block max-w-xs truncate" title={row.translatedText}>
          {row.translatedText.slice(0, 80)}
        </span>
      ),
    },
    {
      key: 'usageCount',
      label: t('tm_col_usage'),
      headerTooltip: t('usage_header_tooltip'),
    },
    {
      key: 'qualityScore',
      label: t('tm_col_quality'),
      headerTooltip: t('quality_header_tooltip'),
      render: (row: TmEntry) => (
        <Badge
          tone={
            row.qualityScore !== null && row.qualityScore >= 4
              ? 'success'
              : row.qualityScore !== null && row.qualityScore <= 1
                ? 'danger'
                : 'neutral'
          }
        >
          {row.qualityScore ?? t('tm_not_rated')}
        </Badge>
      ),
    },
    {
      key: 'actions',
      label: t('tm_col_actions'),
      render: (row: TmEntry) => {
        const key = `${row.sourceHash}:${row.targetLocale}`;
        const busy = updating === key;
        return (
          <div className="flex items-center gap-1" role="group" aria-label={t('tm_score_aria')}>
            {[1, 2, 3, 4, 5].map((score) => (
              <Button
                key={score}
                variant="ghost"
                size="sm"
                disabled={busy}
                aria-pressed={row.qualityScore === score}
                aria-label={interpolate(t('tm_score_btn_aria'), { score })}
                onClick={() => handleScore(row, score)}
              >
                {score}
              </Button>
            ))}
            <Button
              variant="danger"
              size="sm"
              disabled={busy}
              onClick={() => handleScore(row, -1)}
              aria-label={t('tm_evict')}
              title={t('evict_tooltip')}
            >
              {t('tm_evict')}
            </Button>
          </div>
        );
      },
    },
  ];

  return (
    <div className="flex flex-col gap-4">
      <div>
        <h1 className="text-text-default text-xl font-bold">{t('translations_memory_title')}</h1>
        <p className="text-text-muted mt-1 text-sm">{t('translations_memory_subtitle')}</p>
      </div>

      {(loadError || actionError) && (
        <div role="alert" className="text-danger-600 text-sm">
          {loadError ?? actionError}
        </div>
      )}

      <div role="group" aria-label={t('tm_filter_label')} className="flex gap-2">
        {filters.map((f) => (
          <button
            key={f}
            type="button"
            aria-pressed={filter === f}
            onClick={() => setUrlState({ filter: f }, HISTORY.tweak)}
            className={[
              'rounded-full px-3 py-1 text-sm font-medium transition-colors',
              filter === f
                ? 'bg-brand-primary-600 text-brand-on-primary'
                : 'bg-surface-subtle text-text-default hover:bg-surface-hover',
            ].join(' ')}
          >
            {t(`tm_filter_${f}` as Parameters<typeof t>[0])}
          </button>
        ))}
      </div>

      <AdminTable
        columns={columns}
        rows={rows.map((r) => ({ ...r, id: `${r.sourceHash}:${r.targetLocale}` }))}
        loading={loading}
      />
    </div>
  );
}
