import { LoaderFunctionArgs, useLoaderData } from "react-router";
import { parseOffset } from "#lib/pagination";
import { createPostsPageURL } from "#lib/urls";
import { fetchPosts } from "#api/posts";
import { PageSkeleton } from "#components/pages";
import { Paginator } from "#components/pagination";
import { FooterAd, HeaderAd, SliderAd } from "#components/advs";
import { CardList, PostCard } from "#components/cards";
import { FormRouter, FormSection } from "#components/forms";
import { IPost } from "#entities/posts";
import { findFavouritePosts, findFavouriteProfiles } from "#entities/account";

interface IProps {
  count: number;
  trueCount: number;
  offset?: number;
  posts: IPost[];
  query?: string;
  tags?: string[];
}

export function PostsPage() {
  const { count, trueCount, offset, query, posts, tags } =
    useLoaderData() as IProps;
  const title = "Posts";
  const heading = "Posts";

  return (
    <PageSkeleton name="posts" title={title} heading={heading}>
      <div className="paginator" id="paginator-top">
        <Paginator
          count={count}
          true_count={trueCount}
          offset={offset}
          constructURL={(offset) =>
            String(createPostsPageURL(offset, query, tags))
          }
        />
        <FormRouter method="GET">
          <FormSection>
            <input
              id="q"
              className="search-input"
              type="text"
              name="q"
              aria-autocomplete="none"
              defaultValue={query}
              minLength={2}
              placeholder="search for posts..."
            />
          </FormSection>
        </FormRouter>
      </div>

      <SliderAd />
      <HeaderAd />

      <CardList>
        {count === 0 ? (
          <div className="card-list__item--no-results">
            <h2 className="subtitle">Nobody here but us chickens!</h2>
            <p className="subtitle">There are no posts for your query.</p>
          </div>
        ) : (
          posts.map((post) => (
            <PostCard
              key={`${post.id}-${post.service}`}
              post={post}
              isFavourite={post.isFavourite}
              isFavouriteProfile={post.isFavouriteProfile}
            />
          ))
        )}
      </CardList>

      <FooterAd />

      <div className="paginator" id="paginator-bottom">
        <Paginator
          count={count}
          true_count={trueCount}
          offset={offset}
          constructURL={(offset) =>
            String(createPostsPageURL(offset, query, tags))
          }
        />
      </div>
    </PageSkeleton>
  );
}

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

  let offset: number | undefined = undefined;
  {
    const parsedOffset = searchParams.get("o")?.trim();

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

  const query = searchParams.get("q")?.trim();
  const tags = searchParams.getAll("tag");
  const { count, true_count, posts } = await fetchPosts(offset, query, tags);
  const postsData = posts.map(({ service, user, id }) => ({
    service,
    user,
    id,
  }));
  const profilesData = posts.reduce<{ service: string; id: string }[]>(
    (profilesData, post) => {
      const match = profilesData.find(
        (profileData) =>
          profileData.id === post.user && profileData.service === post.service
      );

      if (!match) {
        profilesData.push({ service: post.service, id: post.user });
      }

      return profilesData;
    },
    []
  );
  const favPosts = await findFavouritePosts(postsData);
  const favProfiles = await findFavouriteProfiles(profilesData);
  const postsWithFavs = posts.map<IPost>((post) => {
    const isFavPost = Boolean(
      favPosts.find(
        ({ service, user, id }) =>
          id === post.id && user === post.user && service === post.service
      )
    );
    const isFavProfile = Boolean(
      favProfiles.find(
        ({ service, id }) => id === post.user && service === post.service
      )
    );

    if (!isFavPost && !isFavProfile) {
      return post;
    }

    return {
      ...post,
      isFavourite: isFavPost,
      isFavouriteProfile: isFavProfile,
    };
  });

  return {
    offset,
    query,
    tags,
    count,
    trueCount: true_count,
    posts: postsWithFavs,
  };
}
