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, ArtistCard } from "#components/cards";
import { FormRouter } from "#components/forms";
import { PageSkeleton, createAccountPageLoader } from "#components/pages";
import { KemonoLink } from "#components/links";
import { IFavouriteArtist, getAllFavouriteProfiles } from "#entities/account";

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

interface IProps {
  order?: IOrder;
  count: number;
  offset?: number;
  sortBy?: ISortBy;
  profiles: IFavouriteArtist[];
}

const sortByValues = ["updated", "faved_seq", "last_imported"] 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}".`);
  }
}

export function FavoriteProfilesPage() {
  const { sortBy, order, count, offset, profiles } = useLoaderData() as IProps;
  const title = "Favorite profiles";
  const heading = "Favorite Profiles";

  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(createAccountFavoritePostsPageURL())}>
            Favorite Posts
          </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 ?? "updated"}
        >
          <option value="updated">New post date</option>
          <option value="faved_seq">Faved date</option>
          <option value="last_imported">Reimported date</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(createAccountFavoriteProfilesPageURL(offset, sortBy, order))
          }
        />
      </div>

      <CardList layout="phone">
        {count === 0 ? (
          <>
            <h2 className="subtitle">Nobody here but us chickens!</h2>
            <p className="subtitle">There are no profiles.</p>
          </>
        ) : (
          profiles.map((profile) => (
            <ArtistCard
              // @ts-expect-error something something fav types
              artist={{
                ...profile,
                updated: String(
                  Math.round(new Date(profile.updated).getTime() / 1000)
                ),
                indexed: String(
                  Math.round(new Date(profile.indexed).getTime() / 1000)
                ),
              }}
              isUpdated
            />
          ))
        )}
      </CardList>

      <div className="paginator" id="paginator-bottom">
        <Paginator
          count={count}
          offset={offset}
          constructURL={(offset) =>
            String(createAccountFavoriteProfilesPageURL(offset, sortBy, order))
          }
        />
      </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, profiles } = await getAllFavouriteProfiles(
    offset,
    order,
    sortBy
  );

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