"use client";

import { useContext, useEffect, useRef, useState } from "react";
import { useLocalStorage } from "@/hooks/use-local-storage";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { LinkIcon, Loader2Icon, SendIcon, SparklesIcon } from "lucide-react";
import { UploadContext } from "@/features/upload-manager/upload-context";
import { isDefaultShortTitle } from "@/lib/short-title";
import type { PostedPlatforms } from "@/lib/short-status";
import { findConvertibleAiHeroUrls, replaceUrls } from "./convert-short-links";

type PostState = "idle" | "checking-export";

export type ShortsPostingMode = "both" | "youtube" | "tiktok";

const SHORTS_DESC_KEY = (videoId: string) =>
  `shorts-post-description-${videoId}`;

export function ShortsPostingModal({
  open,
  onOpenChange,
  videoId,
  videoTitle,
  mode = "both",
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  videoId: string;
  videoTitle: string;
  mode?: ShortsPostingMode;
}) {
  const [postedStatus, setPostedStatus] = useState<PostedPlatforms | null>(
    null
  );
  useEffect(() => {
    if (!open) return;
    let cancelled = false;
    fetch(`/api/videos/${videoId}/posted-status`)
      .then((res) => (res.ok ? res.json() : null))
      .then((data: PostedPlatforms | null) => {
        if (!cancelled && data) setPostedStatus(data);
      })
      .catch(() => {});
    return () => {
      cancelled = true;
    };
  }, [open, videoId]);
  const [description, setDescription] = useLocalStorage(
    SHORTS_DESC_KEY(videoId),
    ""
  );

  const [title, setTitle] = useState(videoTitle);
  useEffect(() => {
    setTitle(videoTitle);
  }, [videoTitle]);

  const showDescription = mode === "both" || mode === "youtube";
  const requireDescription = showDescription;

  const [isGeneratingDescription, setIsGeneratingDescription] = useState(false);
  const [isConvertingShortLinks, setIsConvertingShortLinks] = useState(false);
  const hasAutoGeneratedRef = useRef(false);

  const {
    startYoutubeShortsUpload,
    startSocialUpload,
    startRenderVerticalUpload,
  } = useContext(UploadContext);

  const [postState, setPostState] = useState<PostState>("idle");

  const handleGenerateDescription = async () => {
    setIsGeneratingDescription(true);
    try {
      const response = await fetch(`/api/videos/${videoId}/generate`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          mode: "youtube-description",
          enabledFiles: [],
          includeTranscript: true,
          enabledSections: [],
        }),
      });

      if (!response.ok) throw new Error("Generation failed");

      const result = await response.json();
      setDescription(result.text as string);
    } catch {
      toast.error("Failed to generate text");
    } finally {
      setIsGeneratingDescription(false);
    }
  };

  useEffect(() => {
    if (
      open &&
      showDescription &&
      !description.trim() &&
      !hasAutoGeneratedRef.current
    ) {
      hasAutoGeneratedRef.current = true;
      handleGenerateDescription();
    }
  }, [open]);

  const handleConvertToShortLinks = async () => {
    const convertibleUrls = findConvertibleAiHeroUrls(description);

    if (convertibleUrls.length === 0) {
      toast("No convertible links", {
        description: "No aihero.dev links to convert in the description.",
      });
      return;
    }

    setIsConvertingShortLinks(true);
    try {
      const replacements = new Map<string, string>();
      for (const url of convertibleUrls) {
        const response = await fetch("/api/shortlinks/find-or-create", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            url,
            description: `YouTube Short (${videoTitle})`,
          }),
        });

        if (!response.ok) throw new Error("Failed to create short link");

        const { shortLinkUrl } = await response.json();
        replacements.set(url, shortLinkUrl);
      }

      setDescription(replaceUrls(description, replacements));
      toast("Links converted", {
        description: `Converted ${convertibleUrls.length} aihero.dev URL${convertibleUrls.length > 1 ? "s" : ""} to short links.`,
      });
    } catch {
      toast.error("Failed to convert links");
    } finally {
      setIsConvertingShortLinks(false);
    }
  };

  const persistTitle = async () => {
    const trimmed = title.trim();
    if (!trimmed || trimmed === videoTitle) return;
    try {
      const formData = new FormData();
      formData.set("name", trimmed);
      const res = await fetch(`/api/videos/${videoId}/rename`, {
        method: "POST",
        body: formData,
      });
      if (!res.ok) {
        if (res.status === 409) {
          toast.error("That name is already taken in this lesson.");
        } else {
          throw new Error("Rename failed");
        }
        setTitle(videoTitle);
      }
    } catch {
      toast.error("Failed to rename short");
      setTitle(videoTitle);
    }
  };

  const handlePost = async () => {
    const currentTitle = title.trim();

    if (isDefaultShortTitle(currentTitle)) {
      toast.error(
        "Rename this short before posting — it still has its default title."
      );
      return;
    }

    if (requireDescription && !description.trim()) {
      toast.error("Description is required");
      return;
    }

    setPostState("checking-export");
    try {
      const res = await fetch(`/api/videos/${videoId}/vertical-export-exists`);
      if (!res.ok) throw new Error("Failed to check export status");
      const { exists } = (await res.json()) as { exists: boolean };

      let exportId: string | undefined;
      if (!exists) {
        exportId = startRenderVerticalUpload(videoId, currentTitle);
      }

      if (mode === "both" || mode === "youtube") {
        startYoutubeShortsUpload(
          videoId,
          currentTitle,
          description.trim(),
          exportId
        );
      }

      if (mode === "both" || mode === "tiktok") {
        startSocialUpload(videoId, currentTitle, currentTitle, exportId);
      }

      onOpenChange(false);

      const target =
        mode === "youtube"
          ? "YouTube Shorts"
          : mode === "tiktok"
            ? "Buffer"
            : "YouTube Shorts + Buffer";
      if (exportId) {
        toast("Export + post started", {
          description: `"${currentTitle}" will export first, then post`,
        });
      } else {
        toast(`${target} posting started`);
      }
    } catch {
      toast.error("Failed to check export status");
    } finally {
      setPostState("idle");
    }
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-lg">
        <DialogHeader>
          <DialogTitle>
            {mode === "youtube"
              ? "Post to YouTube"
              : mode === "tiktok"
                ? "Post to TikTok"
                : "Post Short"}
          </DialogTitle>
          <DialogDescription>
            {mode === "youtube"
              ? "Post to YouTube Shorts. The exported vertical video will be used."
              : mode === "tiktok"
                ? "Post to TikTok via Buffer. The title is used as the caption."
                : "Post to YouTube Shorts and Buffer (TikTok / X / Bluesky). The exported vertical video will be used."}
          </DialogDescription>
        </DialogHeader>

        <div className="space-y-4 py-2">
          {postedStatus && (postedStatus.youtube || postedStatus.tiktok) && (
            <div className="flex gap-2 text-xs text-muted-foreground">
              {postedStatus.youtube && (
                <span className="inline-flex items-center gap-1 rounded bg-muted px-1.5 py-0.5">
                  Posted to YouTube
                </span>
              )}
              {postedStatus.tiktok && (
                <span className="inline-flex items-center gap-1 rounded bg-muted px-1.5 py-0.5">
                  Posted to TikTok
                </span>
              )}
            </div>
          )}

          <div className="space-y-1">
            <Label
              htmlFor="shorts-title"
              className="text-muted-foreground text-xs"
            >
              {mode === "tiktok" ? "Title / Caption" : "Title"}
            </Label>
            <Input
              id="shorts-title"
              value={title}
              onChange={(e) => setTitle(e.target.value)}
              onBlur={persistTitle}
              placeholder="Short title..."
            />
          </div>

          {showDescription && (
            <div className="space-y-2">
              <div className="flex items-center justify-between">
                <Label htmlFor="shorts-description">YouTube Description</Label>
                <Button
                  variant="ghost"
                  size="sm"
                  onClick={handleGenerateDescription}
                  disabled={isGeneratingDescription}
                >
                  {isGeneratingDescription ? (
                    <Loader2Icon className="h-3 w-3 animate-spin" />
                  ) : (
                    <SparklesIcon className="h-3 w-3" />
                  )}
                </Button>
              </div>
              <Textarea
                id="shorts-description"
                value={description}
                onChange={(e) => setDescription(e.target.value)}
                placeholder="YouTube description..."
                className="min-h-[80px] resize-y"
              />
            </div>
          )}

          {showDescription && (
            <Button
              variant="outline"
              size="sm"
              onClick={handleConvertToShortLinks}
              disabled={isConvertingShortLinks || !description.trim()}
            >
              {isConvertingShortLinks ? (
                <Loader2Icon className="h-3 w-3 animate-spin" />
              ) : (
                <LinkIcon className="h-3 w-3" />
              )}
              Convert to short links
            </Button>
          )}
        </div>

        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
          <Button
            onClick={handlePost}
            disabled={
              (requireDescription && !description.trim()) ||
              !title.trim() ||
              postState === "checking-export"
            }
          >
            {postState === "checking-export" ? (
              <>
                <Loader2Icon className="w-4 h-4 mr-2 animate-spin" />
                Checking export...
              </>
            ) : (
              <>
                <SendIcon className="w-4 h-4 mr-2" />
                Post Short
              </>
            )}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
