/**
 * WorkflowResultRenderer - Human-first result display for workflow execution outputs.
 *
 * Rendering strategy (spec 0005):
 *  - AgentStyleResult  (object with a "response" key) → answer-first card + usage + transcript
 *  - Everything else   → generic structured inspector with collapsible raw JSON
 */

import { useState } from "react";
import Markdown from "react-markdown";
import remarkGfm from "remark-gfm";
import {
  ArrowDown,
  ArrowUp,
  Bug,
  Check,
  ChevronDown,
  ChevronRight,
  Clock,
  Copy,
  DollarSign,
  Info,
  MessageSquare,
} from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";

// ── Types ──────────────────────────────────────────────────────────────────

interface AgentStyleResult {
  response: string | null | undefined;
  messages?: Record<string, any>[];
  usage?: Record<string, any> | null;
  metadata?: Record<string, any> | null;
}

interface WorkflowResultRendererProps {
  result: any;
}

// ── Shape Detection ────────────────────────────────────────────────────────

function isAgentStyleResult(result: any): result is AgentStyleResult {
  return (
    result !== null &&
    result !== undefined &&
    typeof result === "object" &&
    !Array.isArray(result) &&
    "response" in result
  );
}

// ── Collapsible Section ────────────────────────────────────────────────────

function CollapsibleSection({
  title,
  icon,
  defaultOpen = false,
  badge,
  children,
}: {
  title: string;
  icon: React.ReactNode;
  defaultOpen?: boolean;
  badge?: string;
  children: React.ReactNode;
}) {
  const [isOpen, setIsOpen] = useState(defaultOpen);

  return (
    <div className="border rounded-lg overflow-hidden">
      <button
        onClick={() => setIsOpen(!isOpen)}
        className="w-full flex items-center justify-between p-3 text-sm font-medium hover:bg-muted/50 transition-colors text-left"
      >
        <div className="flex items-center gap-2">
          {icon}
          <span>{title}</span>
          {badge && (
            <Badge variant="secondary" className="text-xs px-1.5 py-0">
              {badge}
            </Badge>
          )}
        </div>
        {isOpen ? (
          <ChevronDown className="h-4 w-4 text-muted-foreground flex-shrink-0" />
        ) : (
          <ChevronRight className="h-4 w-4 text-muted-foreground flex-shrink-0" />
        )}
      </button>
      {isOpen && <div className="border-t p-3">{children}</div>}
    </div>
  );
}

// ── Markdown Content ───────────────────────────────────────────────────────

function MarkdownContent({ content }: { content: string }) {
  return (
    <div className="text-sm leading-relaxed">
      <Markdown
        remarkPlugins={[remarkGfm]}
        components={{
          h1: ({ ...props }) => (
            <h1 className="text-xl font-bold mb-3 mt-4 first:mt-0" {...props} />
          ),
          h2: ({ ...props }) => (
            <h2 className="text-lg font-semibold mb-2 mt-4 first:mt-0" {...props} />
          ),
          h3: ({ ...props }) => (
            <h3 className="text-base font-semibold mb-2 mt-3 first:mt-0" {...props} />
          ),
          p: ({ ...props }) => <p className="mb-3 last:mb-0" {...props} />,
          ul: ({ ...props }) => (
            <ul className="list-disc list-inside mb-3 space-y-1" {...props} />
          ),
          ol: ({ ...props }) => (
            <ol className="list-decimal list-inside mb-3 space-y-1" {...props} />
          ),
          li: ({ ...props }) => <li className="ml-2" {...props} />,
          strong: ({ ...props }) => <strong className="font-semibold" {...props} />,
          em: ({ ...props }) => <em className="italic" {...props} />,
          blockquote: ({ ...props }) => (
            <blockquote
              className="border-l-4 border-border pl-4 italic text-muted-foreground mb-3"
              {...props}
            />
          ),
          hr: () => <hr className="my-4 border-border" />,
          // Inline code vs block code: block code fences get a language-* className
          code: ({ className, children, ...props }: any) => {
            const isBlock = Boolean(className?.startsWith("language-"));
            return isBlock ? (
              <code
                className="block bg-muted p-3 rounded text-xs font-mono overflow-x-auto whitespace-pre"
                {...props}
              >
                {children}
              </code>
            ) : (
              <code
                className="bg-muted px-1.5 py-0.5 rounded text-xs font-mono"
                {...props}
              >
                {children}
              </code>
            );
          },
          pre: ({ ...props }) => (
            <pre className="mb-3 overflow-x-auto" {...props} />
          ),
          table: ({ ...props }) => (
            <div className="overflow-x-auto mb-3">
              <table className="w-full text-xs border-collapse" {...props} />
            </div>
          ),
          th: ({ ...props }) => (
            <th
              className="border border-border px-3 py-1.5 bg-muted font-semibold text-left"
              {...props}
            />
          ),
          td: ({ ...props }) => (
            <td className="border border-border px-3 py-1.5" {...props} />
          ),
          a: ({ ...props }) => (
            <a
              className="text-blue-600 underline hover:text-blue-800"
              target="_blank"
              rel="noopener noreferrer"
              {...props}
            />
          ),
        }}
      >
        {content}
      </Markdown>
    </div>
  );
}

