"use client";

import React, { useState, useRef } from "react";
import Image from "next/image";
import { ImagePlus, MapPin, VideoIcon, Vote } from "lucide-react";
import { Button } from "@/components/ui/button";
import { MdOutlineGifBox } from "react-icons/md";
import { useCloudinary } from "@/hooks/useCloudinary";
import { addPostAction } from "@/lib/actions/user";
import { unescapeMultipleStrings } from "@/lib/utils";
import { toast } from "sonner";

const MAX_POST_LENGTH = 280;
const MAX_MEDIA_COUNT = 4;
const MAX_TEXTAREA_ROWS = 4;

export interface PostEditorProps {
  placeHolderText?: string;
  PostButtonText?: string;
  token: string;
}

interface LinkPreview {
  url: string;
  title: string;
  description: string;
  imageUrl?: string;
}

const PostEditor: React.FC<PostEditorProps> = ({
  placeHolderText = "What's happening in your neighbourhood?",
  PostButtonText = "Post",
  token,
}) => {
  const [post, setPost] = useState("");
  const [media, setMedia] = useState<File[]>([]);
  const [linkPreview, setLinkPreview] = useState<LinkPreview | null>(null);
  const [linkPreviewFetched, setLinkPreviewFetched] = useState(false);
  const [posting, setPosting] = useState(false);

  const textareaRef = useRef<HTMLTextAreaElement>(null);

  const { uploadImage, uploading } = useCloudinary();

  const handlePostChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
    const newPost = e.target.value;
    setPost(newPost);
    resizeTextarea();
    checkForLinkPreview(newPost);
  };

  const handlePaste = (e: React.ClipboardEvent<HTMLTextAreaElement>) => {
    const clipboardItems = e.clipboardData.items;
    for (const item of Array.from(clipboardItems)) {
      if (item.type.includes("image") && media.length < MAX_MEDIA_COUNT) {
        const blob = item.getAsFile();
        if (blob) {
          setMedia((prevMedia) => [...prevMedia, blob]);
        }
      }
    }
  };

  const resizeTextarea = () => {
    const textarea = textareaRef.current;
    if (textarea) {
      textarea.style.height = "auto";
      const newHeight = Math.min(textarea.scrollHeight, MAX_TEXTAREA_ROWS * 30);
      textarea.style.height = `${newHeight}px`;

      if (newHeight >= MAX_TEXTAREA_ROWS * 30) {
        textarea.style.overflowY = "auto";
      } else {
        textarea.style.overflowY = "hidden";
      }
    }
  };

  const handleMediaChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files) {
      const filesArray = Array.from(e.target.files).slice(
        0,
        MAX_MEDIA_COUNT - media.length
      );
      setMedia((prevMedia) =>
        [...prevMedia, ...filesArray].slice(0, MAX_MEDIA_COUNT)
      );
    }
  };

  const isPostValid =
    (post.length > 0 && post.length <= MAX_POST_LENGTH) || media.length;

  const handlePostSubmit = async () => {
    try {
      if (!token) return;
      setPosting(true);

      if (isPostValid) {
        // Upload images to Cloudinary
        const uploadPromises = media.map((file) => uploadImage(file));
        const urls = await Promise.all(uploadPromises);
        if (urls) {
          const uploadedMediaUrls = urls.filter(
            (url) => url !== null
          ) as string[];

          console.log("Post submitted:", post, uploadedMediaUrls, linkPreview);
          const res = await addPostAction(
            {
              images: JSON.stringify(uploadedMediaUrls),
              location: "Ahoada, Rivers",
              post,
            },
            token
          );
          if (res?.data) {
            toast.success("Post uploaded successfully!");
            setPost("");
            setMedia([]);
            setLinkPreview(null);
            setLinkPreviewFetched(false);

            if (textareaRef.current) {
              textareaRef.current.style.height = "auto";
            }
          }
        }
      }
    } catch (error) {
      console.error(error);
      toast.error("An error occurred while uploading post");
    } finally {
      setPosting(false);
    }
  };

  // Fetch link preview from the Next.js API route
  const fetchLinkPreview = async (url: string) => {
    try {
      const response = await fetch(
        `/api/link-preview?url=${encodeURIComponent(url)}`
      );
      const data = await response.json();

      if (data.error) {
        setLinkPreview(null);
        return;
      }

      const { title, description, image } = data;
      setLinkPreview({
        url,
        title,
        description,
        imageUrl: image,
      });
      setLinkPreviewFetched(true); // Mark that link preview has been fetched
    } catch (error) {
      console.error("Error fetching link preview:", error);
      setLinkPreview(null);
      setLinkPreviewFetched(true); // Even if it fails, mark it as fetched
    }
  };

  // Function to check for a link in the post text and generate a preview
  const checkForLinkPreview = (text: string) => {
    const urlRegex = /(https?:\/\/[^\s]+)/g;
    const match = text.match(urlRegex);

    if (match && match[0]) {
      const url = match[0];
      if (!linkPreviewFetched) {
        fetchLinkPreview(url); // Fetch metadata for the detected link only if not already fetched
      }
    } else {
      setLinkPreview(null);
      setLinkPreviewFetched(false); // Reset flag if no link is present
    }
  };

  return (
    <div className="bg-white">
      <div className="flex items-start space-x-2">
        {/* User Avatar */}
        <Image
          height={500}
          width={500}
          src="/assets/images/interior2.webp"
          alt="User Avatar"
          className="w-10 h-10 rounded-full"
        />

        {/* Post Input Area */}
        <div className="flex-1">
          <textarea
            ref={textareaRef}
            value={post}
            onChange={handlePostChange}
            onPaste={handlePaste}
            placeholder={placeHolderText}
            className="w-full border-none resize-none focus:ring-0 focus:outline-none text-lg placeholder-neutral-600"
            rows={1}
            maxLength={MAX_POST_LENGTH}
            style={{ height: "auto" }}
          />

          {/* Media Preview */}
          <div className="mt-2 grid grid-cols-2 gap-2">
            {media.map((file, index) => (
              <div key={index} className="relative">
                <Image
                  height={500}
                  width={500}
                  src={URL.createObjectURL(file)}
                  alt={`Selected media ${index + 1}`}
                  className="w-full rounded-lg"
                />
                <button
                  onClick={() =>
                    setMedia((prevMedia) =>
                      prevMedia.filter((_, i) => i !== index)
                    )
                  }
                  className="absolute top-1 right-1 bg-black text-white p-1 rounded-full"
                >
                  ✕
                </button>
              </div>
            ))}
          </div>

          {/* Link Preview */}
          {linkPreview && (
            <div className="border rounded-lg mt-2 p-4 flex space-x-4">
              <Image
                height={500}
                width={500}
                src={linkPreview.imageUrl || ""}
                alt="Link preview"
                className="w-16 h-16 rounded-lg"
              />
              <div>
                <a
                  href={linkPreview.url}
                  target="_blank"
                  rel="noopener noreferrer"
                  className="text-primary font-bold"
                >
                  {linkPreview.title}
                </a>
                <p className="text-neutral-700 truncate-text-2">
                  {linkPreview.description}
                </p>
              </div>
            </div>
          )}

          {/* Media and Other Actions */}
          <div className="flex items-center justify-between mt-4">
            <div className="flex items-center space-x-1">
              {media.length < MAX_MEDIA_COUNT && (
                <label className="cursor-pointer text-primary hover:text-primary">
                  <input
                    type="file"
                    accept="image/*"
                    multiple
                    className="hidden"
                    onChange={handleMediaChange}
                  />
                  <Button variant={"ghost"} size={"icon"}>
                    <ImagePlus className="icon !m-0" />
                  </Button>
                </label>
              )}
              <label className="cursor-pointer text-primary hover:text-primary">
                <input
                  type="file"
                  accept="image/*"
                  multiple
                  className="hidden"
                  onChange={handleMediaChange}
                />

                <Button variant={"ghost"} size={"icon"}>
                  <MdOutlineGifBox className="icon !m-0" />
                </Button>
              </label>
              <label className="cursor-pointer text-primary hover:text-primary">
                <input
                  type="file"
                  accept="image/*"
                  multiple
                  className="hidden"
                  onChange={handleMediaChange}
                />

                <Button variant={"ghost"} size={"icon"}>
                  <Vote className="icon !m-0" />
                </Button>
              </label>
              <label className="cursor-pointer text-primary hover:text-primary">
                <input
                  type="file"
                  accept="image/*"
                  multiple
                  className="hidden"
                  onChange={handleMediaChange}
                />

                <Button variant={"ghost"} size={"icon"}>
                  <MapPin className="icon !m-0" />
                </Button>
              </label>
              <label className="cursor-pointer text-primary hover:text-primary">
                <input
                  type="file"
                  accept="video/*"
                  multiple
                  className="hidden"
                  onChange={handleMediaChange}
                />

                <Button variant={"ghost"} size={"icon"}>
                  <VideoIcon className="icon !m-0" />
                </Button>
              </label>
            </div>

            {/* Submit Button */}
            <Button
              onClick={handlePostSubmit}
              className={`ml-2 font-medium bg-primary text-white ${
                !isPostValid && "opacity-50 cursor-not-allowed"
              }`}
              disabled={!isPostValid || posting}
            >
              {PostButtonText}
            </Button>
          </div>
        </div>
      </div>
    </div>
  );
};

export default PostEditor;
