import { Show, createSignal, createEffect, onCleanup } from "solid-js";
import { useNavigate } from "@solidjs/router";
import { api } from "~/lib/api";
import { debounce } from "es-toolkit";
import Dropzone from "~/components/blog/Dropzone";
import TextEditor from "~/components/blog/TextEditor";
import TagMaker from "~/components/blog/TagMaker";
import AddAttachmentSection from "~/components/blog/AddAttachmentSection";
import XCircle from "~/components/icons/XCircle";
import AddImageToS3 from "~/lib/s3upload";

interface PostFormProps {
  mode: "create" | "edit";
  postId?: number;
  initialData?: {
    title: string;
    subtitle: string;
    body: string;
    banner_photo: string;
    published: boolean;
    tags: string[];
  };
  userID: number;
}

export default function PostForm(props: PostFormProps) {
  const navigate = useNavigate();

  const [title, setTitle] = createSignal(props.initialData?.title || "");
  const [subtitle, setSubtitle] = createSignal(
    props.initialData?.subtitle || ""
  );
  const [body, setBody] = createSignal(props.initialData?.body || "");
  const [bannerPhoto, setBannerPhoto] = createSignal(
    props.initialData?.banner_photo || ""
  );
  const [bannerImageFile, setBannerImageFile] = createSignal<File>();
  const [bannerImageHolder, setBannerImageHolder] = createSignal<
    string | ArrayBuffer | null
  >(null);
  const [requestedDeleteImage, setRequestedDeleteImage] = createSignal(false);
  const [published, setPublished] = createSignal(
    props.initialData?.published || false
  );
  const [tags, setTags] = createSignal<string[]>(props.initialData?.tags || []);
  const [tagInputValue, setTagInputValue] = createSignal("");
  const [loading, setLoading] = createSignal(false);
  const [error, setError] = createSignal("");
  const [showAutoSaveMessage, setShowAutoSaveMessage] = createSignal(false);
  const [isInitialLoad, setIsInitialLoad] = createSignal(props.mode === "edit");
  const [initialBody, setInitialBody] = createSignal<string | undefined>(
    props.initialData?.body
  );
  const [hasSaved, setHasSaved] = createSignal(props.mode === "edit");

  // Mark initial load as complete after data is loaded (for edit mode)
  createEffect(() => {
    if (props.mode === "edit" && props.initialData) {
      setIsInitialLoad(false);
    }
  });

  const autoSave = async () => {
    const titleVal = title();

    if (titleVal) {
      try {
        let bannerImageKey = "";
        const bannerFile = bannerImageFile();
        if (bannerFile) {
          bannerImageKey = (await AddImageToS3(
            bannerFile,
            titleVal,
            "blog"
          )) as string;
        }

        if (props.mode === "edit") {
          await api.database.updatePost.mutate({
            id: props.postId!,
            title: titleVal.replaceAll(" ", "_"),
            subtitle: subtitle() || null,
            body: body() || null,
            banner_photo:
              bannerImageKey !== ""
                ? bannerImageKey
                : requestedDeleteImage()
                  ? "_DELETE_IMAGE_"
                  : null,
            published: published(),
            tags: tags().length > 0 ? tags() : null,
            author_id: props.userID
          });
        } else {
          // Create mode: only save once
          if (!hasSaved()) {
            await api.database.createPost.mutate({
              category: "blog",
              title: titleVal.replaceAll(" ", "_"),
              subtitle: subtitle() || null,
              body: body() || null,
              banner_photo: bannerImageKey !== "" ? bannerImageKey : null,
              published: published(),
              tags: tags().length > 0 ? tags() : null,
              author_id: props.userID
            });
            setHasSaved(true);
          }
        }

        showAutoSaveTrigger();
      } catch (err) {
        console.error("Autosave failed:", err);
      }
    }
  };

  const showAutoSaveTrigger = () => {
    setShowAutoSaveMessage(true);
    setTimeout(() => {
      setShowAutoSaveMessage(false);
    }, 5000);
  };

  // Debounced auto-save (1 second after last change)
  const debouncedAutoSave = debounce(autoSave, 1000);

  // Track changes to trigger auto-save
  createEffect(() => {
    const titleVal = title();
    const subtitleVal = subtitle();
    const bodyVal = body();
    const tagsVal = tags();
    const publishedVal = published();

    // Only trigger auto-save if conditions are met
    if (props.mode === "edit" && !isInitialLoad() && titleVal) {
      debouncedAutoSave();
    } else if (props.mode === "create" && titleVal) {
      debouncedAutoSave();
    }
  });

  onCleanup(() => {
    debouncedAutoSave.cancel();
  });

  const handleBannerImageDrop = (acceptedFiles: File[]) => {
    if (acceptedFiles.length > 0) {
      const file = acceptedFiles[0];
      if (props.mode === "edit") {
        setRequestedDeleteImage(false);
      }
      setBannerImageFile(file);
      const reader = new FileReader();
      reader.onload = () => {
        setBannerImageHolder(reader.result);
      };
      reader.readAsDataURL(file);
    }
  };

  const removeBannerImage = () => {
    setBannerImageFile(undefined);
    setBannerImageHolder(null);
    if (props.mode === "edit") {
      setRequestedDeleteImage(true);
    }
  };

  const tagHandler = (input: string) => {
    const split = input.split(" ");
    if (split.length > 1) {
      const newSplit: string[] = [];
      split.forEach((word) => {
        if (word[0] === "#" && word.length > 1) {
          setTags((prevTags) => [...prevTags, word]);
        } else {
          newSplit.push(word);
        }
      });
      setTagInputValue(newSplit.join(" "));
    } else {
      setTagInputValue(input);
    }
  };

  const deleteTag = (idx: number) => {
    setTags((prevTags) => prevTags.filter((_, index) => index !== idx));
  };

  const handleSubmit = async (e: Event) => {
    e.preventDefault();

    if (!props.userID) {
      setError(`You must be logged in to ${props.mode} posts`);
      return;
    }

    if (!title()) {
      setError("Title is required to publish");
      return;
    }

    setLoading(true);
    setError("");

    try {
      let bannerImageKey = "";
      const bannerFile = bannerImageFile();
      if (bannerFile) {
        bannerImageKey = (await AddImageToS3(
          bannerFile,
          title(),
          "blog"
        )) as string;
      }

      if (props.mode === "edit") {
        await api.database.updatePost.mutate({
          id: props.postId!,
          title: title().replaceAll(" ", "_"),
          subtitle: subtitle() || null,
          body: body() || null,
          banner_photo:
            bannerImageKey !== ""
              ? bannerImageKey
              : requestedDeleteImage()
                ? "_DELETE_IMAGE_"
                : null,
          published: published(),
          tags: tags().length > 0 ? tags() : null,
          author_id: props.userID
        });
      } else {
        await api.database.createPost.mutate({
          category: "blog",
          title: title().replaceAll(" ", "_"),
          subtitle: subtitle() || null,
          body: body() || null,
          banner_photo: bannerImageKey !== "" ? bannerImageKey : null,
          published: published(),
          tags: tags().length > 0 ? tags() : null,
          author_id: props.userID
        });
      }

      navigate(`/blog/${encodeURIComponent(title().replaceAll(" ", "_"))}`);
    } catch (err) {
      console.error(`Error ${props.mode}ing post:`, err);
      setError(`Failed to ${props.mode} post. Please try again.`);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div class="bg-base text-text min-h-screen px-8 py-32">
      <div class="text-center text-2xl tracking-wide">
        {props.mode === "edit" ? "Edit a Blog" : "Create a Blog"}
      </div>
      <div class="flex h-full w-full justify-center">
        <form onSubmit={handleSubmit} class="w-full md:w-3/4 lg:w-1/3 xl:w-1/2">
          {/* Title */}
          <div class="input-group mx-4">
            <input
              type="text"
              value={title()}
              onInput={(e) => setTitle(e.currentTarget.value)}
              name="title"
              placeholder=" "
              class="underlinedInput w-full bg-transparent"
            />
            <span class="bar"></span>
            <label class="underlinedInputLabel">Title</label>
          </div>

          {/* Subtitle */}
          <div class="input-group mx-4">
            <input
              type="text"
              value={subtitle()}
              onInput={(e) => setSubtitle(e.currentTarget.value)}
              name="subtitle"
              placeholder=" "
              class="underlinedInput w-full bg-transparent"
            />
            <span class="bar"></span>
            <label class="underlinedInputLabel">Subtitle</label>
          </div>

          {/* Banner */}
          <div class="pt-8 text-center text-xl">Banner</div>
          <div class="flex justify-center pb-8">
            <Dropzone
              onDrop={handleBannerImageDrop}
              accept="image/jpg, image/jpeg, image/png"
              fileHolder={bannerImageHolder()}
              preSet={
                props.mode === "edit" && !requestedDeleteImage()
                  ? bannerPhoto() || null
                  : null
              }
            />
            <button
              type="button"
              class="z-50 -ml-6 h-fit rounded-full"
              onClick={removeBannerImage}
            >
              <XCircle
                height={36}
                width={36}
                stroke={"currentColor"}
                strokeWidth={1}
              />
            </button>
          </div>

          {/* Attachments */}
          <AddAttachmentSection
            type="blog"
            postId={props.postId}
            postTitle={title()}
            existingAttachments={
              props.mode === "edit" && props.initialData
                ? (props.initialData as any)?.attachments
                : undefined
            }
          />

          {/* Text Editor */}
          <div class="-mx-6 md:-mx-36">
            <TextEditor updateContent={setBody} preSet={initialBody()} />
          </div>

          {/* Tags */}
          <TagMaker
            tagInputValue={tagInputValue()}
            tagHandler={tagHandler}
            tags={tags()}
            deleteTag={deleteTag}
          />

          {/* Auto-save message */}
          <div
            class={`${
              showAutoSaveMessage() ? "" : "user-select opacity-0"
            } text-green flex min-h-4 justify-center text-center italic transition-opacity duration-500 ease-in-out`}
          >
            {showAutoSaveMessage() ? "Auto save success!" : ""}
          </div>

          {/* Publish checkbox */}
          <div class="flex justify-end pt-4 pb-2">
            <input
              type="checkbox"
              class="my-auto"
              name="publish"
              checked={published()}
              onChange={(e) => setPublished(e.currentTarget.checked)}
            />
            <div class="my-auto px-2 text-sm font-normal">Published</div>
          </div>

          {/* Error message */}
          <Show when={error()}>
            <div class="text-red text-sm">{error()}</div>
          </Show>

          {/* Submit button */}
          <div class="flex justify-end">
            <button
              type="submit"
              disabled={loading()}
              class={`${
                loading()
                  ? "bg-surface2 cursor-not-allowed"
                  : published()
                    ? "bg-peach hover:brightness-125"
                    : "bg-green hover:brightness-125"
              } text-crust flex w-36 justify-center rounded py-3 transition-all duration-300 ease-out active:scale-90`}
            >
              {loading()
                ? "Loading..."
                : published()
                  ? "Publish!"
                  : "Save as Draft"}
            </button>
          </div>
        </form>
      </div>
      <Show when={props.mode === "edit"}>
        <div class="mt-2 flex justify-center">
          <a
            href={`/blog/${encodeURIComponent(title().replaceAll(" ", "_"))}`}
            class="border-blue bg-blue hover:bg-blue rounded border px-4 py-2 shadow-md transition-all duration-300 ease-in-out hover:brightness-125 active:scale-90"
          >
            Go to Post
          </a>
        </div>
      </Show>
    </div>
  );
}
