"use client";
/* eslint-disable @next/next/no-img-element */

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Check, Film, Images, Loader2, Sparkles, Trash2, UploadCloud } from "lucide-react";
import { useRouter } from "next/navigation";
import type { Theme, ThemeCategory } from "@/data/themes";

type CarouselOption = {
  id: number;
  name: string;
};

const CAROUSEL_OPTIONS: CarouselOption[] = [
  { id: 1, name: "Simple tweet cards monocolor" },
  { id: 2, name: "Quote cards monocolor paper" },
  { id: 3, name: "Tweet cards with photo background" },
  { id: 4, name: "Quote cards with highlight on paper" },
];

type UploadPreview = {
  file: File;
  url: string;
  type: "image" | "video";
};

type FeedbackState =
  | { type: "success"; text: string }
  | { type: "error"; text: string }
  | { type: "info"; text: string }
  | null;

type GenerationFormProps = {
  themes: ThemeCategory[];
};

const MAX_UPLOADS = 5;

export default function GenerationForm({ themes }: GenerationFormProps) {
  const router = useRouter();

  const [message, setMessage] = useState("");
  const [themeSearch, setThemeSearch] = useState("");
  const [selectedTheme, setSelectedTheme] = useState<Theme | null>(null);
  const [themeDropdownOpen, setThemeDropdownOpen] = useState(false);

  const [isVideo, setIsVideo] = useState(false);
  const [isCarousel, setIsCarousel] = useState(false);
  const [carouselCount, setCarouselCount] = useState("8");
  const [carouselDropdownOpen, setCarouselDropdownOpen] = useState(false);
  const [selectedCarouselOption, setSelectedCarouselOption] = useState<CarouselOption | null>(null);

  const [uploads, setUploads] = useState<UploadPreview[]>([]);
  const [selectedUploadIndex, setSelectedUploadIndex] = useState(0);

  const [feedback, setFeedback] = useState<FeedbackState>(null);
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [isProcessing, setIsProcessing] = useState(false);

  const pollRef = useRef<NodeJS.Timeout | null>(null);
  const uploadsRef = useRef<UploadPreview[]>([]);

  const filteredThemes = useMemo(() => {
    if (!themeSearch.trim()) {
      return themes;
    }
    const term = themeSearch.toLowerCase();
    return themes
      .map((category) => ({
        category: category.category,
        themes: category.themes.filter((theme) => theme.name.toLowerCase().includes(term)),
      }))
      .filter((category) => category.themes.length > 0);
  }, [themeSearch, themes]);

  const resetUploads = useCallback(() => {
    setUploads((prev) => {
      prev.forEach((item) => URL.revokeObjectURL(item.url));
      return [];
    });
    setSelectedUploadIndex(0);
  }, []);

  useEffect(() => {
    uploadsRef.current = uploads;
  }, [uploads]);

  useEffect(() => {
    const checkStatus = async () => {
      try {
        const response = await fetch("/api/check-webhook-status", {
          method: "GET",
        });
        if (response.ok) {
          const data = await response.json();
          if (data?.is_processing) {
            startPolling();
          }
        }
      } catch (error) {
        console.error("Initial status check error", error);
      }
    };

    checkStatus();

    return () => {
      if (pollRef.current) {
        clearInterval(pollRef.current);
      }
      // Only revoke object URLs on unmount; avoid state updates here to prevent render loops
      uploadsRef.current.forEach((item) => URL.revokeObjectURL(item.url));
    };
  }, []);

  const startPolling = useCallback(() => {
    if (pollRef.current) {
      clearInterval(pollRef.current);
    }

    setIsProcessing(true);

    pollRef.current = setInterval(async () => {
      try {
        const response = await fetch("/api/check-webhook-status", {
          method: "GET",
        });

        if (!response.ok) {
          return;
        }

        const data = await response.json();

        if (!data?.is_processing) {
          setIsProcessing(false);
          if (pollRef.current) {
            clearInterval(pollRef.current);
            pollRef.current = null;
          }
          setFeedback({ type: "success", text: "Webhook finished. Updating the post list." });
          if (typeof window !== "undefined") {
            window.dispatchEvent(new Event("topics:refresh"));
          }
        }
      } catch (error) {
        console.error("Webhook status check error", error);
      }
    }, 2000);
  }, [router]);

  const handleFilesChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const files = Array.from(event.target.files ?? []);
    if (!files.length) return;

    const remainingSlots = MAX_UPLOADS - uploads.length;
    if (remainingSlots <= 0) {
      setFeedback({ type: "info", text: `You can upload at most ${MAX_UPLOADS} media items.` });
      event.target.value = "";
      return;
    }

    const nextFiles = files.slice(0, remainingSlots).map<UploadPreview>((file) => ({
      file,
      url: URL.createObjectURL(file),
      type: file.type.startsWith("video") ? "video" : "image",
    }));

    setUploads((prev) => [...prev, ...nextFiles]);
    event.target.value = "";
  };

  const removeUpload = (index: number) => {
    setUploads((prev) => {
      if (!prev[index]) return prev;
      URL.revokeObjectURL(prev[index].url);
      const clone = [...prev];
      clone.splice(index, 1);
      if (selectedUploadIndex >= clone.length) {
        setSelectedUploadIndex(Math.max(0, clone.length - 1));
      }
      return clone;
    });
  };

  const handleGenerate = async () => {
    if (!message.trim() && uploads.length === 0) {
      setFeedback({ type: "error", text: "Please add a prompt or at least one media file." });
      return;
    }

    setFeedback(null);
    setIsSubmitting(true);

    const formData = new FormData();
    formData.append("message", message);
    formData.append("isVideo", String(isVideo));
    formData.append("showNumberInput", String(isCarousel));

    if (selectedTheme) {
      formData.append("themePrompt", selectedTheme.prompt);
      formData.append("theme_name", selectedTheme.name);
    }

    if (isCarousel) {
      formData.append("numberValue", carouselCount || "0");
      if (selectedCarouselOption) {
        formData.append("carouselOption", JSON.stringify(selectedCarouselOption));
      }
    }

    uploads.forEach((item) => {
      formData.append("photos[]", item.file);
    });

    try {
      const response = await fetch("/api/send-webhook", {
        method: "POST",
        body: formData,
      });

      const data = await response.json().catch(() => ({}));

      if (!response.ok || data?.success === false) {
        if (response.status === 429) {
          setFeedback({ type: "info", text: data?.message || "Previous webhook run is still in progress." });
          startPolling();
        } else {
          throw new Error(data?.message || "Something went wrong while sending the webhook.");
        }
      } else {
        setFeedback({ type: "success", text: "Webhook triggered, generation started." });
        setMessage("");
        setSelectedTheme(null);
        setThemeSearch("");
        setIsVideo(false);
        setIsCarousel(false);
        setCarouselCount("8");
        setSelectedCarouselOption(null);
        resetUploads();
        startPolling();
      }
    } catch (error) {
      console.error("Webhook submission error", error);
      const text = error instanceof Error ? error.message : "An unexpected error occurred.";
      setFeedback({ type: "error", text });
      setIsProcessing(false);
    } finally {
      setIsSubmitting(false);
    }
  };

  const currentPreview = uploads[selectedUploadIndex];

  return (
    <section className="rounded-3xl border border-white/10 bg-white p-6 shadow-2xl shadow-orange-500/10 dark:border-white/5 dark:bg-white/5">
      <header className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
        <div>
          <p className="text-sm uppercase tracking-[0.3em] text-orange-600 dark:text-orange-300">Workflow</p>
          <h2 className="text-2xl font-semibold text-slate-900 dark:text-white">Create new content</h2>
          <p className="text-sm text-slate-600 dark:text-slate-400">
            Write a prompt, pick a theme, optionally upload media, then hit Generate to trigger the webhook pipeline.
          </p>
        </div>
        {isProcessing ? (
          <div className="flex items-center gap-2 rounded-2xl bg-amber-500/10 px-4 py-2 text-xs font-semibold text-amber-700 dark:text-amber-200">
            <Loader2 className="h-4 w-4 animate-spin" />
            Webhook in progress
          </div>
        ) : null}
      </header>

      <div className="mt-6 space-y-4">
        <div className="flex flex-col gap-3 lg:flex-row lg:items-start">
          <div className="flex-1 rounded-2xl border border-slate-200 bg-white px-4 py-3 dark:border-white/10 dark:bg-white/5">
            <label className="text-xs uppercase tracking-[0.3em] text-slate-500 dark:text-slate-400">Prompt</label>
            <textarea
              value={message}
              onChange={(event) => setMessage(event.target.value)}
              className="mt-2 w-full bg-transparent text-base text-slate-900 outline-none dark:text-white"
              placeholder="Describe the campaign theme, tone of voice, or key talking points..."
              rows={3}
              disabled={isSubmitting}
            />
          </div>
          {!isCarousel ? (
            <div className="relative w-full lg:w-72">
              <button
                type="button"
                onClick={() => setThemeDropdownOpen((prev) => !prev)}
                className="flex w-full items-center justify-between rounded-2xl border border-white/10 bg-gradient-to-r from-orange-100 to-amber-100 px-3 py-3 text-orange-900 shadow-md shadow-orange-500/20"
                aria-expanded={themeDropdownOpen}
              >
                <span className="truncate text-sm font-semibold">
                  {selectedTheme ? selectedTheme.name : "Select a theme"}
                </span>
                <Sparkles className="h-4 w-4 text-orange-500" />
              </button>
              {themeDropdownOpen ? (
                <div className="absolute z-20 mt-2 max-h-64 w-full overflow-y-auto rounded-2xl border border-white/10 bg-white/95 text-slate-800 shadow-2xl shadow-orange-500/20">
                  <div className="sticky top-0 bg-white/90 p-3">
                    <input
                      type="text"
                      value={themeSearch}
                      onChange={(event) => setThemeSearch(event.target.value)}
                      placeholder="Search themes..."
                      className="w-full rounded-xl border border-slate-200 bg-white px-3 py-2 text-sm text-slate-800 outline-none focus:border-orange-400"
                    />
                  </div>
                  {filteredThemes.length === 0 ? (
                    <p className="px-4 py-3 text-sm text-slate-500">No results found.</p>
                  ) : (
                    filteredThemes.map((category) => (
                      <div key={category.category}>
                        <p className="border-b border-orange-100 bg-orange-50 px-4 py-2 text-xs font-semibold uppercase tracking-[0.3em] text-orange-500">
                          {category.category}
                        </p>
                        {category.themes.map((theme) => (
                          <button
                            key={theme.name}
                            type="button"
                            className="flex w-full items-center justify-between px-4 py-2 text-sm font-medium text-slate-700 hover:bg-orange-50"
                            onClick={() => {
                              setSelectedTheme(theme);
                              setThemeDropdownOpen(false);
                            }}
                          >
                            <span>{theme.name}</span>
                            {selectedTheme?.name === theme.name ? <Check className="h-4 w-4 text-orange-500" /> : null}
                          </button>
                        ))}
                      </div>
                    ))
                  )}
                </div>
              ) : null}
            </div>
          ) : null}
        </div>

        <div className="flex flex-wrap items-center gap-3 text-sm font-semibold text-slate-900 dark:text-white">
          <label className="inline-flex cursor-pointer items-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 dark:border-white/10">
            <input
              type="checkbox"
              className="size-4 accent-orange-500"
              checked={isVideo}
              onChange={(event) => {
                setIsVideo(event.target.checked);
                if (event.target.checked) {
                  setIsCarousel(false);
                }
              }}
              disabled={isSubmitting}
            />
            <Film className="h-4 w-4" />
            Video
          </label>
          <label className="inline-flex cursor-pointer items-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 dark:border-white/10">
            <input
              type="checkbox"
              className="size-4 accent-orange-500"
              checked={isCarousel}
              onChange={(event) => {
                setIsCarousel(event.target.checked);
                if (event.target.checked) {
                  setIsVideo(false);
                }
              }}
              disabled={isSubmitting}
            />
            <Images className="h-4 w-4" />
            Carousel
          </label>
          {!isCarousel ? (
            <label className="flex cursor-pointer items-center gap-2 rounded-2xl border border-slate-200 bg-slate-100 px-4 py-2 text-xs font-semibold uppercase tracking-[0.3em] text-slate-900 shadow-inner shadow-slate-200/10 transition hover:border-slate-300 dark:border-white/10 dark:bg-white/10 dark:text-white dark:shadow-white/10 dark:hover:border-white/40">
              <input
                type="file"
                accept="image/*,video/*"
                multiple
                className="hidden"
                onChange={handleFilesChange}
                disabled={isSubmitting}
              />
              <UploadCloud className="h-4 w-4" />
              Add media (max {MAX_UPLOADS})
            </label>
          ) : null}
        </div>

        {isCarousel ? (
          <div className="flex flex-col gap-3 rounded-2xl border border-slate-200 bg-white p-4 text-sm text-slate-900 dark:border-white/10 dark:bg-white/5 dark:text-white md:flex-row md:items-center">
            <div className="flex flex-1 flex-col gap-2">
              <span className="text-xs uppercase tracking-[0.3em] text-slate-500 dark:text-slate-400">Carousel type</span>
              <div className="relative">
                <button
                  type="button"
                  onClick={() => setCarouselDropdownOpen((prev) => !prev)}
                  className="flex w-full items-center justify-between rounded-2xl border border-slate-200 bg-slate-50 px-4 py-2 dark:border-white/10 dark:bg-white/10"
                >
                  <span>{selectedCarouselOption?.name ?? "Select an option"}</span>
                  <svg className="h-4 w-4 text-slate-700 dark:text-white" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                    <path d="m6 9 6 6 6-6" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
                  </svg>
                </button>
                {carouselDropdownOpen ? (
                  <div className="absolute z-10 mt-2 w-full rounded-2xl border border-slate-200 bg-white text-slate-800 shadow-2xl shadow-orange-500/20 dark:border-white/10 dark:bg-white/95">
                    {CAROUSEL_OPTIONS.map((option) => (
                      <button
                        key={option.id}
                        type="button"
                        className="flex w-full items-center justify-between px-4 py-2 text-left text-sm font-medium hover:bg-orange-50"
                        onClick={() => {
                          setSelectedCarouselOption(option);
                          setCarouselDropdownOpen(false);
                        }}
                      >
                        <span>{option.name}</span>
                        {selectedCarouselOption?.id === option.id ? <Check className="h-4 w-4 text-orange-500" /> : null}
                      </button>
                    ))}
                  </div>
                ) : null}
              </div>
            </div>
            <div className="flex flex-col gap-2">
              <span className="text-xs uppercase tracking-[0.3em] text-slate-500 dark:text-slate-400">Slide count</span>
              <input
                type="number"
                min="1"
                value={carouselCount}
                onChange={(event) => setCarouselCount(event.target.value)}
                className="w-24 rounded-2xl border border-slate-200 bg-white px-3 py-2 text-center text-slate-900 outline-none focus:border-orange-400 dark:border-white/10 dark:bg-slate-900/40 dark:text-white"
              />
            </div>
          </div>
        ) : null}

        {uploads.length > 0 ? (
          <div className="flex flex-col gap-4 rounded-2xl border border-dashed border-slate-200 p-4 dark:border-white/10">
            <div className="relative mx-auto h-64 w-64 overflow-hidden rounded-2xl border border-slate-200 dark:border-white/10">
              {currentPreview?.type === "image" ? (
                <img src={currentPreview.url} alt="preview" className="h-full w-full object-cover" />
              ) : currentPreview ? (
                <video src={currentPreview.url} className="h-full w-full object-cover" controls />
              ) : null}

              <button
                type="button"
                className="absolute right-3 top-3 rounded-full bg-rose-500/80 p-2 text-white"
                onClick={() => removeUpload(selectedUploadIndex)}
              >
                <Trash2 className="h-4 w-4" />
              </button>
            </div>
            {uploads.length > 1 ? (
              <div className="flex flex-wrap justify-center gap-2">
                {uploads.map((item, index) => (
                  <button
                    key={item.url}
                    type="button"
                    onClick={() => setSelectedUploadIndex(index)}
                    className={`h-16 w-16 overflow-hidden rounded-2xl border ${index === selectedUploadIndex ? "border-orange-500" : "border-slate-200 dark:border-white/10"
                      }`}
                  >
                    {item.type === "image" ? (
                      <img src={item.url} alt="thumb" className="h-full w-full object-cover" />
                    ) : (
                      <video src={item.url} className="h-full w-full object-cover" muted />
                    )}
                  </button>
                ))}
              </div>
            ) : null}
            <button
              type="button"
              onClick={() => resetUploads()}
              className="mx-auto flex items-center gap-2 rounded-2xl border border-slate-200 px-4 py-2 text-sm font-semibold text-slate-900 transition hover:border-slate-300 dark:border-white/10 dark:text-white dark:hover:border-white/40"
            >
              <Trash2 className="h-4 w-4" />
              Clear all media
            </button>
          </div>
        ) : null}

        {feedback ? (
          <div
            className={`rounded-2xl px-4 py-3 text-sm ${feedback.type === "success"
                ? "bg-emerald-500/10 text-emerald-700 dark:text-emerald-200"
                : feedback.type === "info"
                  ? "bg-amber-500/10 text-amber-700 dark:text-amber-200"
                  : "bg-rose-500/10 text-rose-700 dark:text-rose-200"
              }`}
          >
            {feedback.text}
          </div>
        ) : null}

        <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
          <p className="text-xs uppercase tracking-[0.3em] text-slate-500">
            {uploads.length} / {MAX_UPLOADS} media added
          </p>
          <button
            type="button"
            onClick={handleGenerate}
            disabled={isSubmitting || isProcessing}
            className="flex items-center justify-center rounded-2xl bg-gradient-to-r from-orange-500 to-amber-400 px-6 py-3 text-sm font-semibold text-white shadow-lg shadow-orange-500/30 transition hover:brightness-110 disabled:opacity-60"
          >
            {isSubmitting || isProcessing ? (
              <>
                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                Generating...
              </>
            ) : (
              <>
                <UploadCloud className="mr-2 h-4 w-4" />
                Generate
              </>
            )}
          </button>
        </div>
      </div>
    </section>
  );
}
