import { useCallback, useEffect, useRef, useState } from "react";
import type { FC } from "react";
import { traceApi } from "../../api/traceApi";
import styles from "./AgentControlPanel.module.css";

interface LogLine {
    time: string;
    type: "system" | "agent" | "tool" | "result" | "error" | "warn";
    text: string;
}

interface AgentControlPanelProps {
    traceId: string | null;
    onClose: () => void;
    onMessageInserted?: () => void;
}

interface BackendLogEntry {
    timestamp: string;
    level: string;
    name: string;
    message: string;
}

// WebSocket trace 事件类型
interface TraceEvent {
    event?: string;
    event_type?: string;
    type?: string;
    role?: string;
    content?: unknown;
    status?: string;
    trace_status?: string;
    is_running?: boolean;
    error_message?: string;
    total_cost?: number;
    total_messages?: number;
}

function formatContent(content: unknown): string {
    if (typeof content === "string") return content.slice(0, 200);
    if (typeof content === "object" && content !== null) {
        const c = content as Record<string, unknown>;
        const text = c.text as string | undefined;
        const toolCalls = c.tool_calls as Array<{ function?: { name?: string } }> | undefined;
        const toolName = c.tool_name as string | undefined;
        if (text && !toolCalls) return text.slice(0, 200);
        if (toolCalls?.length) {
            return toolCalls.map((tc) => tc.function?.name || "tool").join(", ");
        }
        if (toolName) return toolName;
        return JSON.stringify(content).slice(0, 200);
    }
    return String(content ?? "");
}

function now() {
    return new Date().toLocaleTimeString("zh-CN", { hour12: false });
}

const API_BASE =
    (typeof window !== "undefined"
        ? (window as unknown as { CONFIG?: { API_BASE_URL?: string } }).CONFIG?.API_BASE_URL
        : undefined) ||
    (typeof import.meta !== "undefined" && import.meta.env?.VITE_API_BASE_URL
        ? import.meta.env.VITE_API_BASE_URL
        : typeof window !== "undefined"
            ? `${window.location.protocol}//${window.location.hostname}:8000`
            : "http://localhost:8000");

