"use client";

import { useState, useEffect } from "react";
import * as Dialog from "@radix-ui/react-dialog";
import { api } from "@/lib/api";
import { useCanvasStore } from "@/store/canvas";
import { type ActivityEntry } from "@/types/activity";
import { useWorkspaceName } from "@/hooks/useWorkspaceName";

interface Props {
  open: boolean;
  workspaceId: string;
  onClose: () => void;
}

/** Exported for unit testing — see ConversationTraceModal.test.ts */
export function extractMessageText(body: Record<string, unknown> | null): string {
  if (!body) return "";
  try {
    // Simple task format from MCP server: {task: "..."}
    if (body.task && typeof body.task === "string") return body.task;

    // Request: params.message.parts[].text
    const params = body.params as Record<string, unknown> | undefined;
    const message = params?.message as Record<string, unknown> | undefined;
    const parts = (message?.parts || []) as Array<Record<string, unknown>>;
    const text = parts
      .map((p) => (p.text as string) || "")
      .filter(Boolean)
      .join("\n");
    if (text) return text;

    // Response: result.parts[].text or result.parts[].root.text
    // Use the first part that has a direct text field; within that part,
    // prefer direct text over root.text. Subsequent parts' root.text fields
    // are ignored when a direct text exists in an earlier part.
    const result = body.result as Record<string, unknown> | undefined;
    const rParts = (result?.parts || []) as Array<Record<string, unknown>>;
    const firstPartWithText = rParts.find(
      (p) => typeof p.text === "string" && (p.text as string) !== ""
    );
    if (firstPartWithText) {
      return firstPartWithText.text as string;
    }
    // No direct text found; use root.text from the first part (if present).
    const firstPart = rParts[0];
    if (firstPart) {
      const root = firstPart.root as Record<string, unknown> | undefined;
      if (typeof root?.text === "string" && root.text !== "") {
        return root.text as string;
      }
    }

    if (typeof body.result === "string") return body.result;
  } catch { /* ignore */ }
  return "";
}

