import { useEffect, useRef, useState } from 'react';
import { Loader2, X, Activity } from 'lucide-react';
import { usePluginContext } from './client';
import type { AnalysisJob } from './types';

const API_BASE = '/api/v1/plugin/data_analytics';

interface Props {
  jobId: string;
  onClose: () => void;
}

interface StreamEvent {
  type?: string;
  ts?: number;
  payload?: unknown;
  raw?: string;
}

export function JobDetail({ jobId, onClose }: Props) {
  const { client, token, apiBase } = usePluginContext();
  const [job, setJob] = useState<AnalysisJob | null>(null);
  const [events, setEvents] = useState<StreamEvent[]>([]);
  const [loading, setLoading] = useState(true);
  const eventBoxRef = useRef<HTMLDivElement | null>(null);

  // 初次加载 + 后台轮询
  useEffect(() => {
    let cancelled = false;
    const fetchJob = async () => {
      try {
        const resp = await client.get<AnalysisJob>(`${API_BASE}/jobs/${jobId}`);
        if (!cancelled) setJob(resp.data);
      } catch (e) {
        console.error('fetch job failed', e);
      } finally {
        if (!cancelled) setLoading(false);
      }
    };
    fetchJob();
    const t = setInterval(fetchJob, 4000);
    return () => {
      cancelled = true;
      clearInterval(t);
    };
  }, [client, jobId]);

  // SSE 事件流（用 fetch + ReadableStream，因为 EventSource 不支持自定义 header）
  useEffect(() => {
    const controller = new AbortController();
    const run = async () => {
      try {
        const url = `${apiBase || ''}${API_BASE}/jobs/${jobId}/stream`;
        const resp = await fetch(url, {
          headers: { Authorization: `Bearer ${token}` },
          signal: controller.signal,
        });
        if (!resp.body) return;
        const reader = resp.body.getReader();
        const decoder = new TextDecoder('utf-8');
        let buf = '';
        // eslint-disable-next-line no-constant-condition
        while (true) {
          const { value, done } = await reader.read();
          if (done) break;
          buf += decoder.decode(value, { stream: true });
          const parts = buf.split('\n\n');
          buf = parts.pop() || '';
          for (const part of parts) {
            const line = part.split('\n').find((l) => l.startsWith('data:'));
            if (!line) continue;
            const payload = line.slice(5).trim();
            try {
              setEvents((prev) => [...prev, JSON.parse(payload)]);
            } catch {
              setEvents((prev) => [...prev, { raw: payload }]);
            }
          }
        }
      } catch (e) {
        if ((e as Error).name !== 'AbortError') console.error('SSE error', e);
      }
    };
    run();
    return () => controller.abort();
  }, [apiBase, jobId, token]);

  // 自动滚动到底部
  useEffect(() => {
    if (eventBoxRef.current) {
      eventBoxRef.current.scrollTop = eventBoxRef.current.scrollHeight;
    }
  }, [events]);

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4">
      <div className="w-full max-w-3xl max-h-[85vh] bg-bg-card rounded-2xl border border-border-primary shadow-xl flex flex-col">
        <div className="flex items-center justify-between p-4 border-b border-border-primary">
          <div className="min-w-0">
            <h3 className="font-semibold text-text-primary flex items-center gap-2">
              <Activity size={16} className="text-accent" />
              任务详情
            </h3>
            <span className="text-[11px] font-mono text-text-muted">{jobId}</span>
          </div>
          <button className="p-1 text-text-muted hover:text-text-primary" onClick={onClose}>
            <X size={16} />
          </button>
        </div>

        <div className="flex-1 min-h-0 overflow-y-auto p-5 space-y-4">
          {loading ? (
            <div className="flex items-center justify-center py-12 text-text-muted">
              <Loader2 size={20} className="animate-spin" />
            </div>
          ) : job ? (
            <>
              <div className="space-y-2">
                <Field label="状态" value={job.task_status || job.status} />
                <Field label="描述" value={job.description} />
                {job.task_error && <Field label="错误" value={job.task_error} danger />}
              </div>

              {job.task_result !== undefined && job.task_result !== null && (
                <div>
                  <div className="text-xs text-text-secondary mb-1.5">执行结果</div>
                  <pre className="text-xs font-mono whitespace-pre-wrap break-words bg-bg-secondary border border-border-secondary rounded-lg p-3 max-h-64 overflow-auto">
                    {typeof job.task_result === 'string'
                      ? job.task_result
                      : JSON.stringify(job.task_result, null, 2)}
                  </pre>
                </div>
              )}

              <div>
                <div className="text-xs text-text-secondary mb-1.5">事件流（SSE）</div>
                <div
                  ref={eventBoxRef}
                  className="text-[11px] font-mono bg-bg-secondary border border-border-secondary rounded-lg p-3 max-h-72 overflow-auto space-y-1"
                >
                  {events.length === 0 ? (
                    <span className="text-text-muted">(等待事件…)</span>
                  ) : (
                    events.map((e, i) => (
                      <div key={i} className="text-text-secondary">
                        <span className="text-accent">{e.type || 'event'}</span>{' '}
                        {e.payload !== undefined ? (
                          <span>{JSON.stringify(e.payload)}</span>
                        ) : e.raw ? (
                          <span>{e.raw}</span>
                        ) : null}
                      </div>
                    ))
                  )}
                </div>
              </div>
            </>
          ) : (
            <div className="text-sm text-text-muted text-center py-8">任务不存在或已被删除</div>
          )}
        </div>
      </div>
    </div>
  );
}

function Field({ label, value, danger }: { label: string; value: string; danger?: boolean }) {
  return (
    <div className="flex gap-3">
      <div className="text-xs text-text-muted w-16 shrink-0 pt-0.5">{label}</div>
      <div className={`text-sm flex-1 break-words ${danger ? 'text-danger' : 'text-text-primary'}`}>{value}</div>
    </div>
  );
}