// ── Copy Button ────────────────────────────────────────────────────────────

function CopyButton({ text }: { text: string }) {
  const [copied, setCopied] = useState(false);

  const handleCopy = async () => {
    try {
      await navigator.clipboard.writeText(text);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch {
      // Clipboard API unavailable (non-secure context); silent fail
    }
  };

  return (
    <Button
      variant="ghost"
      size="sm"
      onClick={handleCopy}
      className="gap-1.5 h-7 px-2 text-xs"
    >
      {copied ? (
        <>
          <Check className="h-3.5 w-3.5 text-green-600" />
          Copied
        </>
      ) : (
        <>
          <Copy className="h-3.5 w-3.5" />
          Copy
        </>
      )}
    </Button>
  );
}

// ── Usage Counters ─────────────────────────────────────────────────────────

function UsageCounters({ usage }: { usage: Record<string, any> }) {
  const tokensIn: number = usage.tokens_input ?? 0;
  const tokensOut: number = usage.tokens_output ?? 0;
  const durationMs: number | undefined = usage.duration_ms;
  const costEstimate: number | undefined = usage.cost_estimate;
  const hasTopLevel =
    tokensIn > 0 || tokensOut > 0 || durationMs !== undefined;

  if (!hasTopLevel) return null;

  const secondaryFields = [
    { label: "LLM calls", value: usage.llm_calls },
    { label: "Tool calls", value: usage.tool_calls },
    { label: "Memory ops", value: usage.memory_operations },
  ].filter((f) => f.value !== undefined && f.value !== null);

  return (
    <div className="space-y-1.5">
      <div className="flex items-center gap-2 flex-wrap">
        {(tokensIn > 0 || tokensOut > 0) && (
          <Badge variant="outline" className="text-xs gap-1">
            <ArrowUp className="h-3 w-3" />
            {tokensIn.toLocaleString()}
            <ArrowDown className="h-3 w-3" />
            {tokensOut.toLocaleString()}
          </Badge>
        )}
        {durationMs !== undefined && (
          <Badge variant="outline" className="text-xs gap-1">
            <Clock className="h-3 w-3" />
            {durationMs < 1000
              ? `${durationMs}ms`
              : `${(durationMs / 1000).toFixed(1)}s`}
          </Badge>
        )}
        {costEstimate !== undefined && costEstimate > 0 && (
          <Badge variant="outline" className="text-xs gap-1">
            <DollarSign className="h-3 w-3" />
            {costEstimate < 0.01 ? "<$0.01" : `$${costEstimate.toFixed(3)}`}
          </Badge>
        )}
      </div>
      {secondaryFields.length > 0 && (
        <div className="flex items-center gap-3 flex-wrap">
          {secondaryFields.map((f) => (
            <span key={f.label} className="text-xs text-muted-foreground">
              {f.label}:{" "}
              <span className="font-medium text-foreground">{f.value}</span>
            </span>
          ))}
        </div>
      )}
    </div>
  );
}

// ── Message Transcript ─────────────────────────────────────────────────────

function MessageTranscript({
  messages,
}: {
  messages: Record<string, any>[];
}) {
  if (messages.length === 0) {
    return (
      <p className="text-xs text-muted-foreground">No messages recorded.</p>
    );
  }

  return (
    <div className="space-y-2">
      {messages.map((msg, idx) => {
        const role: string = msg.role ?? "unknown";
        const content: string = msg.content ?? "";

        let rowStyle = "bg-muted/30 border-border/50";
        let labelStyle = "text-muted-foreground";
        let roleLabel = role;

        if (role === "user") {
          rowStyle = "bg-blue-50/50 border-blue-200/50";
          labelStyle = "text-blue-700";
        } else if (role === "assistant") {
          rowStyle = "bg-green-50/50 border-green-200/50";
          labelStyle = "text-green-700";
        } else if (role === "tool") {
          rowStyle = "bg-orange-50/50 border-orange-200/50";
          labelStyle = "text-orange-700";
          roleLabel = msg.tool_name ? `tool: ${msg.tool_name}` : "tool";
        } else if (role === "system") {
          rowStyle = "bg-gray-50/50 border-gray-200/50";
          labelStyle = "text-gray-500";
        }

        const toolCallNames: string =
          Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0
            ? msg.tool_calls.map((tc: any) => tc.tool_name).join(", ")
            : "";

        return (
          <div key={idx} className={`border rounded px-3 py-2 ${rowStyle}`}>
            <div
              className={`text-xs font-semibold mb-1 uppercase tracking-wide ${labelStyle}`}
            >
              {roleLabel}
            </div>
            {content ? (
              <p className="text-xs whitespace-pre-wrap break-words line-clamp-4">
                {content}
              </p>
            ) : toolCallNames ? (
              <p className="text-xs text-muted-foreground italic">
                Tool calls: {toolCallNames}
              </p>
            ) : (
              <p className="text-xs text-muted-foreground italic">
                (no text content)
              </p>
            )}
          </div>
        );
      })}
    </div>
  );
}

// ── Agent-style Renderer ───────────────────────────────────────────────────

function AgentStyleResultRenderer({ result }: { result: AgentStyleResult }) {
  const hasResponse =
    result.response !== null &&
    result.response !== undefined &&
    result.response !== "";
  const messages = result.messages ?? [];
  const hasMessages = messages.length > 0;
  const hasUsage =
    result.usage !== null &&
    result.usage !== undefined &&
    typeof result.usage === "object";
  const hasMetadata =
    result.metadata !== null &&
    result.metadata !== undefined &&
    typeof result.metadata === "object" &&
    Object.keys(result.metadata).length > 0;

  return (
    <div className="space-y-3">
      {/* Primary response */}
      {hasResponse ? (
        <Card>
          <CardHeader className="pb-2 pt-3 px-4">
            <div className="flex items-center justify-between">
              <CardTitle className="text-sm font-medium">Result</CardTitle>
              <CopyButton text={result.response!} />
            </div>
          </CardHeader>
          <CardContent className="px-4 pb-4">
            <MarkdownContent content={result.response!} />
          </CardContent>
        </Card>
      ) : (
        <p className="text-sm text-muted-foreground px-1">
          No response content returned.
        </p>
      )}

      {/* Usage */}
      {hasUsage && (
        <div className="px-1">
          <UsageCounters usage={result.usage!} />
        </div>
      )}

      {/* Transcript */}
      {hasMessages && (
        <CollapsibleSection
          title="Transcript"
          icon={<MessageSquare className="h-4 w-4 text-muted-foreground" />}
          badge={String(messages.length)}
        >
          <MessageTranscript messages={messages} />
        </CollapsibleSection>
      )}

      {/* Metadata */}
      {hasMetadata && (
        <CollapsibleSection
          title="Metadata"
          icon={<Info className="h-4 w-4 text-muted-foreground" />}
        >
          <pre className="text-xs bg-muted p-2 rounded overflow-auto whitespace-pre-wrap break-words">
            {JSON.stringify(result.metadata, null, 2)}
          </pre>
        </CollapsibleSection>
      )}

      {/* Raw JSON debug */}
      <CollapsibleSection
        title="Raw JSON"
        icon={<Bug className="h-4 w-4 text-muted-foreground" />}
      >
        <pre className="text-xs bg-muted p-2 rounded overflow-auto whitespace-pre-wrap break-words">
          {JSON.stringify(result, null, 2)}
        </pre>
      </CollapsibleSection>
    </div>
  );
}

// ── Generic Fallback Renderer ──────────────────────────────────────────────

function GenericResultRenderer({ result }: { result: any }) {
  const isPlainObject =
    result !== null && typeof result === "object" && !Array.isArray(result);
  const isArray = Array.isArray(result);
  const isPrimitive = !isPlainObject && !isArray;

  if (isPrimitive) {
    return (
      <Card>
        <CardContent className="px-4 py-3">
          <pre className="text-sm whitespace-pre-wrap break-words">
            {String(result)}
          </pre>
        </CardContent>
      </Card>
    );
  }

  const keys = isPlainObject ? Object.keys(result) : [];
  const hasSimpleSummary = isPlainObject && keys.length > 0 && keys.length <= 10;

  return (
    <div className="space-y-3">
      {hasSimpleSummary && (
        <Card>
          <CardHeader className="pb-2 pt-3 px-4">
            <CardTitle className="text-sm font-medium">Result Summary</CardTitle>
          </CardHeader>
          <CardContent className="px-4 pb-4 space-y-2">
            {keys.map((key) => {
              const value = result[key];
              const isSimple = typeof value !== "object" || value === null;
              return (
                <div key={key} className="flex gap-2 text-sm">
                  <span className="font-medium text-muted-foreground min-w-[6rem] shrink-0">
                    {key}
                  </span>
                  {isSimple ? (
                    <span className="break-all">{String(value)}</span>
                  ) : (
                    <span className="text-muted-foreground italic text-xs">
                      {Array.isArray(value)
                        ? `Array(${value.length})`
                        : "Object"}
                    </span>
                  )}
                </div>
              );
            })}
          </CardContent>
        </Card>
      )}

      <CollapsibleSection
        title={hasSimpleSummary ? "Raw JSON" : "Result"}
        icon={<Bug className="h-4 w-4 text-muted-foreground" />}
        defaultOpen={!hasSimpleSummary}
      >
        <pre className="text-xs bg-muted p-2 rounded overflow-auto whitespace-pre-wrap break-words">
          {JSON.stringify(result, null, 2)}
        </pre>
      </CollapsibleSection>
    </div>
  );
}

// ── Main Export ────────────────────────────────────────────────────────────

export function WorkflowResultRenderer({
  result,
}: WorkflowResultRendererProps) {
  if (isAgentStyleResult(result)) {
    return <AgentStyleResultRenderer result={result} />;
  }
  return <GenericResultRenderer result={result} />;
}
