import clsx from "clsx";
import { useEffect, useState } from "react";
import { useNavigate } from "react-router";
import {
  createBannerURL,
  createIconURL,
  createPostRevisionPageURL,
  createPostURL,
  createProfileTagURL,
  createProfilePageURL,
} from "#lib/urls";
import { ImageBackground, ImageLink } from "#components/images";
import { KemonoLink } from "#components/links";
import { IPaySite } from "#entities/paysites";
import {
  addPostToFavourites,
  isFavouritePost,
  isRegisteredAccount,
  removePostFromFavourites,
} from "#entities/account";
import { IPostActionsProps, IPostOverviewProps } from "./types";
import { FlagButton } from "./flag-button";
import { Timestamp } from "#components/dates";

interface IPostHeaderProps
  extends Pick<
    IPostOverviewProps,
    "post" | "profile" | "revisions" | "flagged"
  > {
  postTitle: string;
  paysite: IPaySite;
}

export function PostHeader({
  post,
  profile,
  postTitle,
  paysite,
  revisions,
  flagged,
}: IPostHeaderProps) {
  const navigate = useNavigate();
  const profileURL = String(
    createProfilePageURL({ service: post.service, profileID: post.user })
  );
  const profileIcon = createIconURL(post.service, post.user);
  const bannerURL = createBannerURL(post.service, post.user);

  return (
    <header className="post__header">
      <div className="post__user">
        <ImageBackground src={bannerURL} />
        <ImageLink
          url={profileURL}
          src={profileIcon}
          isLazy={false}
          className="post__user-profile"
        />

        <div>
          <KemonoLink className="post__user-name" url={profileURL}>
            {!profile ? `Profile page` : profile.name}
          </KemonoLink>
        </div>
      </div>

      <div className="post__info">
        <h1 className="post__title">
          <span>{postTitle}</span> <span>({paysite.title})</span>
        </h1>

        {!post.published ? undefined : (
          <div className="post__published" style={{ margin: "0.125rem 0" }}>
            <div style={{ width: "89px", display: "inline-block" }}>
              Published:
            </div>{" "}
            <Timestamp time={post.published} />
          </div>
        )}

        {!post.edited || post.edited === post.published ? undefined : (
          <div className="post__edited" style={{ margin: "0.125rem 0" }}>
            <div style={{ display: "inline-block", width: "89px" }}>
              Edited:
            </div>{" "}
            <Timestamp time={post.edited} />
          </div>
        )}

        <div className="post__added" style={{ margin: "0.125rem 0" }}>
          {revisions.length < 2 ? (
            <span>
              <div style={{ width: "89px", display: "inline-block" }}>
                Imported:{" "}
              </div>{" "}
              {post.added?.slice(0, 7) ?? "Unknown"}
            </span>
          ) : (
            <>
              <div
                style={{
                  display: "inline-block",
                  width: "85px",
                  margin: "0",
                }}
              >
                Imported:
              </div>
              <span
                className="post__revisions"
                title="View past versions of this page"
              >
                <select
                  id="post-revision-selection"
                  style={{ textAlignLast: "left" }}
                  defaultValue={post.revision_id}
                  onChange={(event) => {
                    const revisionID = event.currentTarget.value;

                    if (revisionID) {
                      navigate(
                        String(
                          createPostRevisionPageURL(
                            post.service,
                            post.user,
                            post.id,
                            revisionID
                          )
                        )
                      );
                    } else {
                      navigate(
                        String(createPostURL(post.service, post.user, post.id))
                      );
                    }
                  }}
                >
                  {revisions.map(([index, postRevision]) => (
                    <option key={index} value={postRevision.revision_id ?? ""}>
                      {postRevision.added?.slice(0, 7) ?? "Unknown"} {"<"}
                      {index}
                      {">"} [{postRevision.revision_id ?? "current"}]
                    </option>
                  ))}
                </select>
              </span>
            </>
          )}
        </div>

        {post.tags && post.tags.length !== 0 && (
          <section id="post-tags">
            <span id="label">Tags: </span>
            <div>
              {post.tags.map((tag, index) => (
                <a
                  key={index}
                  href={String(
                    createProfileTagURL(post.service, post.user, tag)
                  )}
                >
                  {tag}
                </a>
              ))}
            </div>
          </section>
        )}

        <PostActions
          service={post.service}
          profileID={post.user}
          postID={post.id}
          flagged={flagged}
        />
      </div>
    </header>
  );
}

function PostActions({
  service,
  profileID,
  postID,
  flagged,
}: IPostActionsProps) {
  return (
    <div className="post__actions">
      <FavoriteButton service={service} profileID={profileID} postID={postID} />
      <FlagButton service={service} profileID={profileID} postID={postID} flagged={flagged} />
    </div>
  );
}

interface IFavoriteButtonProps {
  service: string;
  profileID: string;
  postID: string;
}

function FavoriteButton({ service, profileID, postID }: IFavoriteButtonProps) {
  const [isFavorite, switchFavorite] = useState(false);
  const [isLoading, switchLoading] = useState(true);
  const renderKey = `${postID}${profileID}${service}`;

  useEffect(() => {
    (async () => {
      try {
        switchLoading(true);

        const isLoggedIn = await isRegisteredAccount();

        if (!isLoggedIn) {
          return;
        }

        const isFav = await isFavouritePost(service, profileID, postID);

        switchFavorite(isFav);
      } catch (error) {
        // TODO: better error handling
        console.error(error);
      } finally {
        switchLoading(false);
      }
    })();
  }, [service, profileID, postID]);

  async function handleFavorite() {
    try {
      switchLoading(true);
      await addPostToFavourites(service, profileID, postID);
      switchFavorite(true);
    } catch (error) {
      // TODO: better error handling
      console.error(error);
    } finally {
      switchLoading(false);
    }
  }
  async function handleUnfavorite() {
    try {
      switchLoading(true);
      await removePostFromFavourites(service, profileID, postID);
      switchFavorite(false);
    } catch (error) {
      // TODO: better error handling
      console.error(error);
    } finally {
      switchLoading(false);
    }
  }

  return isFavorite ? (
    <button
      key={renderKey}
      className={clsx("post__fav", "post__fav--unfav")}
      type="button"
      disabled={isLoading}
      onClick={handleUnfavorite}
    >
      <span className="post__fav-icon">★</span>
      <span>Unfavorite</span>
    </button>
  ) : (
    <button
      key={renderKey}
      className={clsx("post__fav")}
      type="button"
      disabled={isLoading}
      onClick={handleFavorite}
    >
      <span className="post__fav-icon">☆</span>
      <span>Favorite</span>
    </button>
  );
}
