import { LoaderFunctionArgs, useLoaderData } from "react-router";
import {
  createAccountFavoritePostsPageURL,
  createAccountFavoriteProfilesPageURL,
} from "#lib/urls";
import { parseOffset } from "#lib/pagination";
import { HeaderAd, SliderAd } from "#components/advs";
import { Paginator } from "#components/pagination";
import { CardList, PostCard } from "#components/cards";
import { FormRouter } from "#components/forms";
import { PageSkeleton, createAccountPageLoader } from "#components/pages";
import { KemonoLink } from "#components/links";
import { IFavouritePost, getAllFavouritePosts } from "#entities/account";

import * as styles from "./posts.module.scss";

type IProps = {
  order?: IOrder;
  count: number;
  offset?: number;
  sortBy?: ISortBy;
  posts: IFavouritePost[];
};

const sortByValues = ["faved_seq", "published"] as const;
const orderValues = ["asc", "desc"] as const;

type ISortBy = (typeof sortByValues)[number];
type IOrder = (typeof orderValues)[number];

function validateSortBy(input: unknown): asserts input is ISortBy {
  if (!sortByValues.includes(input as ISortBy)) {
    throw new Error(`Invalid sort by value "${input}".`);
  }
}

function validateOrder(input: unknown): asserts input is IOrder {
  if (!orderValues.includes(input as IOrder)) {
    throw new Error(`Invalid order value "${input}".`);
  }
}

/**
 * TODO: split into separate pages
 */
export function FavoritePostsPage() {
  const { sortBy, order, count, offset, posts } = useLoaderData() as IProps;
  const title = "Favorite posts";
  const heading = "Favorite Posts";

  return (
    <PageSkeleton name="favorites" title={title} heading={heading}>
      <SliderAd />
      <HeaderAd />

      <>
        <FormRouter
          id="filter-favorites"
          className={styles.dropdowns}
          method="GET"
          submitButton={(state) => "Filter"}
        >
          <p>
            <KemonoLink url={String(createAccountFavoriteProfilesPageURL())}>
              Favorite Artists
            </KemonoLink>
          </p>
          {/* a filler div until proper form rewrite */}
          <div></div>
          <label className={styles.label} htmlFor="filter-favorites-sort_by">
            Sort by
          </label>
          <select
            id="filter-favorites-sort_by"
            name="sort_by"
            autoComplete="off"
            defaultValue={sortBy ?? "faved_seq"}
          >
            <option value="faved_seq">Faved date</option>
            <option value="published">Published</option>
          </select>

          <label className={styles.label} htmlFor="filter-favorites-order">
            Order
          </label>
          <select
            id="filter-favorites-order"
            name="order"
            autoComplete="off"
            defaultValue={order ?? "desc"}
          >
            <option value="desc">Descending</option>
            <option value="asc">Ascending</option>
          </select>
        </FormRouter>

        <>
          <div className="paginator" id="paginator-top">
            <Paginator
              count={count}
              offset={offset}
              constructURL={(offset) =>
                String(createAccountFavoritePostsPageURL(offset))
              }
            />
          </div>

          <CardList>
            {count === 0 ? (
              <>
                <h2 className="subtitle">Nobody here but us chickens!</h2>
                <p className="subtitle">There are no more posts.</p>
              </>
            ) : (
              posts.map((post) => (
                <PostCard
                  key={post.id}
                  // @ts-expect-error fav post mismatch
                  post={post}
                />
              ))
            )}
          </CardList>

          <div className="paginator" id="paginator-bottom">
            <Paginator
              count={count}
              offset={offset}
              constructURL={(offset) =>
                String(createAccountFavoritePostsPageURL(offset))
              }
            />
          </div>
        </>
      </>
    </PageSkeleton>
  );
}

export const loader = createAccountPageLoader(async function loader({
  request,
}: LoaderFunctionArgs): Promise<IProps> {
  const searchParams = new URL(request.url).searchParams;

  let sortBy: IProps["sortBy"] = undefined;
  {
    const inputValue = searchParams.get("sort_by")?.trim();

    if (inputValue) {
      validateSortBy(inputValue);

      sortBy = inputValue;
    }
  }

  let offset: IProps["offset"] = undefined;
  {
    const inputValue = searchParams.get("o")?.trim();

    if (inputValue) {
      offset = parseOffset(inputValue);
    }
  }

  let order: IProps["order"] = undefined;
  {
    const inputValue = searchParams.get("order")?.trim();

    if (inputValue) {
      validateOrder(inputValue);

      order = inputValue;
    }
  }

  const { count, posts } = await getAllFavouritePosts(offset, order, sortBy);

  return {
    count,
    posts,
    offset,
    order,
    sortBy,
  };
});