export const AgentControlPanel: FC<AgentControlPanelProps> = ({
    traceId,
    onClose,
    onMessageInserted,
}) => {
    const [logs, setLogs] = useState<LogLine[]>([]);
    const [backendLogs, setBackendLogs] = useState<BackendLogEntry[]>([]);
    const [activeTab, setActiveTab] = useState<"trace" | "backend">("trace");
    const [traceStatus, setTraceStatus] = useState<string>("unknown");
    const [totalCost, setTotalCost] = useState<number>(0);
    const [totalSteps, setTotalSteps] = useState<number>(0);
    const [wsConnected, setWsConnected] = useState(false);
    const [logWsConnected, setLogWsConnected] = useState(false);
    const [isStatusLoaded, setIsStatusLoaded] = useState(false);  // 状态已确认，防止未知状态下误操作
    const [isPausing, setIsPausing] = useState(false);
    const [isResuming, setIsResuming] = useState(false);
    const [interventionText, setInterventionText] = useState("");
    const [isSubmitting, setIsSubmitting] = useState(false);
    const [isReflecting, setIsReflecting] = useState(false);
    const [isCompacting, setIsCompacting] = useState(false);
    const logsEndRef = useRef<HTMLDivElement>(null);
    const backendLogsEndRef = useRef<HTMLDivElement>(null);
    const wsRef = useRef<WebSocket | null>(null);
    const logWsRef = useRef<WebSocket | null>(null);
    const autoScrollRef = useRef(true);
    const logContainerRef = useRef<HTMLDivElement>(null);

    const appendLog = useCallback((line: LogLine) => {
        setLogs((prev) => [...prev.slice(-500), line]); // 最多保留500条
    }, []);

    // WebSocket 监听 trace 事件
    useEffect(() => {
        if (!traceId) return;
        const wsBase = API_BASE.replace(/^http(s?):\/\//, "ws$1://").replace(/\/+$/, "");
        const url = `${wsBase}/api/traces/${traceId}/watch?since_event_id=0`;
        const ws = new WebSocket(url);
        wsRef.current = ws;

        ws.onopen = () => {
            setWsConnected(true);
            appendLog({ time: now(), type: "system", text: "引擎已就绪，监听实时事件..." });
        };

        ws.onmessage = (event) => {
            try {
                const data: TraceEvent = JSON.parse(event.data);

                // 连接成功事件：竅即根据服务端返回的真实状态初始化按鈕
                if (data.event === "connected") {
                    const realStatus = data.trace_status || (data.is_running ? "running" : "unknown");
                    setTraceStatus(realStatus);
                    setIsStatusLoaded(true);
                    appendLog({ time: now(), type: "system", text: `当前状态: ${realStatus.toUpperCase()}` });
                    return;
                }

                // 处理 trace 状态变化
                if (data.status) {
                    setTraceStatus(data.status);
                    setIsStatusLoaded(true);
                    if (typeof data.total_cost === "number") setTotalCost(data.total_cost);
                    if (typeof data.total_messages === "number") setTotalSteps(data.total_messages);

                    if (data.status === "running") {
                        appendLog({ time: now(), type: "system", text: "执行已恢复运行。" });
                    } else if (data.status === "stopped") {
                        appendLog({ time: now(), type: "warn", text: "执行已挂起，等待人工干预..." });
                    } else if (data.status === "completed") {
                        appendLog({ time: now(), type: "system", text: "任务已完成 ✓" });
                    } else if (data.status === "failed") {
                        appendLog({ time: now(), type: "error", text: `执行失败: ${data.error_message || "未知错误"}` });
                    }
                    return;
                }

                // 处理消息事件
                const role = data.role;
                if (!role) return;

                if (role === "assistant") {
                    const contentStr = formatContent(data.content);
                    const isToolCall =
                        typeof data.content === "object" &&
                        data.content !== null &&
                        Array.isArray((data.content as Record<string, unknown>).tool_calls);
                    if (isToolCall) {
                        appendLog({ time: now(), type: "tool", text: `调用工具: ${contentStr}` });
                    } else if (contentStr) {
                        appendLog({ time: now(), type: "agent", text: contentStr });
                    }
                } else if (role === "tool") {
                    const contentStr = formatContent(data.content);
                    if (contentStr) {
                        appendLog({ time: now(), type: "result", text: contentStr });
                    }
                } else if (role === "system") {
                    const contentStr = formatContent(data.content);
                    if (contentStr) {
                        appendLog({ time: now(), type: "system", text: contentStr.slice(0, 80) + "..." });
                    }
                }
            } catch {
                // ignore parse errors
            }
        };

        ws.onerror = () => setWsConnected(false);
        ws.onclose = () => {
            setWsConnected(false);
        };

        // 初始加载 trace 状态（作为备用手段，主要依靠 connected 事件）
        traceApi.fetchTraceDetail(traceId).then((detail) => {
            // 仅在状态未被 WebSocket 初始化时才覆盖
            setTraceStatus(s => s === "unknown" ? (detail.status || "unknown") : s);
            setIsStatusLoaded(true);
            setTotalCost(detail.total_cost ?? 0);
            setTotalSteps(detail.total_messages ?? 0);
        }).catch(() => { });

        // --- 新增：全局后端日志监听 ---
        const logWs = new WebSocket(`${wsBase}/api/logs/watch`);
        logWsRef.current = logWs;

        logWs.onopen = () => setLogWsConnected(true);
        logWs.onmessage = (event) => {
            try {
                const entry: BackendLogEntry = JSON.parse(event.data);
                setBackendLogs(prev => [...prev.slice(-1000), entry]);
            } catch (e) { /* ignore */ }
        };
        logWs.onclose = () => setLogWsConnected(false);
        logWs.onerror = () => setLogWsConnected(false);

        return () => {
            ws.close();
            logWs.close();
        };
    }, [traceId, appendLog]);

    // 自动滚动 (逻辑复用)
    useEffect(() => {
        if (!autoScrollRef.current) return;
        if (activeTab === "trace" && logsEndRef.current) {
            logsEndRef.current.scrollIntoView({ behavior: "smooth" });
        } else if (activeTab === "backend" && backendLogsEndRef.current) {
            backendLogsEndRef.current.scrollIntoView({ behavior: "smooth" });
        }
    }, [logs, backendLogs, activeTab]);

    const handleScroll = () => {
        const el = logContainerRef.current;
        if (!el) return;
        const isAtBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 40;
        autoScrollRef.current = isAtBottom;
    };

    // 轮询等待 trace 停止
    const waitUntilStopped = async (id: string, maxMs = 30000): Promise<boolean> => {
        const interval = 300;
        let waited = 0;
        while (waited < maxMs) {
            try {
                const detail = await traceApi.fetchTraceDetail(id);
                if (detail.status !== "running") return true;
            } catch {
                return true;
            }
            await new Promise((r) => setTimeout(r, interval));
            waited += interval;
        }
        return false;
    };

    const handlePause = async () => {
        if (!traceId) return;
        setIsPausing(true);
        try {
            await traceApi.stopTrace(traceId);
            appendLog({ time: now(), type: "warn", text: "已发送暂停指令，等待当前步骤完成..." });
        } catch {
            appendLog({ time: now(), type: "error", text: "暂停失败" });
        } finally {
            setIsPausing(false);
        }
    };

    const handleResume = async () => {
        if (!traceId) return;
        setIsResuming(true);
        appendLog({ time: now(), type: "system", text: "等待 Agent 完全停止后继续..." });
        try {
            const stopped = await waitUntilStopped(traceId);
            if (!stopped) {
                appendLog({ time: now(), type: "error", text: "Agent 仍在处理中，请稍候再试" });
                return;
            }
            await traceApi.runTrace(traceId, { messages: [] });
            appendLog({ time: now(), type: "system", text: "已发送继续指令。" });
        } catch {
            appendLog({ time: now(), type: "error", text: "继续失败" });
        } finally {
            setIsResuming(false);
        }
    };

    const handleStop = async () => {
        if (!traceId) return;
        if (!confirm("确认结束任务？Trace 将保持 stopped 状态不再运行。")) return;
        try {
            await traceApi.stopTrace(traceId);
            appendLog({ time: now(), type: "error", text: "任务已结束。" });
        } catch {
            appendLog({ time: now(), type: "error", text: "结束失败" });
        }
    };

    const handleReflect = async () => {
        if (!traceId) return;
        setIsReflecting(true);
        appendLog({ time: now(), type: "system", text: "正在生成反思与经验提取..." });
        try {
            const res = await traceApi.reflectTrace(traceId);
            // 这里 res 包含 { reflection: string }，我们截取一部分展示在日志里
            const snippet = res.reflection.length > 100 ? res.reflection.slice(0, 100) + "..." : res.reflection;
            appendLog({ time: now(), type: "system", text: `反思完成：\n"${snippet}"` });
            appendLog({ time: now(), type: "system", text: "经验已作为 [strategy] 标签存入原子知识库 ✓" });
        } catch (error) {
            console.error("Reflection failed:", error);
            appendLog({ time: now(), type: "error", text: "反思失败" });
        } finally {
            setIsReflecting(false);
        }
    };

    const handleCompact = async () => {
        if (!traceId) return;
        setIsCompacting(true);
        appendLog({ time: now(), type: "system", text: "正在执行上下文压缩 (Compact)..." });
        try {
            const res = await traceApi.compactTrace(traceId);
            appendLog({ time: now(), type: "system", text: `压缩成功: ${res.previous_count} -> ${res.new_count} 条消息。` });
        } catch (error) {
            console.error("Compaction failed:", error);
            appendLog({ time: now(), type: "error", text: "上下文压缩失败" });
        } finally {
            setIsCompacting(false);
        }
    };

    const handleSubmitIntervention = async () => {
        const text = interventionText.trim();
        if (!text || !traceId) return;
        setIsSubmitting(true);
        appendLog({ time: now(), type: "system", text: `发送干预消息: "${text.slice(0, 60)}"` });
        try {
            const stopped = await waitUntilStopped(traceId);
            if (!stopped) {
                appendLog({ time: now(), type: "error", text: "Agent 仍在处理中，请先暂停后再插入" });
                return;
            }
            await traceApi.runTrace(traceId, {
                messages: [{ role: "user", content: text }],
            });
            setInterventionText("");
            onMessageInserted?.();
            appendLog({ time: now(), type: "system", text: "干预消息已插入，Agent 继续执行。" });
        } catch {
            appendLog({ time: now(), type: "error", text: "插入干预消息失败" });
        } finally {
            setIsSubmitting(false);
        }
    };

    const isRunning = traceStatus === "running";
    const isStopped = traceStatus === "stopped" || traceStatus === "completed" || traceStatus === "failed";

    const statusLabel: Record<string, string> = {
        running: "RUNNING",
        stopped: "PAUSED",
        completed: "COMPLETED",
        failed: "FAILED",
        unknown: "UNKNOWN",
    };

    return (
        <div className={styles.overlay} onClick={(e) => e.target === e.currentTarget && onClose()}>
            <div className={styles.panel}>
                {/* === 头部 === */}
                <div className={styles.header}>
                    <div className={styles.headerLeft}>
                        <span className={`${styles.statusDot} ${styles[traceStatus] || styles.unknown}`} />
                        <span className={styles.title}>Agent 控制中心</span>
                        <span className={`${styles.statusBadge} ${styles[`badge_${traceStatus}`] || ""}`}>
                            {statusLabel[traceStatus] || (traceStatus || "unknown").toUpperCase()}
                        </span>
                    </div>
                    <div className={styles.headerRight}>
                        {isRunning ? (
                            <button
                                className={`${styles.btn} ${styles.btnPause}`}
                                onClick={handlePause}
                                disabled={isPausing || !isStatusLoaded}
                            >
                                ⏸ {isPausing ? "暂停中..." : "暂停执行"}
                            </button>
                        ) : (
                            <button
                                className={`${styles.btn} ${styles.btnResume}`}
                                onClick={handleResume}
                                disabled={isResuming || !isStatusLoaded}
                            >
                                ▶ {isResuming ? "等待中..." : "继续执行"}
                            </button>
                        )}
                        {!isStatusLoaded && (
                            <span style={{ fontSize: 12, color: "#94a3b8", marginRight: 4 }}>状态加载中...</span>
                        )}
                        <button
                            className={`${styles.btn} ${styles.btnStop}`}
                            onClick={handleStop}
                            disabled={isStopped && traceStatus !== "stopped"}
                        >
                            ■ 结束任务
                        </button>
                        <button className={styles.closeBtn} onClick={onClose}>✕</button>
                    </div>
                </div>

                {/* === 控制台日志区 === */}
                <div className={styles.logSection}>
                    <div className={styles.logHeader}>
                        <div className={styles.tabs}>
                            <button
                                className={`${styles.tabItem} ${activeTab === "trace" ? styles.tabActive : ""}`}
                                onClick={() => setActiveTab("trace")}
                            >
                                轨迹 (TRACE)
                            </button>
                            <button
                                className={`${styles.tabItem} ${activeTab === "backend" ? styles.tabActive : ""}`}
                                onClick={() => setActiveTab("backend")}
                            >
                                后端日志
                                <span className={`${styles.dot} ${logWsConnected ? styles.dotOk : styles.dotOff}`} />
                            </button>
                        </div>
                        {traceId && activeTab === "trace" && (
                            <span className={styles.traceIdLabel}>
                                Trace ID: {traceId.slice(0, 8)}...
                            </span>
                        )}
                    </div>
                    <div
                        className={`${styles.logContainer} ${activeTab === "backend" ? styles.logContainerBackend : ""}`}
                        ref={logContainerRef}
                        onScroll={handleScroll}
                    >
                        {activeTab === "trace" ? (
                            logs.length === 0 ? (
                                <div className={styles.logEmpty}>等待事件...</div>
                            ) : (
                                logs.map((log, i) => (
                                    <div key={i} className={`${styles.logLine} ${styles[`log_${log.type}`]}`}>
                                        <span className={styles.logTime}>[{log.time}]</span>
                                        <span className={styles.logTag}>[{(log.type || "system").toUpperCase()}]</span>
                                        <span className={styles.logText}>{log.text}</span>
                                    </div>
                                ))
                            )
                        ) : (
                            backendLogs.length === 0 ? (
                                <div className={styles.logEmpty}>等待日志输出...</div>
                            ) : (
                                backendLogs.map((log, i) => (
                                    <div key={i} className={`${styles.backendLogLine} ${styles[`level_${log.level}`]}`}>
                                        <span className={styles.logTime}>
                                            {new Date(log.timestamp).toLocaleTimeString()}
                                        </span>
                                        <span className={styles.logLevel}>[{log.level}]</span>
                                        <span className={styles.logName}>{log.name}:</span>
                                        <span className={styles.logText}>{log.message}</span>
                                    </div>
                                ))
                            )
                        )}
                        {activeTab === "trace" ? (
                            <div ref={logsEndRef} />
                        ) : (
                            <div ref={backendLogsEndRef} />
                        )}
                    </div>
                </div>

                {/* === 操作按钮区 === */}
                <div className={styles.actionSection}>
                    <button
                        className={`${styles.actionCard} ${isReflecting ? styles.actionCardActive : ""}`}
                        onClick={handleReflect}
                        disabled={isReflecting || isRunning}
                    >
                        <span className={styles.actionIcon}>🧠</span>
                        <span className={styles.actionLabel}>{isReflecting ? "反思中..." : "触发反思"}</span>
                    </button>
                    <button
                        className={`${styles.actionCard} ${isCompacting ? styles.actionCardActive : ""}`}
                        onClick={handleCompact}
                        disabled={isCompacting || isRunning}
                    >
                        <span className={styles.actionIcon}>⊞</span>
                        <span className={styles.actionLabel}>{isCompacting ? "压缩中..." : "压缩上下文"}</span>
                    </button>
                </div>

                {/* === 干预消息输入区 === */}
                <div className={styles.interventionSection}>
                    <textarea
                        className={styles.interventionInput}
                        placeholder="插入人工干预消息..."
                        value={interventionText}
                        onChange={(e) => setInterventionText(e.target.value)}
                        rows={3}
                        onKeyDown={(e) => {
                            if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
                                e.preventDefault();
                                void handleSubmitIntervention();
                            }
                        }}
                    />
                    <button
                        className={styles.submitBtn}
                        onClick={handleSubmitIntervention}
                        disabled={isSubmitting || !interventionText.trim()}
                    >
                        {isSubmitting ? "提交中..." : "提交指令"}
                    </button>
                </div>

                {/* === 底部状态栏 === */}
                <div className={styles.footer}>
                    <span>💰 Cost: ${totalCost.toFixed(4)}</span>
                    <span>📋 Steps: {totalSteps}</span>
                    <span className={`${styles.wsStatus} ${wsConnected ? styles.wsOk : styles.wsOff}`}>
                        {wsConnected ? "● Backend Connected" : "○ Disconnected"}
                    </span>
                </div>
            </div>
        </div>
    );
};
