"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import { Label } from "@/components/ui/label";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { ImageIcon, Loader2Icon, SparklesIcon, Trash2Icon } from "lucide-react";
import type { CourseStructure } from "@/components/video-context-panel";
import type { SectionWithWordCount } from "@/features/article-writer/types";

export function ImageUploadDropdown({
  videoId,
  body,
  onBodyChange,
}: {
  videoId: string;
  body: string;
  onBodyChange: (body: string) => void;
}) {
  const [isUploading, setIsUploading] = useState(false);
  const hasLocalImages = useMemo(() => {
    const imageRegex = /!\[[^\]]*\]\(([^)]+)\)/g;
    const matches = Array.from(body.matchAll(imageRegex));
    return matches.some(
      (m) => !m[1]!.startsWith("http://") && !m[1]!.startsWith("https://")
    );
  }, [body]);

  const handleUpload = async (deleteLocalFiles: boolean) => {
    if (!body.trim()) return;
    setIsUploading(true);
    try {
      const response = await fetch(`/api/videos/${videoId}/upload-images`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ body, deleteLocalFiles }),
      });
      if (!response.ok) {
        const errorText = await response.text();
        throw new Error(errorText || "Failed to upload images");
      }
      const result = await response.json();
      if (result.body !== body) {
        onBodyChange(result.body);
        toast.success(
          deleteLocalFiles
            ? "Images uploaded to Cloudinary and local files deleted"
            : "Images uploaded to Cloudinary"
        );
      } else {
        toast("No local images found to upload");
      }
    } catch (error) {
      toast.error(
        error instanceof Error ? error.message : "Failed to upload images"
      );
    } finally {
      setIsUploading(false);
    }
  };

  if (!hasLocalImages && !isUploading) return null;

  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button variant="outline" size="sm" disabled={isUploading}>
          {isUploading ? (
            <>
              <Loader2Icon className="h-4 w-4 animate-spin" />
              Uploading images...
            </>
          ) : (
            <>
              <ImageIcon className="h-4 w-4" />
              Upload Images to Cloudinary
            </>
          )}
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent align="start">
        <DropdownMenuItem onClick={() => handleUpload(false)}>
          <ImageIcon className="h-4 w-4" />
          <div>
            <div>Upload</div>
            <p className="text-muted-foreground text-xs">
              Upload local images to Cloudinary and update references
            </p>
          </div>
        </DropdownMenuItem>
        <DropdownMenuItem
          variant="destructive"
          onClick={() => handleUpload(true)}
        >
          <Trash2Icon className="h-4 w-4" />
          <div>
            <div>Upload and delete local files</div>
            <p className="text-xs opacity-70">
              Upload to Cloudinary, then remove the local image files
            </p>
          </div>
        </DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}

export function SeoDescriptionField({
  videoId,
  description,
  onDescriptionChange,
  autoGenerate,
  enabledFiles,
  enabledSections,
  includeTranscript,
  courseStructure,
  includeCourseStructure,
  chapters,
}: {
  videoId: string;
  description: string;
  onDescriptionChange: (d: string) => void;
  autoGenerate: boolean;
  enabledFiles: Set<string>;
  enabledSections: Set<string>;
  includeTranscript: boolean;
  courseStructure: CourseStructure | null;
  includeCourseStructure: boolean;
  chapters: SectionWithWordCount[];
}) {
  const [isGenerating, setIsGenerating] = useState(false);
  const hasAutoGenerated = useRef(false);
  const [confirmRegenerate, setConfirmRegenerate] = useState(false);
  const [pendingGenerated, setPendingGenerated] = useState("");

  const isDescriptionTooLong = description.length > 160;

  const generate = useCallback(async () => {
    setIsGenerating(true);
    try {
      const transcriptEnabled =
        chapters.length > 0 ? enabledSections.size > 0 : includeTranscript;

      const response = await fetch(`/api/videos/${videoId}/generate`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          mode: "seo-description",
          enabledFiles: Array.from(enabledFiles),
          includeTranscript: transcriptEnabled,
          enabledSections: Array.from(enabledSections),
          courseStructure:
            includeCourseStructure && courseStructure
              ? courseStructure
              : undefined,
        }),
      });

      if (!response.ok) {
        throw new Error("Failed to generate description");
      }

      const result = await response.json();
      return result.text as string;
    } finally {
      setIsGenerating(false);
    }
  }, [
    videoId,
    chapters.length,
    enabledSections,
    includeTranscript,
    enabledFiles,
    includeCourseStructure,
    courseStructure,
  ]);

  useEffect(() => {
    if (!hasAutoGenerated.current && !description.trim() && autoGenerate) {
      hasAutoGenerated.current = true;
      generate()
        .then((text) => {
          if (text) onDescriptionChange(text);
        })
        .catch(console.error);
    }
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  const handleRegenerate = async () => {
    const text = await generate();
    if (!text) return;

    if (description.trim()) {
      setPendingGenerated(text);
      setConfirmRegenerate(true);
    } else {
      onDescriptionChange(text);
    }
  };

  return (
    <>
      <div className="space-y-2">
        <div className="flex items-center justify-between">
          <Label htmlFor="sc-description">SEO Description</Label>
          <Button
            variant="outline"
            size="sm"
            onClick={handleRegenerate}
            disabled={isGenerating}
          >
            {isGenerating ? (
              <>
                <Loader2Icon className="h-4 w-4 animate-spin" />
                Generating...
              </>
            ) : (
              <>
                <SparklesIcon className="h-4 w-4" />
                Regenerate
              </>
            )}
          </Button>
        </div>
        <Textarea
          id="sc-description"
          value={description}
          onChange={(e) => onDescriptionChange(e.target.value)}
          placeholder={
            isGenerating
              ? "Generating description..."
              : "SEO description (160 characters max)..."
          }
          className={`min-h-[80px] resize-y ${isDescriptionTooLong ? "border-red-500 focus-visible:ring-red-500" : ""}`}
        />
        <p
          className={`text-xs text-right ${isDescriptionTooLong ? "text-red-500" : "text-muted-foreground"}`}
        >
          {description.length}/160
        </p>
      </div>

      <Dialog
        open={confirmRegenerate}
        onOpenChange={(open) => {
          if (!open) {
            setConfirmRegenerate(false);
            setPendingGenerated("");
          }
        }}
      >
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Replace description?</DialogTitle>
            <DialogDescription>
              The description field already has content. Do you want to replace
              it with the newly generated text?
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button
              variant="outline"
              onClick={() => {
                setConfirmRegenerate(false);
                setPendingGenerated("");
              }}
            >
              Cancel
            </Button>
            <Button
              onClick={() => {
                onDescriptionChange(pendingGenerated);
                setConfirmRegenerate(false);
                setPendingGenerated("");
              }}
            >
              Replace
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  );
}
