"use client";

import { useMemo, useState } from "react";
import Image from "next/image";
import { Download, RefreshCw, Sparkles } from "lucide-react";

import {
  ExportPanel,
  MediaUploadDropzone,
  MetadataPanel,
  ProcessingStatus,
  VideoPlayerPreview
} from "@/components/media";
import { EmptyState } from "@/components/shared/empty-state";
import { ErrorState } from "@/components/shared/error-state";
import { SimpleToastStack } from "@/components/shared/simple-toast-stack";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Switch } from "@/components/ui/switch";
import { useObjectUrl } from "@/hooks/use-object-url";
import { useSimpleToast } from "@/hooks/use-simple-toast";
import { parseApiErrorMessage } from "@/lib/client/api-utils";
import { formatSecondsAsClock, formatSecondsAsTimecode } from "@/lib/client/time-format";
import { cn } from "@/lib/utils";
import type { ApiSuccessResponse } from "@/types/api";
import type { MetadataItem } from "@/types/media-ui";
import type { VideoMetadata } from "@/types/media-processing";

interface ThumbnailCandidateView {
  id: string;
  timestampSeconds: number;
  score: number;
  rationale: string;
  fileName: string;
  dataUrl: string;
}

interface AnalyzePayload {
  metadata: VideoMetadata;
  reroll: number;
  seed: number;
  enhancements: {
    sharpen: boolean;
    boost: boolean;
    titleSafeOverlay: boolean;
  };
  candidates: ThumbnailCandidateView[];
}

interface EnhancementState {
  sharpen: boolean;
  boost: boolean;
  titleSafeOverlay: boolean;
}

function EnhancementToggle({
  label,
  description,
  checked,
  onCheckedChange
}: {
  label: string;
  description: string;
  checked: boolean;
  onCheckedChange: (checked: boolean) => void;
}) {
  return (
    <label className="flex items-start justify-between gap-3 rounded-lg border border-white/10 bg-white/5 px-3 py-2.5">
      <div className="space-y-0.5">
        <p className="text-sm text-white">{label}</p>
        <p className="text-xs text-slate-400">{description}</p>
      </div>
      <Switch checked={checked} onCheckedChange={onCheckedChange} aria-label={label} />
    </label>
  );
}

