import { useEffect, useRef, useState } from "react";
import {
  MdAdd,
  MdClose,
  MdContentCopy,
  MdDelete,
  MdOutlineInfo,
} from "react-icons/md";
import { Tag } from "../network/models.ts";
import { network } from "../network/network.ts";
import { useNavigate } from "react-router";
import { useTranslation } from "react-i18next";
import { app } from "../app.ts";
import { ErrorAlert } from "../components/alert.tsx";
import { useAppContext } from "../components/AppContext.tsx";
import TagInput, { QuickAddTagDialog } from "../components/tag_input.tsx";
import {
  ImageDropArea,
  SelectAndUploadImageButton,
  UploadClipboardImageButton,
} from "../components/image_selector.tsx";

export default function PublishPage() {
  const [title, setTitle] = useState<string>("");
  const [altTitles, setAltTitles] = useState<string[]>([]);
  const [tags, setTags] = useState<Tag[]>([]);
  const [article, setArticle] = useState<string>("");
  const [images, setImages] = useState<number[]>([]);
  const [links, setLinks] = useState<{ label: string; url: string }[]>([]);
  const [error, setError] = useState<string | null>(null);
  const [isSubmitting, setSubmitting] = useState(false);

  const isFirstLoad = useRef(true);

  useEffect(() => {
    if (isFirstLoad.current) {
      const oldData = localStorage.getItem("publish_data");
      if (oldData) {
        try {
          const data = JSON.parse(oldData);
          setTitle(data.title || "");
          setAltTitles(data.alternative_titles || []);
          setTags(data.tags || []);
          setArticle(data.article || "");
          setImages(data.images || []);
        } catch (e) {
          console.error("Failed to parse publish_data from localStorage", e);
        }
      }
      isFirstLoad.current = false;
    } else {
      const data = {
        title: title,
        alternative_titles: altTitles,
        tags: tags,
        article: article,
        images: images,
      };
      const dataString = JSON.stringify(data);
      localStorage.setItem("publish_data", dataString);
    }
  }, [altTitles, article, images, tags, title]);

  const navigate = useNavigate();
  const { t } = useTranslation();

  const appContext = useAppContext();

  useEffect(() => {
    document.title = t("Publish Resource");
  }, [t]);

  const handleSubmit = async () => {
    if (isSubmitting) {
      return;
    }
    if (!title) {
      setError(t("Title cannot be empty"));
      return;
    }
    for (let i = 0; i < altTitles.length; i++) {
      if (!altTitles[i]) {
        setError(t("Alternative title cannot be empty"));
        return;
      }
    }
    for (let i = 0; i < links.length; i++) {
      if (!links[i].label || !links[i].url) {
        setError(t("Link cannot be empty"));
        return;
      }
    }
    if (!tags || tags.length === 0) {
      setError(t("At least one tag required"));
      return;
    }
    if (!article) {
      setError(t("Description cannot be empty"));
      return;
    }
    setSubmitting(true);
    const res = await network.createResource({
      title: title,
      alternative_titles: altTitles,
      tags: tags.map((tag) => tag.id),
      article: article,
      images: images,
      links: links,
    });
    if (res.success) {
      localStorage.removeItem("publish_data");
      setSubmitting(false);
      appContext.clear();
      navigate("/resources/" + res.data!, { replace: true });
    } else {
      setSubmitting(false);
      setError(res.message);
    }
  };

  if (!app.user) {
    return (
      <ErrorAlert
        className={"m-4"}
        message={t("You are not logged in. Please log in to access this page.")}
      />
    );
  }

  if (!app.canUpload()) {
    return (
      <ErrorAlert
        className={"m-4"}
        message={t("You are not authorized to access this page.")}
      />
    );
  }

  return (
    <ImageDropArea
      onUploaded={(images) => {
        setImages((prev) => [...prev, ...images]);
      }}
    >
      <div className={"p-4"}>
        <h1 className={"text-2xl font-bold my-4"}>{t("Publish Resource")}</h1>
        <div role="alert" className="alert alert-info mb-2 alert-dash">
          <MdOutlineInfo size={24} />
          <span>{t("All information can be modified after publishing")}</span>
        </div>
        <p className={"my-1"}>{t("Title")}</p>
        <input
          type="text"
          className="input w-full"
          value={title}
          onChange={(e) => setTitle(e.target.value)}
        />
        <div className={"h-4"}></div>
        <p className={"my-1"}>{t("Alternative Titles")}</p>
        {altTitles.map((title, index) => {
          return (
            <div key={index} className={"flex items-center my-2"}>
              <input
                type="text"
                className="input w-full"
                value={title}
                onChange={(e) => {
                  const newAltTitles = [...altTitles];
                  newAltTitles[index] = e.target.value;
                  setAltTitles(newAltTitles);
                }}
              />
              <button
                className={"btn btn-square btn-error ml-2"}
                type={"button"}
                onClick={() => {
                  const newAltTitles = [...altTitles];
                  newAltTitles.splice(index, 1);
                  setAltTitles(newAltTitles);
                }}
              >
                <MdDelete size={24} />
              </button>
            </div>
          );
        })}
        <button
          className={"btn my-2"}
          type={"button"}
          onClick={() => {
            setAltTitles([...altTitles, ""]);
          }}
        >
          <MdAdd />
          {t("Add Alternative Title")}
        </button>
        <div className={"h-2"}></div>
        <p className={"my-1"}>{t("Links")}</p>
        <div className={"flex flex-col"}>
          {links.map((link, index) => {
            return (
              <div key={index} className={"flex items-center my-2"}>
                <input
                  type="text"
                  className="input"
                  placeholder={t("Label")}
                  value={link.label}
                  onChange={(e) => {
                    const newLinks = [...links];
                    newLinks[index].label = e.target.value;
                    setLinks(newLinks);
                  }}
                />
                <input
                  type="text"
                  className="input w-full ml-2"
                  placeholder={t("URL")}
                  value={link.url}
                  onChange={(e) => {
                    const newLinks = [...links];
                    newLinks[index].url = e.target.value;
                    setLinks(newLinks);
                  }}
                />
                <button
                  className={"btn btn-square btn-error ml-2"}
                  type={"button"}
                  onClick={() => {
                    const newLinks = [...links];
                    newLinks.splice(index, 1);
                    setLinks(newLinks);
                  }}
                >
                  <MdDelete size={24} />
                </button>
              </div>
            );
          })}
          <div className={"flex"}>
            <button
              className={"btn my-2"}
              type={"button"}
              onClick={() => {
                setLinks([...links, { label: "", url: "" }]);
              }}
            >
              <MdAdd />
              {t("Add Link")}
            </button>
          </div>
        </div>
        <div className={"h-2"}></div>
        <p className={"my-1"}>{t("Tags")}</p>
        <p className={"my-1 pb-1"}>
          {tags.map((tag, index) => {
            return (
              <span key={index} className={"badge badge-primary mr-2 text-sm"}>
                {tag.name}
                <span
                  onClick={() => {
                    const newTags = [...tags];
                    newTags.splice(index, 1);
                    setTags(newTags);
                  }}
                >
                  <MdClose size={18} />
                </span>
              </span>
            );
          })}
        </p>
        <div className={"flex items-center"}>
          <TagInput
            onAdd={(tag) => {
              setTags((prev) => {
                const existingTag = prev.find((t) => t.id === tag.id);
                if (existingTag) {
                  return prev; // If the tag already exists, do not add it again
                }
                return [...prev, tag];
              });
            }}
          />
          <span className={"w-4"} />
          <QuickAddTagDialog
            onAdded={(tags) => {
              setTags((prev) => {
                const newTags = [...prev];
                for (const tag of tags) {
                  const existingTag = newTags.find((t) => t.id === tag.id);
                  if (!existingTag) {
                    newTags.push(tag);
                  }
                }
                return newTags;
              });
            }}
          />
        </div>
        <div className={"h-4"}></div>
        <p className={"my-1"}>{t("Description")}</p>
        <textarea
          className="textarea w-full min-h-80 p-4"
          value={article}
          onChange={(e) => setArticle(e.target.value)}
        />
        <div className={"flex items-center py-1 "}>
          <MdOutlineInfo className={"inline mr-1"} />
          <span className={"text-sm"}>{t("Use markdown format")}</span>
        </div>
        <div className={"h-4"}></div>
        <p className={"my-1"}>{t("Images")}</p>
        <div role="alert" className="alert alert-info alert-soft my-2">
          <MdOutlineInfo size={24} />
          <div>
            <p>
              {t(
                "Images will not be displayed automatically, you need to reference them in the description",
              )}
            </p>
            <p>{t("The first image will be used as the cover image")}</p>
          </div>
        </div>
        <div
          className={`rounded-box border border-base-content/5 bg-base-100 ${images.length === 0 ? "hidden" : ""}`}
        >
          <table className={"table"}>
            <thead>
              <tr>
                <td>{t("Preview")}</td>
                <td>{"Markdown"}</td>
                <td>{t("Action")}</td>
              </tr>
            </thead>
            <tbody>
              {images.map((image, index) => {
                return (
                  <tr key={index} className={"hover"}>
                    <td>
                      <img
                        src={network.getImageUrl(image)}
                        className={"w-16 h-16 object-cover card"}
                        alt={"image"}
                      />
                    </td>
                    <td>
                      <span>{`![](${network.getImageUrl(image)})`}</span>
                      <button
                        className={"btn btn-sm btn-circle btn-ghost ml-1"}
                        onClick={() => {
                          navigator.clipboard.writeText(
                            `![](${network.getImageUrl(image)})`,
                          );
                        }}
                      >
                        <MdContentCopy />
                      </button>
                    </td>
                    <td>
                      <button
                        className={"btn btn-square"}
                        type={"button"}
                        onClick={() => {
                          const id = images[index];
                          const newImages = [...images];
                          newImages.splice(index, 1);
                          setImages(newImages);
                          network.deleteImage(id);
                        }}
                      >
                        <MdDelete size={24} />
                      </button>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
        <div className={"flex"}>
          <SelectAndUploadImageButton
            onUploaded={(images) => {
              setImages((prev) => [...prev, ...images]);
            }}
          />
          <span className={"w-4"}></span>
          <UploadClipboardImageButton
            onUploaded={(images) => {
              setImages((prev) => [...prev, ...images]);
            }}
          />
        </div>
        <div className={"h-4"}></div>
        {error && (
          <div role="alert" className="alert alert-error my-2 shadow">
            <svg
              xmlns="http://www.w3.org/2000/svg"
              className="h-6 w-6 shrink-0 stroke-current"
              fill="none"
              viewBox="0 0 24 24"
            >
              <path
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="2"
                d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
              />
            </svg>
            <span>
              {t("Error")}: {error}
            </span>
          </div>
        )}
        <div className={"flex flex-row-reverse mt-4"}>
          <button className={"btn btn-accent shadow"} onClick={handleSubmit}>
            {isSubmitting && <span className="loading loading-spinner"></span>}
            {t("Publish")}
          </button>
        </div>
      </div>
    </ImageDropArea>
  );
}