export function ConversationTraceModal({ open, workspaceId: _workspaceId, onClose }: Props) {
  const [entries, setEntries] = useState<ActivityEntry[]>([]);
  const [loading, setLoading] = useState(false);
  const nodes = useCanvasStore((s) => s.nodes);
  const resolveName = useWorkspaceName();

  // Fetch activities from all workspaces (including hidden children) and merge
  useEffect(() => {
    if (!open) return;
    setLoading(true);

    const wsIds = nodes.map((n) => n.id);

    Promise.all(
      wsIds.map((id) =>
        api
          .get<ActivityEntry[]>(`/workspaces/${id}/activity?limit=200`)
          .catch(() => [] as ActivityEntry[])
      )
    ).then((results) => {
      // Merge, deduplicate by ID, sort chronologically (oldest first)
      const seen = new Set<string>();
      const all: ActivityEntry[] = [];
      for (const batch of results) {
        for (const entry of batch) {
          if (!seen.has(entry.id)) {
            seen.add(entry.id);
            all.push(entry);
          }
        }
      }
      all.sort((a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime());
      setEntries(all);
      setLoading(false);
    });
  }, [open, nodes]);

  const isA2A = (e: ActivityEntry) =>
    e.activity_type === "a2a_receive" || e.activity_type === "a2a_send";

  return (
    <Dialog.Root open={open} onOpenChange={(o) => { if (!o) onClose(); }}>
      <Dialog.Portal>
        {/* Overlay replaces the old manual backdrop div */}
        <Dialog.Overlay className="fixed inset-0 z-[59] bg-black/70 backdrop-blur-sm" />

        {/* Content wraps the entire centred modal panel */}
        <Dialog.Content
          className="fixed inset-0 z-[60] flex items-center justify-center p-4"
          aria-label="Conversation trace"
        >
          {/* Modal panel */}
          <div className="relative bg-surface-sunken border border-line rounded-xl shadow-2xl max-w-[700px] w-full max-h-[85vh] flex flex-col overflow-hidden">
            {/* Header */}
            <div className="flex items-center justify-between px-5 py-3 border-b border-line">
              <div>
                <Dialog.Title className="text-sm font-semibold text-ink">
                  Conversation Trace
                </Dialog.Title>
                <p className="text-[10px] text-ink-mid mt-0.5">
                  {entries.length} events across all workspaces
                </p>
              </div>
              <Dialog.Close asChild>
                <button
                  type="button"
                  aria-label="Close conversation trace"
                  className="text-ink-mid hover:text-ink-mid text-lg px-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1 focus-visible:ring-offset-surface"
                >
                  ✕
                </button>
              </Dialog.Close>
            </div>

            {/* Timeline */}
            <div className="flex-1 overflow-y-auto px-5 py-4">
              {loading && (
                <div role="status" aria-live="polite" className="text-xs text-ink-mid text-center py-8">
                  Loading trace from all workspaces...
                </div>
              )}

              {!loading && entries.length === 0 && (
                <div role="status" aria-live="polite" className="text-xs text-ink-mid text-center py-8">
                  No activity found
                </div>
              )}

              <div className="space-y-1">
                {entries.map((entry) => {
                  const time = new Date(entry.created_at).toLocaleTimeString();
                  const wsName = resolveName(entry.workspace_id);
                  const sourceName = resolveName(entry.source_id);
                  const targetName = resolveName(entry.target_id);
                  const requestText = extractMessageText(entry.request_body);
                  const responseText = extractMessageText(entry.response_body);
                  const isError = entry.status === "error";
                  const isSend = entry.activity_type === "a2a_send";
                  const isReceive = entry.activity_type === "a2a_receive";

                  return (
                    <div key={entry.id} className="group">
                      {/* Event header */}
                      <div className="flex items-start gap-3">
                        {/* Timeline dot + line */}
                        <div className="flex flex-col items-center pt-1.5">
                          <div
                            className={`w-2.5 h-2.5 rounded-full shrink-0 ${
                              isError
                                ? "bg-red-500"
                                : isSend
                                ? "bg-cyan-500"
                                : isReceive
                                ? "bg-accent"
                                : "bg-surface-card"
                            }`}
                          />
                          <div className="w-px flex-1 bg-surface-card min-h-[8px]" />
                        </div>

                        {/* Content */}
                        <div className="flex-1 pb-3 min-w-0">
                          <div className="flex items-center gap-2 flex-wrap">
                            <span className="text-[9px] text-ink-mid font-mono">
                              {time}
                            </span>
                            <span
                              className={`text-[9px] font-semibold px-1.5 py-0.5 rounded ${
                                isError
                                  ? "bg-red-950/50 text-bad"
                                  : isSend
                                  ? "bg-cyan-950 text-cyan-300"
                                  : isReceive
                                  ? "bg-blue-950/50 text-accent"
                                  : "bg-surface-card text-ink-mid"
                              }`}
                            >
                              {isSend
                                ? "SEND"
                                : isReceive
                                ? "RECEIVE"
                                : entry.activity_type.toUpperCase()}
                            </span>
                            {entry.duration_ms != null && entry.duration_ms > 0 && (
                              <span className="text-[9px] text-ink-mid">
                                {entry.duration_ms > 1000
                                  ? `${Math.round(entry.duration_ms / 1000)}s`
                                  : `${entry.duration_ms}ms`}
                              </span>
                            )}
                          </div>

                          {/* Flow */}
                          {isA2A(entry) && (
                            <div className="text-[11px] mt-1">
                              {isSend ? (
                                <span>
                                  <span className="text-cyan-400 font-medium">
                                    {sourceName || wsName}
                                  </span>
                                  <span className="text-ink-mid"> → </span>
                                  <span className="text-accent font-medium">
                                    {targetName}
                                  </span>
                                </span>
                              ) : (
                                <span>
                                  <span className="text-accent font-medium">
                                    {targetName || wsName}
                                  </span>
                                  {sourceName && (
                                    <>
                                      <span className="text-ink-mid">
                                        {" "}← {" "}
                                      </span>
                                      <span className="text-cyan-400 font-medium">
                                        {sourceName}
                                      </span>
                                    </>
                                  )}
                                </span>
                              )}
                            </div>
                          )}

                          {/* Summary */}
                          {entry.summary && !isA2A(entry) && (
                            <div className="text-[10px] text-ink-mid mt-1">
                              <span className="text-ink-mid font-medium">{wsName}:</span>{" "}
                              {entry.summary}
                            </div>
                          )}

                          {/* Error */}
                          {isError && entry.error_detail && (
                            <div className="text-[10px] text-bad mt-1 truncate">
                              {entry.error_detail.slice(0, 200)}
                            </div>
                          )}

                          {/* Message content — show request and/or response */}
                          {requestText && (
                            <div className="mt-1.5 bg-surface/60 border border-line/50 rounded-lg px-3 py-2 max-h-32 overflow-y-auto">
                              <div className="text-[8px] text-ink-mid uppercase mb-1">
                                {isSend ? "Task" : "Request"}
                              </div>
                              <div className="text-[10px] text-ink-mid whitespace-pre-wrap break-words leading-relaxed">
                                {requestText.slice(0, 2000)}
                                {requestText.length > 2000 && (
                                  <span className="text-ink-mid"> ...({requestText.length} chars)</span>
                                )}
                              </div>
                            </div>
                          )}
                          {responseText && (
                            <div className="mt-1 bg-surface/60 border border-emerald-900/30 rounded-lg px-3 py-2 max-h-32 overflow-y-auto">
                              <div className="text-[8px] text-good uppercase mb-1">Response</div>
                              <div className="text-[10px] text-ink-mid whitespace-pre-wrap break-words leading-relaxed">
                                {responseText.slice(0, 2000)}
                                {responseText.length > 2000 && (
                                  <span className="text-ink-mid"> ...({responseText.length} chars)</span>
                                )}
                              </div>
                            </div>
                          )}
                        </div>
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>

            {/* Footer */}
            <div className="px-5 py-3 border-t border-line bg-surface/50 flex justify-end">
              <Dialog.Close asChild>
                <button
                  type="button"
                  className="px-4 py-1.5 text-[12px] bg-surface-card hover:bg-surface-card text-ink-mid rounded-lg transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1 focus-visible:ring-offset-surface"
                >
                  Close
                </button>
              </Dialog.Close>
            </div>
          </div>
        </Dialog.Content>
      </Dialog.Portal>
    </Dialog.Root>
  );
}
