import {
  AlertTriangle,
  ArrowDown,
  ArrowUp,
  Check,
  ChevronDown,
  ChevronRight,
  ChevronsDown,
  ChevronsUp,
  Clock,
  Copy,
  FileTerminal,
  Globe,
  Loader2,
  MessageSquare,
  OctagonAlert,
  Radio,
  RotateCcw,
  Wrench,
  Zap,
} from "lucide-react";
import type { JSX, MouseEvent } from "react";
import { memo, useMemo } from "react";
import { cn, formatTokens, getStatusCategory, type StatusCategory } from "../../lib/utils";
import type { CapturedLog } from "../../proxy/schemas";
import { Badge } from "../ui/badge";
import { Button } from "../ui/button";
import { ProviderLogo, detectProvider } from "../providers/ProviderLogo";
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "../ui/tooltip";
import type { CacheTrend } from "./cacheTrend";

const STATUS_BADGE_CLASSES: Record<StatusCategory, string> = {
  success: "bg-emerald-500/15 text-emerald-400 border-emerald-500/25",
  client_error: "bg-amber-500/15 text-amber-400 border-amber-500/25",
  server_error: "bg-rose-500/15 text-rose-400 border-rose-500/25",
  pending: "bg-muted text-muted-foreground border-border",
};

function formatElapsed(ms: number): string {
  if (ms < 1000) return `${ms}ms`;
  return `${(ms / 1000).toFixed(1)}s`;
}

/**
 * Inline trend indicator: small arrow (green up / red down) plus the absolute
 * delta in compact form. Returns `null` when there is no trend to display.
 */
function CacheTrendIndicator({ trend }: { trend: CacheTrend | null }): JSX.Element | null {
  if (trend === null) return null;
  const isUp = trend.direction === "up";
  const Icon = isUp ? ArrowUp : ArrowDown;
  const sign = isUp ? "+" : "-";
  return (
    <span className="flex items-center gap-0.5 text-muted-foreground tabular-nums">
      <Icon className={isUp ? "size-3 text-emerald-400" : "size-3 text-rose-400"} />
      <span className="font-mono">
        {sign}
        {formatTokens(trend.delta)}
      </span>
    </span>
  );
}

export type LogEntryHeaderProps = {
  log: CapturedLog;
  /** Number of messages in the request (supports both Anthropic and OpenAI formats). */
  messageCount?: number | null;
  /** Number of tools defined in the request (supports both Anthropic and OpenAI formats). */
  toolCount?: number | null;
  expanded: boolean;
  onToggle: () => void;
  /** Tool call names extracted from the model response (e.g., ["read_file", "grep"]). */
  responseToolNames?: string[] | null;
  /** Per-log cache token trend (creation + read) relative to the previous log
   * in the same conversation group. When `undefined` or a field is `null`,
   * the corresponding cache span renders as it did before — no arrow.
   */
  cacheTrend?: { creation: CacheTrend | null; read: CacheTrend | null } | null;
  /** Re-send this request to the provider. Rendered in the header row when
   *  `expanded` is true. */
  onReplay?: () => void;
  /** Copy the request body to the clipboard. Omit to hide the button. */
  onCopyRequest?: (event: MouseEvent) => void;
  /** Whether the latest copy of the request body succeeded (shows "Copied!"). */
  requestCopied?: boolean;
  /** Toggle the JSON bulk-expansion state for the request body. */
  onToggleRequestExpansion?: () => void;
  /** Current state of the JSON bulk-expansion button. `null` means the
   *  request body is not JSON, so the button is hidden. */
  requestExpansionState?: {
    isExpanded: boolean;
    isPending: boolean;
  } | null;
  /** Slow-response threshold in seconds. `0` disables the warning indicator. */
  slowResponseThresholdSeconds?: number;
};

