import { RotateCcw } from "lucide-react";
import type { JSX } from "react";
import { useState } from "react";
import { z } from "zod";
import { Button } from "../ui/button";
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "../ui/tooltip";
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "../ui/dialog";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../ui/tabs";
import { ResponseView } from "./ResponseView";
import type { CapturedLog } from "../../proxy/schemas";

const ReplayResultSchema = z.object({
  success: z.boolean(),
  error: z.string().optional(),
  responseStatus: z.number().optional(),
  responseText: z.string().optional(),
  inputTokens: z.number().optional(),
  outputTokens: z.number().optional(),
  elapsedMs: z.number().optional(),
  streaming: z.boolean().optional(),
});

type ReplayResult = z.infer<typeof ReplayResultSchema>;

type ReplayDialogProps = {
  log: CapturedLog;
  open: boolean;
  onOpenChange: (open: boolean) => void;
};

export function ReplayDialog({ log, open, onOpenChange }: ReplayDialogProps): JSX.Element {
  const [modifiedBody, setModifiedBody] = useState<string>(() => {
    return log.rawRequestBody ?? "{}";
  });
  const [replayResult, setReplayResult] = useState<ReplayResult | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  async function handleReplay() {
    setLoading(true);
    setError(null);
    setReplayResult(null);

    try {
      const res = await fetch(`/api/logs/${log.id}/replay`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ modifiedBody }),
      });

      const json: unknown = await res.json();
      const parsed = ReplayResultSchema.safeParse(json);
      if (!parsed.success) {
        setError("Invalid response from server");
        setLoading(false);
        return;
      }
      const data = parsed.data;
      setReplayResult(data);
      if (!data.success) {
        setError(data.error ?? "Replay failed");
      }
    } catch (err) {
      setError(err instanceof Error ? err.message : "Network error");
    } finally {
      setLoading(false);
    }
  }

  function handleClose() {
    setReplayResult(null);
    setError(null);
    onOpenChange(false);
  }

  return (
    <Dialog open={open} onOpenChange={handleClose}>
      <DialogContent className="max-w-4xl max-h-[85vh] overflow-auto">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            <RotateCcw className="size-4" />
            Replay Request #{log.id}
          </DialogTitle>
        </DialogHeader>

        <Tabs defaultValue="modified">
          <TabsList>
            <TabsTrigger value="modified">Modified Request</TabsTrigger>
            <TabsTrigger value="original">Original Response</TabsTrigger>
            {replayResult && <TabsTrigger value="replay">Replay Response</TabsTrigger>}
          </TabsList>

          <TabsContent value="modified" className="space-y-4">
            <div>
              <label className="text-sm font-medium mb-2 block">Request Body (JSON)</label>
              <TooltipProvider>
                <Tooltip>
                  <TooltipTrigger asChild>
                    <textarea
                      className="w-full h-64 p-3 font-mono text-xs bg-muted rounded-md border border-input resize-none focus:outline-none focus:ring-2 focus:ring-ring"
                      value={modifiedBody}
                      onChange={(e) => setModifiedBody(e.target.value)}
                      spellCheck={false}
                    />
                  </TooltipTrigger>
                  <TooltipContent>
                    Edit the request body before re-sending to the provider
                  </TooltipContent>
                </Tooltip>
              </TooltipProvider>
            </div>

            {error !== null && error !== "" && (
              <div className="text-sm text-destructive bg-destructive/10 px-3 py-2 rounded-md">
                {error}
              </div>
            )}

            <div className="flex justify-end">
              <Button
                onClick={() => {
                  void handleReplay();
                }}
                disabled={loading}
              >
                {loading ? "Replaying..." : "Replay"}
              </Button>
            </div>

            {replayResult && replayResult.success && (
              <Tabs defaultValue="parsed">
                <TabsList>
                  <TabsTrigger value="parsed">Response</TabsTrigger>
                  <TabsTrigger value="raw">Raw Response</TabsTrigger>
                </TabsList>
                <TabsContent value="parsed">
                  <ResponseView
                    responseText={replayResult.responseText ?? null}
                    responseStatus={replayResult.responseStatus ?? null}
                    streaming={replayResult.streaming ?? false}
                    inputTokens={replayResult.inputTokens ?? null}
                    outputTokens={replayResult.outputTokens ?? null}
                    apiFormat={log.apiFormat}
                  />
                </TabsContent>
                <TabsContent value="raw">
                  <pre className="font-mono text-xs whitespace-pre-wrap bg-muted p-3 rounded-md max-h-96 overflow-auto">
                    {replayResult.responseText ?? "No response"}
                  </pre>
                </TabsContent>
              </Tabs>
            )}
          </TabsContent>

          <TabsContent value="original">
            {log.responseText !== null ? (
              <Tabs defaultValue="parsed">
                <TabsList>
                  <TabsTrigger value="parsed">Response</TabsTrigger>
                  <TabsTrigger value="raw">Raw Response</TabsTrigger>
                </TabsList>
                <TabsContent value="parsed">
                  <ResponseView
                    responseText={log.responseText}
                    responseStatus={log.responseStatus}
                    streaming={log.streaming}
                    inputTokens={log.inputTokens}
                    outputTokens={log.outputTokens}
                    cacheCreationInputTokens={log.cacheCreationInputTokens}
                    cacheReadInputTokens={log.cacheReadInputTokens}
                    apiFormat={log.apiFormat}
                  />
                </TabsContent>
                <TabsContent value="raw">
                  <pre className="font-mono text-xs whitespace-pre-wrap bg-muted p-3 rounded-md max-h-96 overflow-auto">
                    {log.responseText}
                  </pre>
                </TabsContent>
              </Tabs>
            ) : (
              <p className="text-sm text-muted-foreground italic">No original response</p>
            )}
          </TabsContent>

          {replayResult && replayResult.success && (
            <TabsContent value="replay">
              {replayResult.responseText !== null ? (
                <Tabs defaultValue="parsed">
                  <TabsList>
                    <TabsTrigger value="parsed">Response</TabsTrigger>
                    <TabsTrigger value="raw">Raw Response</TabsTrigger>
                  </TabsList>
                  <TabsContent value="parsed">
                    <ResponseView
                      responseText={replayResult.responseText ?? null}
                      responseStatus={replayResult.responseStatus ?? null}
                      streaming={replayResult.streaming ?? false}
                      inputTokens={replayResult.inputTokens ?? null}
                      outputTokens={replayResult.outputTokens ?? null}
                      apiFormat={log.apiFormat}
                    />
                  </TabsContent>
                  <TabsContent value="raw">
                    <pre className="font-mono text-xs whitespace-pre-wrap bg-muted p-3 rounded-md max-h-96 overflow-auto">
                      {replayResult.responseText}
                    </pre>
                  </TabsContent>
                </Tabs>
              ) : (
                <p className="text-sm text-muted-foreground italic">No replay response</p>
              )}
            </TabsContent>
          )}
        </Tabs>
      </DialogContent>
    </Dialog>
  );
}
