import { AlertTriangle, Zap } from "lucide-react";
import type { JSX } from "react";
import { memo } from "react";
import { useMemo } from "react";
import ReactMarkdown from "react-markdown";
import { cn, formatTokens, getStatusCategory, type StatusCategory } from "../../lib/utils";
import type { RequestFormat } from "../../proxy/schemas";
import { formatViewFor } from "./formats";
import { getLogFormatAdapter } from "./log-formats";

export type ResponseViewProps = {
  responseText: string | null;
  responseStatus: number | null;
  streaming: boolean;
  inputTokens: number | null;
  outputTokens: number | null;
  cacheCreationInputTokens?: number | null;
  cacheReadInputTokens?: number | null;
  apiFormat?: RequestFormat;
  /** SSE error message from streaming response */
  error?: string | null;
};

function getStatusClasses(category: StatusCategory): string {
  switch (category) {
    case "success":
      return "text-emerald-400";
    case "client_error":
      return "text-amber-400";
    case "server_error":
      return "text-red-400";
    case "pending":
      return "text-muted-foreground";
  }
}

function StatusIndicator({ status }: { status: number | null }): JSX.Element {
  const category = getStatusCategory(status);
  const classes = getStatusClasses(category);

  if (status === null) {
    return <span className="text-xs text-muted-foreground italic">pending</span>;
  }

  return (
    <span className={cn("flex items-center gap-1 text-xs font-mono font-semibold", classes)}>
      {category === "server_error" && <AlertTriangle className="size-3" />}
      {status}
    </span>
  );
}

function ErrorResponseView({ text }: { text: string }): JSX.Element {
  return (
    <div className="rounded-md border border-red-500/30 bg-red-500/5 p-3">
      <pre className="text-xs text-red-300 whitespace-pre-wrap font-mono leading-relaxed overflow-auto max-h-[60vh]">
        {text}
      </pre>
    </div>
  );
}

function MarkdownFallbackView({ text }: { text: string }): JSX.Element {
  return (
    <div className="prose prose-sm dark:prose-invert max-w-none [&_pre]:bg-muted [&_pre]:text-foreground [&_code]:text-[0.8em] [&_p]:my-1 [&_ul]:my-1 [&_ol]:my-1">
      <ReactMarkdown>{text}</ReactMarkdown>
    </div>
  );
}

export const ResponseView = memo(function ResponseView({
  responseText,
  responseStatus,
  streaming,
  inputTokens,
  outputTokens,
  cacheCreationInputTokens,
  cacheReadInputTokens,
  apiFormat,
  error,
}: ResponseViewProps): JSX.Element {
  const resolvedFormat = apiFormat ?? "unknown";
  const parsed = useMemo(
    () => getLogFormatAdapter(resolvedFormat).analyzeResponse(responseText).parsed,
    [resolvedFormat, responseText],
  );

  if (responseText === null && error === undefined) {
    return (
      <div className="flex items-center gap-2 py-3">
        <StatusIndicator status={responseStatus} />
        <span className="text-xs text-muted-foreground italic">No response</span>
      </div>
    );
  }

  const isHttpError = responseStatus !== null && responseStatus >= 400;

  if (isHttpError) {
    return (
      <div className="space-y-2">
        <StatusIndicator status={responseStatus} />
        <ErrorResponseView text={responseText ?? ""} />
        {error !== undefined && error !== null && (
          <div className="rounded border border-destructive/50 bg-destructive/10 p-3 text-xs">
            <div className="font-semibold text-destructive mb-1">SSE Error</div>
            <div className="text-muted-foreground font-mono">{error}</div>
          </div>
        )}
      </div>
    );
  }

  if (error !== undefined && error !== null) {
    return (
      <div className="space-y-2">
        <StatusIndicator status={responseStatus} />
        <div className="rounded border border-destructive/50 bg-destructive/10 p-3 text-xs">
          <div className="font-semibold text-destructive mb-1">SSE Error</div>
          <div className="text-muted-foreground font-mono">{error}</div>
        </div>
        {responseText !== null && (
          <div className="mt-2">
            <ErrorResponseView text={responseText} />
          </div>
        )}
      </div>
    );
  }

  if (parsed !== null) {
    return (
      <div className="space-y-2">
        <StatusIndicator status={responseStatus} />
        {formatViewFor(resolvedFormat, parsed)}
      </div>
    );
  }

  return (
    <div className="space-y-2">
      <div className="flex items-center gap-2">
        <StatusIndicator status={responseStatus} />
        {streaming && (inputTokens !== null || outputTokens !== null) && (
          <span className="flex items-center gap-1 text-muted-foreground text-xs">
            <Zap className="size-3" />
            <span className="font-mono tabular-nums">
              {inputTokens !== null ? formatTokens(inputTokens) : "—"} in /{" "}
              {outputTokens !== null ? formatTokens(outputTokens) : "—"} out
            </span>
            {cacheCreationInputTokens !== null &&
              cacheCreationInputTokens !== undefined &&
              cacheCreationInputTokens > 0 && (
                <span className="font-mono tabular-nums text-emerald-400">
                  Cache +{formatTokens(cacheCreationInputTokens)}
                </span>
              )}
            {cacheReadInputTokens !== null &&
              cacheReadInputTokens !== undefined &&
              cacheReadInputTokens > 0 && (
                <span className="font-mono tabular-nums text-purple-400">
                  Cache ~{formatTokens(cacheReadInputTokens)}
                </span>
              )}
          </span>
        )}
      </div>
      <MarkdownFallbackView text={responseText ?? ""} />
    </div>
  );
});
