import React, { useEffect, useMemo, useState } from 'react';
import { Download, RefreshCw, Scissors, Trash2 } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { useSearchParams } from 'react-router-dom';
import { useAppContext } from '../context/AppContext';
import ArtifactPreviewCard from '../components/data-display/ArtifactPreviewCard';
import { FixedButton, FixedLinkButton, LinkButton } from '../components/ui/Button';
import CodeBlockPanel from '../components/data-display/CodeBlockPanel';
import EmptyState from '../components/data-display/EmptyState';
import { SelectField, TextField } from '../components/ui/FormControls';
import ListPanel from '../components/layout/ListPanel';
import SummaryListItem from '../components/list/SummaryListItem';
import { dataUrlForArtifact, formatArtifactBytes } from '../utils/artifacts';
import { formatLocalDateTime } from '../utils/time';

const NodeArtifacts: React.FC = () => {
  const { t } = useTranslation();
  const { q } = useAppContext();
  const [searchParams, setSearchParams] = useSearchParams();
  const [items, setItems] = useState<any[]>([]);
  const [retentionSummary, setRetentionSummary] = useState<Record<string, any>>({});
  const [selectedID, setSelectedID] = useState('');
  const [loading, setLoading] = useState(false);
  const [prunePending, setPrunePending] = useState(false);
  const [nodeFilter, setNodeFilter] = useState(searchParams.get('node') || 'all');
  const [actionFilter, setActionFilter] = useState(searchParams.get('action') || 'all');
  const [kindFilter, setKindFilter] = useState(searchParams.get('kind') || 'all');
  const [keepLatest, setKeepLatest] = useState('20');

  const apiQuery = useMemo(() => {
    const params = new URLSearchParams();
    params.set('limit', '400');
    if (nodeFilter !== 'all') params.set('node', nodeFilter);
    if (actionFilter !== 'all') params.set('action', actionFilter);
    if (kindFilter !== 'all') params.set('kind', kindFilter);
    return params.toString();
  }, [nodeFilter, actionFilter, kindFilter]);

  useEffect(() => {
    const next = new URLSearchParams();
    if (nodeFilter !== 'all') next.set('node', nodeFilter);
    if (actionFilter !== 'all') next.set('action', actionFilter);
    if (kindFilter !== 'all') next.set('kind', kindFilter);
    setSearchParams(next, { replace: true });
  }, [nodeFilter, actionFilter, kindFilter, setSearchParams]);

  const loadArtifacts = async () => {
    setLoading(true);
    try {
      const query = q ? `${q}&${apiQuery}` : `?${apiQuery}`;
      const r = await fetch(`/webui/api/node_artifacts${query}`);
      if (!r.ok) throw new Error(await r.text());
      const j = await r.json();
      const next = Array.isArray(j.items) ? j.items : [];
      setRetentionSummary(j.artifact_retention && typeof j.artifact_retention === 'object' ? j.artifact_retention : {});
      setItems(next);
      if (next.length === 0) {
        setSelectedID('');
      } else if (!next.some((item: any) => String(item?.id || '') === selectedID)) {
        setSelectedID(String(next[0]?.id || ''));
      }
    } catch (err) {
      console.error(err);
      setItems([]);
      setSelectedID('');
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    loadArtifacts();
  }, [q, apiQuery]);

  const nodes = useMemo(() => Array.from(new Set(items.map((item) => String(item?.node || '')).filter(Boolean))).sort(), [items]);
  const actions = useMemo(() => Array.from(new Set(items.map((item) => String(item?.action || '')).filter(Boolean))).sort(), [items]);
  const kinds = useMemo(() => Array.from(new Set(items.map((item) => String(item?.kind || '')).filter(Boolean))).sort(), [items]);

  const filteredItems = items;

  const selected = useMemo(() => {
    return filteredItems.find((item) => String(item?.id || '') === selectedID) || filteredItems[0] || null;
  }, [filteredItems, selectedID]);

  async function deleteArtifact(id: string) {
    const r = await fetch(`/webui/api/node_artifacts/delete${q}`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ id }),
    });
    if (!r.ok) throw new Error(await r.text());
    await loadArtifacts();
  }

  async function pruneArtifacts() {
    setPrunePending(true);
    try {
      const keep = Math.max(0, Number.parseInt(keepLatest || '0', 10) || 0);
      const r = await fetch(`/webui/api/node_artifacts/prune${q}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          node: nodeFilter === 'all' ? '' : nodeFilter,
          action: actionFilter === 'all' ? '' : actionFilter,
          kind: kindFilter === 'all' ? '' : kindFilter,
          keep_latest: keep,
          limit: 1000,
        }),
      });
      if (!r.ok) throw new Error(await r.text());
      const j = await r.json();
      setRetentionSummary(j && typeof j === 'object' ? { ...retentionSummary, manual_pruned: j.pruned, manual_deleted_files: j.deleted_files, last_run_at: new Date().toISOString() } : retentionSummary);
      await loadArtifacts();
    } catch (err) {
      console.error(err);
    } finally {
      setPrunePending(false);
    }
  }

  function downloadURL(id: string) {
    return `/webui/api/node_artifacts/download${q ? `${q}&id=${encodeURIComponent(id)}` : `?id=${encodeURIComponent(id)}`}`;
  }

  function exportURL() {
    const query = q ? `${q}&${apiQuery}` : `?${apiQuery}`;
    return `/webui/api/node_artifacts/export${query}`;
  }

  return (
    <div className="h-full p-4 md:p-6 xl:p-8 flex flex-col gap-4">
      <div className="flex items-center justify-between flex-wrap gap-3">
        <div>
          <h1 className="ui-text-primary text-xl md:text-2xl font-semibold">{t('nodeArtifacts')}</h1>
          <div className="ui-text-muted text-sm mt-1">{t('nodeArtifactsHint')}</div>
        </div>
        <div className="flex items-center gap-2">
          <FixedLinkButton href={exportURL()} label={t('export')}>
            <Download className="w-4 h-4" />
          </FixedLinkButton>
          <FixedButton onClick={loadArtifacts} variant="primary" label={loading ? t('loading') : t('refresh')}>
            <RefreshCw className={`w-4 h-4 ${loading ? 'animate-spin' : ''}`} />
          </FixedButton>
        </div>
      </div>

      <div className="grid grid-cols-1 xl:grid-cols-[320px_1fr] gap-4 flex-1 min-h-0">
        <ListPanel>
          <div className="ui-border-subtle p-3 border-b space-y-2">
            <div className="ui-code-panel ui-text-secondary p-3 text-xs space-y-1">
              <div className="ui-text-primary font-medium">{t('nodeArtifactsRetention')}</div>
              <div>{t('nodeArtifactsRetentionKeepLatest')}: {Number(retentionSummary?.keep_latest || 0) || '-'}</div>
              <div>{t('nodeArtifactsRetentionRetainDays')}: {Number(retentionSummary?.retain_days || 0)}</div>
              <div>{t('nodeArtifactsRetentionPruned')}: {Number(retentionSummary?.pruned || retentionSummary?.manual_pruned || 0)}</div>
              <div>{t('nodeArtifactsRetentionRemaining')}: {Number(retentionSummary?.remaining || filteredItems.length || 0)}</div>
            </div>
            <div className="grid grid-cols-1 gap-2">
              <SelectField dense value={nodeFilter} onChange={(e) => setNodeFilter(e.target.value)}>
                <option value="all">{t('allNodes')}</option>
                {nodes.map((node) => <option key={node} value={node}>{node}</option>)}
              </SelectField>
              <SelectField dense value={actionFilter} onChange={(e) => setActionFilter(e.target.value)}>
                <option value="all">{t('allActions')}</option>
                {actions.map((action) => <option key={action} value={action}>{action}</option>)}
              </SelectField>
              <SelectField dense value={kindFilter} onChange={(e) => setKindFilter(e.target.value)}>
                <option value="all">{t('allKinds')}</option>
                {kinds.map((kind) => <option key={kind} value={kind}>{kind}</option>)}
              </SelectField>
            </div>
            <div className="grid grid-cols-[1fr_auto] gap-2">
              <TextField
                value={keepLatest}
                onChange={(e) => setKeepLatest(e.target.value)}
                inputMode="numeric"
                placeholder={t('nodeArtifactsKeepLatest')}
                dense
              />
              <FixedButton onClick={pruneArtifacts} disabled={prunePending} variant="warning" label={prunePending ? t('loading') : t('nodeArtifactsPrune')}>
                <Scissors className="w-4 h-4" />
              </FixedButton>
            </div>
          </div>
          <div className="overflow-y-auto min-h-0">
            {filteredItems.length === 0 ? (
              <EmptyState message={t('nodeArtifactsEmpty')} padded />
            ) : filteredItems.map((item, index) => {
              const active = String(selected?.id || '') === String(item?.id || '');
              return (
                <SummaryListItem
                  key={String(item?.id || index)}
                  onClick={() => setSelectedID(String(item?.id || ''))}
                  active={active}
                  className="border-b py-3"
                  title={String(item?.name || item?.source_path || `artifact-${index + 1}`)}
                  subtitle={`${String(item?.node || '-')} · ${String(item?.action || '-')} · ${String(item?.kind || '-')}`}
                  meta={formatLocalDateTime(item?.time)}
                />
              );
            })}
          </div>
        </ListPanel>

        <ListPanel header={<div className="ui-border-subtle ui-text-subtle px-3 py-2 border-b text-xs uppercase tracking-wider">{t('nodeArtifactDetail')}</div>}>
          <div className="p-4 overflow-y-auto min-h-0 space-y-4 text-sm">
            {!selected ? (
              <EmptyState message={t('nodeArtifactsEmpty')} />
            ) : (
              <>
                <div className="flex items-center justify-between gap-3">
                  <div>
                    <div className="ui-text-primary text-lg font-medium">{String(selected?.name || selected?.source_path || 'artifact')}</div>
                    <div className="ui-text-muted text-xs mt-1">{String(selected?.node || '-')} · {String(selected?.action || '-')} · {formatLocalDateTime(selected?.time)}</div>
                  </div>
                  <div className="flex items-center gap-2">
                    <LinkButton href={downloadURL(String(selected?.id || ''))} size="xs">{t('download')}</LinkButton>
                    <FixedButton onClick={() => deleteArtifact(String(selected?.id || ''))} variant="danger" label={t('delete')}>
                      <Trash2 className="w-4 h-4" />
                    </FixedButton>
                  </div>
                </div>

                <div className="grid grid-cols-2 md:grid-cols-4 gap-3">
                  <div><div className="ui-text-muted text-xs">{t('node')}</div><div className="ui-text-secondary">{String(selected?.node || '-')}</div></div>
                  <div><div className="ui-text-muted text-xs">{t('action')}</div><div className="ui-text-secondary">{String(selected?.action || '-')}</div></div>
                  <div><div className="ui-text-muted text-xs">{t('kind')}</div><div className="ui-text-secondary">{String(selected?.kind || '-')}</div></div>
                  <div><div className="ui-text-muted text-xs">{t('size')}</div><div className="ui-text-secondary">{formatArtifactBytes(selected?.size_bytes)}</div></div>
                </div>

                <div className="ui-text-muted text-xs break-all">
                  {String(selected?.source_path || selected?.path || selected?.url || '-')}
                </div>

                <ArtifactPreviewCard
                  artifact={selected}
                  dataUrl={dataUrlForArtifact(selected)}
                  fallbackName={String(selected?.name || 'artifact')}
                  formatBytes={formatArtifactBytes}
                  className="max-h-[420px]"
                />

                {String(selected?.content_text || '').trim() === '' && !String(selected?.content_base64 || '').trim() ? (
                  <EmptyState message={t('nodeArtifactPreviewUnavailable')} />
                ) : null}

                <CodeBlockPanel label={t('rawJson')} pre>{JSON.stringify(selected, null, 2)}</CodeBlockPanel>
              </>
            )}
          </div>
        </ListPanel>
      </div>
    </div>
  );
};

export default NodeArtifacts;