export const LogEntryHeader = memo(function ({
  log,
  messageCount = null,
  toolCount = null,
  expanded,
  onToggle,
  responseToolNames = null,
  cacheTrend = null,
  onReplay,
  onCopyRequest,
  requestCopied = false,
  onToggleRequestExpansion,
  requestExpansionState = null,
  slowResponseThresholdSeconds = 0,
}: LogEntryHeaderProps): JSX.Element {
  const statusCategory = getStatusCategory(log.responseStatus);
  const isSlowResponse =
    log.elapsedMs !== null &&
    slowResponseThresholdSeconds > 0 &&
    log.elapsedMs > slowResponseThresholdSeconds * 1000;

  const hasTokens = log.inputTokens !== null || log.outputTokens !== null;
  const toolNamesJoined = useMemo(() => responseToolNames?.join(", ") ?? null, [responseToolNames]);

  return (
    <TooltipProvider>
      <div
        role="button"
        tabIndex={0}
        data-nav-id={`log-${log.id}`}
        data-nav-action={expanded ? "collapse" : "expand"}
        className={cn(
          "flex items-center gap-2 px-3 py-1 cursor-pointer transition-colors",
          "hover:bg-muted/50",
          "select-none",
          "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:outline-none",
        )}
        onClick={onToggle}
        onKeyDown={(e) => {
          if (e.key === "Enter" || e.key === " ") {
            e.preventDefault();
            onToggle();
          }
        }}
      >
        {/* Request ID */}
        <span className="text-blue-400/80 font-mono text-xs font-semibold tabular-nums shrink-0">
          #{log.id}
        </span>

        {/* Request start time */}
        <span className="flex items-center gap-1 text-muted-foreground text-xs shrink-0">
          <Clock className="size-3" />
          <span className="font-mono tabular-nums">{log.timestamp}</span>
        </span>

        {/* Model — logo icon only, model name in tooltip */}
        {log.model !== null && (
          <Tooltip>
            <TooltipTrigger asChild>
              <span className="shrink-0">
                <ProviderLogo provider={detectProvider(log.model)} className="size-4" />
              </span>
            </TooltipTrigger>
            <TooltipContent>{log.model}</TooltipContent>
          </Tooltip>
        )}

        {/* Response Status — only shown for non-200 or pending. Each category
            carries a distinct icon in addition to color so the meaning is
            legible without color perception. */}
        {statusCategory !== "success" && (
          <Badge
            variant="outline"
            className={cn(
              "text-[10px] px-1.5 py-0 h-5 font-mono tabular-nums gap-1",
              STATUS_BADGE_CLASSES[statusCategory],
            )}
          >
            {statusCategory === "server_error" ? (
              <OctagonAlert className="size-3" aria-label="Server error" />
            ) : statusCategory === "client_error" ? (
              <AlertTriangle className="size-3" aria-label="Client error" />
            ) : statusCategory === "pending" ? (
              <Loader2 className="size-3 animate-spin" aria-label="Pending" />
            ) : null}
            {log.responseStatus}
          </Badge>
        )}

        {/* Elapsed time */}
        {log.elapsedMs !== null && (
          <Tooltip>
            <TooltipTrigger asChild>
              <span
                className={cn(
                  "flex items-center gap-1 text-xs shrink-0",
                  isSlowResponse ? "text-amber-400" : "text-muted-foreground",
                )}
              >
                <Clock className="size-3" />
                <span className="font-mono tabular-nums">{formatElapsed(log.elapsedMs)}</span>
                {isSlowResponse && <AlertTriangle className="size-3" aria-label="Slow response" />}
              </span>
            </TooltipTrigger>
            <TooltipContent>
              {isSlowResponse
                ? `Slow response: ${formatElapsed(log.elapsedMs)} exceeds ${formatElapsed(
                    slowResponseThresholdSeconds * 1000,
                  )}`
                : "Elapsed response time"}
            </TooltipContent>
          </Tooltip>
        )}

        {/* Token counts */}
        {hasTokens && (
          <span className="flex items-center gap-1 text-xs shrink-0">
            <Zap className="size-3 text-muted-foreground" />
            <span className="font-mono tabular-nums">
              <span
                className={log.inputTokens !== null ? "text-blue-400" : "text-muted-foreground"}
              >
                IN {log.inputTokens !== null ? formatTokens(log.inputTokens) : "—"}
              </span>
              {" / "}
              <span
                className={log.outputTokens !== null ? "text-amber-400" : "text-muted-foreground"}
              >
                OUT {log.outputTokens !== null ? formatTokens(log.outputTokens) : "—"}
              </span>
            </span>
          </span>
        )}
        {/* Cache tokens */}
        {log.cacheCreationInputTokens !== null && log.cacheCreationInputTokens > 0 && (
          <Tooltip>
            <TooltipTrigger asChild>
              <span className="flex items-center gap-1 text-xs shrink-0">
                <CacheTrendIndicator trend={cacheTrend?.creation ?? null} />
                <span className="font-mono tabular-nums text-emerald-400">
                  Cache +{formatTokens(log.cacheCreationInputTokens)}
                </span>
              </span>
            </TooltipTrigger>
            <TooltipContent>Tokens cached for reuse, reducing future API cost</TooltipContent>
          </Tooltip>
        )}
        {log.cacheReadInputTokens !== null && log.cacheReadInputTokens > 0 && (
          <Tooltip>
            <TooltipTrigger asChild>
              <span className="flex items-center gap-1 text-xs shrink-0">
                <CacheTrendIndicator trend={cacheTrend?.read ?? null} />
                <span className="font-mono tabular-nums text-purple-400">
                  Cache ~{formatTokens(log.cacheReadInputTokens)}
                </span>
              </span>
            </TooltipTrigger>
            <TooltipContent>Tokens served from cache, reducing API cost</TooltipContent>
          </Tooltip>
        )}

        {/* Message count */}
        {messageCount !== null && (
          <span className="flex items-center gap-1 text-muted-foreground text-xs shrink-0">
            <MessageSquare className="size-3" />
            <span className="font-mono tabular-nums">{messageCount}</span>
          </span>
        )}

        {/* Tool count */}
        {toolCount !== null && (
          <span className="flex items-center gap-1 text-muted-foreground text-xs shrink-0">
            <Wrench className="size-3" />
            <span className="font-mono tabular-nums">{toolCount}</span>
          </span>
        )}

        {/* Response tool calls — tool names the model requested to invoke */}
        {responseToolNames !== null && responseToolNames.length > 0 && (
          <span className="flex items-center gap-1 text-amber-400/80 text-xs shrink-0">
            <Wrench className="size-3" />
            <span className="font-mono tabular-nums truncate max-w-[160px]">{toolNamesJoined}</span>
          </span>
        )}

        {/* Origin */}
        {log.origin !== null && (
          <span
            className="hidden xl:flex items-center gap-1 text-muted-foreground text-xs shrink-0"
            title={`Origin: ${log.origin}`}
          >
            <Globe className="size-3" />
            <span className="font-mono tabular-nums truncate max-w-[120px]" title={log.origin}>
              {log.origin}
            </span>
          </span>
        )}

        {/* Client info (PID + project folder) */}
        {(log.clientPid !== null || log.clientProjectFolder !== null) && (
          <Tooltip>
            <TooltipTrigger asChild>
              <span className="hidden xl:flex items-center gap-1 text-purple-400/80 text-xs shrink-0">
                <FileTerminal className="size-3" />
                {log.clientProjectFolder !== null ? (
                  <span className="font-mono tabular-nums">{log.clientProjectFolder}</span>
                ) : (
                  <span className="font-mono tabular-nums">PID {log.clientPid}</span>
                )}
              </span>
            </TooltipTrigger>
            <TooltipContent>
              {log.clientCwd !== null
                ? `PID: ${log.clientPid ?? "?"}  CWD: ${log.clientCwd}`
                : `Process ID: ${log.clientPid ?? "?"}`}
            </TooltipContent>
          </Tooltip>
        )}

        {/* Streaming indicator */}
        {log.streaming && (
          <Tooltip>
            <TooltipTrigger asChild>
              <Radio className="size-3 text-muted-foreground/60 shrink-0" />
            </TooltipTrigger>
            <TooltipContent>Request used SSE streaming</TooltipContent>
          </Tooltip>
        )}

        {/* Spacer */}
        <span className="flex-1 min-w-0" />

        {/* Header actions — only when expanded, so the collapsed view stays
            compact. Buttons stop propagation so they don't toggle the log. */}
        {expanded && (
          <span
            className="flex items-center gap-1.5 shrink-0"
            onClick={(e) => e.stopPropagation()}
            onKeyDown={(e) => e.stopPropagation()}
          >
            {requestExpansionState !== null && onToggleRequestExpansion !== undefined && (
              <Tooltip>
                <TooltipTrigger asChild>
                  <Button
                    variant="outline"
                    size="icon"
                    className="size-8"
                    onClick={onToggleRequestExpansion}
                    disabled={requestExpansionState.isPending}
                    aria-pressed={requestExpansionState.isExpanded}
                    aria-label={
                      requestExpansionState.isExpanded ? "Collapse all JSON" : "Expand all JSON"
                    }
                  >
                    {requestExpansionState.isExpanded ? (
                      <ChevronsUp className="size-3.5" />
                    ) : (
                      <ChevronsDown className="size-3.5" />
                    )}
                  </Button>
                </TooltipTrigger>
                <TooltipContent>
                  {requestExpansionState.isExpanded
                    ? "Collapse all JSON nodes"
                    : "Expand all JSON nodes"}
                </TooltipContent>
              </Tooltip>
            )}

            {onCopyRequest !== undefined && (
              <Tooltip>
                <TooltipTrigger asChild>
                  <Button
                    variant="outline"
                    size="icon"
                    className="size-8"
                    onClick={onCopyRequest}
                    aria-label="Copy request body"
                  >
                    {requestCopied ? (
                      <Check className="size-3.5 text-emerald-500" />
                    ) : (
                      <Copy className="size-3.5" />
                    )}
                  </Button>
                </TooltipTrigger>
                <TooltipContent>
                  {requestCopied ? "Copied to clipboard" : "Copy request body"}
                </TooltipContent>
              </Tooltip>
            )}

            {onReplay !== undefined && (
              <Tooltip>
                <TooltipTrigger asChild>
                  <Button
                    variant="outline"
                    size="icon"
                    className="size-8"
                    onClick={onReplay}
                    aria-label="Replay request"
                  >
                    <RotateCcw className="size-3.5" />
                  </Button>
                </TooltipTrigger>
                <TooltipContent>Re-send this request to the provider</TooltipContent>
              </Tooltip>
            )}
          </span>
        )}

        {/* Expand chevron */}
        {expanded ? (
          <ChevronDown className="size-4 text-muted-foreground shrink-0" />
        ) : (
          <ChevronRight className="size-4 text-muted-foreground shrink-0" />
        )}
      </div>
    </TooltipProvider>
  );
});