export function VideoThumbnailCreatorTool() {
  const [selectedFile, setSelectedFile] = useState<File | null>(null);
  const sourceObjectUrl = useObjectUrl(selectedFile);

  const [metadata, setMetadata] = useState<VideoMetadata | null>(null);
  const [analysisSeed, setAnalysisSeed] = useState<number | null>(null);
  const [analysisReroll, setAnalysisReroll] = useState(0);

  const [analysisState, setAnalysisState] = useState<"idle" | "processing" | "success" | "error">("idle");
  const [analysisProgress, setAnalysisProgress] = useState(0);
  const [analysisError, setAnalysisError] = useState<string | null>(null);

  const [candidates, setCandidates] = useState<ThumbnailCandidateView[]>([]);
  const [selectedCandidateId, setSelectedCandidateId] = useState<string | null>(null);

  const [enhancements, setEnhancements] = useState<EnhancementState>({
    sharpen: false,
    boost: false,
    titleSafeOverlay: false
  });

  const { toasts, pushToast, dismissToast } = useSimpleToast();

  const selectedCandidate = useMemo(
    () => candidates.find((candidate) => candidate.id === selectedCandidateId) || null,
    [candidates, selectedCandidateId]
  );

  const metadataItems: MetadataItem[] = useMemo(() => {
    if (!metadata) {
      return [];
    }

    return [
      {
        key: "filename",
        label: "Filename",
        value: metadata.filename
      },
      {
        key: "duration",
        label: "Duration",
        value: formatSecondsAsClock(metadata.durationSeconds)
      },
      {
        key: "resolution",
        label: "Resolution",
        value: `${metadata.width} x ${metadata.height}`
      },
      {
        key: "frameRate",
        label: "Frame Rate",
        value: metadata.frameRate ? `${metadata.frameRate.toFixed(2)} fps` : "Unknown"
      },
      {
        key: "videoCodec",
        label: "Video Codec",
        value: metadata.videoCodec ?? "Unknown"
      },
      {
        key: "audio",
        label: "Audio",
        value: metadata.hasAudio ? "Present" : "None"
      }
    ];
  }, [metadata]);

  const handleClearMedia = () => {
    setSelectedFile(null);
    setMetadata(null);
    setAnalysisSeed(null);
    setAnalysisReroll(0);
    setAnalysisState("idle");
    setAnalysisProgress(0);
    setAnalysisError(null);
    setCandidates([]);
    setSelectedCandidateId(null);
  };

  const runAnalysis = async (reroll: number) => {
    if (!selectedFile) {
      return;
    }

    setAnalysisState("processing");
    setAnalysisProgress(10);
    setAnalysisError(null);

    const progressTimer = setInterval(() => {
      setAnalysisProgress((previous) => Math.min(previous + Math.random() * 10, 92));
    }, 220);

    try {
      const formData = new FormData();
      formData.set("file", selectedFile);
      formData.set("reroll", String(reroll));
      formData.set("sharpen", String(enhancements.sharpen));
      formData.set("boost", String(enhancements.boost));
      formData.set("titleSafeOverlay", String(enhancements.titleSafeOverlay));

      const response = await fetch("/api/tools/video-thumbnail-creator/analyze", {
        method: "POST",
        body: formData
      });

      if (!response.ok) {
        const message = await parseApiErrorMessage(response, "Failed to generate thumbnail candidates.");
        throw new Error(message);
      }

      const payload = (await response.json()) as ApiSuccessResponse<AnalyzePayload>;
      if (!payload.ok) {
        throw new Error("Unexpected thumbnail response.");
      }

      setMetadata(payload.data.metadata);
      setAnalysisSeed(payload.data.seed);
      setAnalysisReroll(payload.data.reroll);
      setCandidates(payload.data.candidates);
      setSelectedCandidateId(payload.data.candidates[0]?.id ?? null);
      setAnalysisProgress(100);
      setAnalysisState("success");

      pushToast({
        title: reroll > 0 ? "Thumbnails rerolled" : "Thumbnails generated",
        description: "4 candidates are ready to review.",
        variant: "success"
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : "Failed to analyze video.";
      setAnalysisState("error");
      setAnalysisProgress(0);
      setAnalysisError(message);
      pushToast({
        title: "Analysis failed",
        description: message,
        variant: "error"
      });
    } finally {
      clearInterval(progressTimer);
    }
  };

  return (
    <div className="space-y-5">
      <MediaUploadDropzone
        file={selectedFile}
        onFileSelected={(file) => {
          setSelectedFile(file);
          setMetadata(null);
          setAnalysisSeed(null);
          setAnalysisReroll(0);
          setAnalysisState("idle");
          setAnalysisProgress(0);
          setAnalysisError(null);
          setCandidates([]);
          setSelectedCandidateId(null);
        }}
        onClear={handleClearMedia}
        busy={analysisState === "processing"}
        validation={{
          maxSizeBytes: 1_000_000_000,
          allowedExtensions: [".mp4", ".mov", ".m4v", ".webm", ".mkv", ".avi", ".wmv", ".flv"]
        }}
        onValidationError={(message) =>
          pushToast({
            title: "Invalid file",
            description: message,
            variant: "error"
          })
        }
      />

      <VideoPlayerPreview src={sourceObjectUrl} />

      <ExportPanel
        title="Thumbnail Analysis"
        description="Generate four ranked candidates, reroll with a new seed, and export your strongest frame."
        primaryAction={{
          label: candidates.length > 0 ? "Regenerate 4 Candidates" : "Generate 4 Candidates",
          onClick: () => {
            void runAnalysis(analysisReroll);
          },
          disabled: !selectedFile || analysisState === "processing",
          loading: analysisState === "processing"
        }}
        secondaryAction={{
          label: "Reroll",
          onClick: () => {
            void runAnalysis(analysisReroll + 1);
          },
          disabled: !selectedFile || analysisState === "processing",
          loading: analysisState === "processing"
        }}
      >
        <div className="grid gap-2 sm:grid-cols-2 lg:grid-cols-3">
          <EnhancementToggle
            label="Sharpen"
            description="Adds subtle edge definition for clearer details."
            checked={enhancements.sharpen}
            onCheckedChange={(checked) => setEnhancements((current) => ({ ...current, sharpen: checked }))}
          />
          <EnhancementToggle
            label="Brightness + Contrast"
            description="Boosts readability in flatter or dim footage."
            checked={enhancements.boost}
            onCheckedChange={(checked) => setEnhancements((current) => ({ ...current, boost: checked }))}
          />
          <EnhancementToggle
            label="Title-Safe Overlay"
            description="Draws safe-zone guides directly on generated thumbnails."
            checked={enhancements.titleSafeOverlay}
            onCheckedChange={(checked) =>
              setEnhancements((current) => ({ ...current, titleSafeOverlay: checked }))
            }
          />
        </div>
      </ExportPanel>

      <ProcessingStatus
        state={analysisState}
        label={
          analysisState === "processing"
            ? "Analyzing frames and scoring candidates..."
            : analysisState === "success"
              ? "4 candidate thumbnails ready"
              : analysisState === "error"
                ? "Thumbnail analysis failed"
                : "Awaiting analysis"
        }
        details={
          analysisState === "success" && analysisSeed != null
            ? `Seed ${analysisSeed} | reroll ${analysisReroll}`
            : analysisError ?? undefined
        }
        progress={analysisProgress}
      />

      {analysisState === "error" && analysisError ? (
        <ErrorState
          title="Thumbnail Analysis Error"
          description={analysisError}
          actionLabel="Retry"
          onAction={() => {
            void runAnalysis(analysisReroll);
          }}
        />
      ) : null}

      {metadata ? <MetadataPanel title="Source Metadata" items={metadataItems} columns={3} /> : null}

      {candidates.length > 0 ? (
        <section className="space-y-4">
          <div className="flex items-center justify-between gap-2">
            <h3 className="font-[var(--font-space-grotesk)] text-lg font-medium text-white">Thumbnail Candidates</h3>
            <Button
              variant="outline"
              size="sm"
              className="border-white/20 bg-slate-900/50"
              onClick={() => {
                void runAnalysis(analysisReroll + 1);
              }}
              disabled={analysisState === "processing"}
            >
              <RefreshCw data-icon="inline-start" />
              Reroll
            </Button>
          </div>

          <div className="grid gap-3 sm:grid-cols-2">
            {candidates.map((candidate, index) => {
              const isSelected = candidate.id === selectedCandidateId;
              const scoreLabel = `${Math.round(candidate.score * 100)}%`;

              return (
                <button
                  key={candidate.id}
                  type="button"
                  onClick={() => setSelectedCandidateId(candidate.id)}
                  className={cn(
                    "group overflow-hidden rounded-xl border bg-slate-900/55 text-left transition",
                    isSelected
                      ? "border-sky-300/60 shadow-[0_18px_40px_rgba(56,189,248,0.2)]"
                      : "border-white/10 hover:border-white/25"
                  )}
                >
                  <div className="relative">
                    <Image
                      src={candidate.dataUrl}
                      alt={`Thumbnail candidate ${index + 1}`}
                      width={640}
                      height={360}
                      className="aspect-video w-full object-cover transition duration-300 group-hover:scale-[1.01]"
                      unoptimized
                    />
                    <div className="absolute inset-x-2 top-2 flex items-center justify-between">
                      <Badge className="border-white/20 bg-slate-950/75 text-slate-100">Candidate {index + 1}</Badge>
                      <Badge className="border-sky-300/30 bg-sky-500/15 text-sky-100">
                        <Sparkles data-icon="inline-start" />
                        {scoreLabel}
                      </Badge>
                    </div>
                  </div>
                  <div className="space-y-1.5 p-3">
                    <p className="text-xs uppercase tracking-wide text-slate-400">
                      {formatSecondsAsTimecode(candidate.timestampSeconds)}
                    </p>
                    <p className="line-clamp-2 text-sm text-slate-200">{candidate.rationale}</p>
                  </div>
                </button>
              );
            })}
          </div>
        </section>
      ) : (
        <EmptyState
          title="No Thumbnail Candidates Yet"
          description="Generate candidates to preview and choose your final thumbnail."
        />
      )}

      {selectedCandidate ? (
        <section className="glass-panel rounded-2xl border border-white/15 p-5">
          <div className="flex flex-wrap items-start justify-between gap-3">
            <div>
              <h3 className="font-[var(--font-space-grotesk)] text-lg font-medium text-white">
                Selected Thumbnail
              </h3>
              <p className="mt-1 text-sm text-slate-300">
                Capture: {formatSecondsAsTimecode(selectedCandidate.timestampSeconds)} | Score{" "}
                {Math.round(selectedCandidate.score * 100)}%
              </p>
            </div>
            <Button
              render={
                <a href={selectedCandidate.dataUrl} download={selectedCandidate.fileName}>
                  <Download data-icon="inline-start" />
                  Download JPG
                </a>
              }
            />
          </div>

          <div className="mt-4 overflow-hidden rounded-xl border border-white/10 bg-black/80">
            <Image
              src={selectedCandidate.dataUrl}
              alt="Selected thumbnail preview"
              width={960}
              height={540}
              className="h-auto w-full object-contain"
              unoptimized
            />
          </div>
        </section>
      ) : null}

      <SimpleToastStack toasts={toasts} onDismiss={dismissToast} />
    </div>
  );
}
