import { useEffect, useState } from "react";
import clsx from "clsx";
import {
  ActionFunctionArgs,
  LoaderFunctionArgs,
  useActionData,
  useLoaderData,
} from "react-router";
import { SITE_NAME } from "#env/env-vars";
import { AVAILABLE_PAYSITE_LIST } from "#env/derived-vars";
import { ElementType } from "#lib/types";
import { fetchAddProfileLink } from "#api/account";
import {
  ProfilePageSkeleton,
  createAccountPageLoader,
} from "#components/pages";
import { FormRouter, FormSection, ButtonSubmit } from "#components/forms";
import { InputHidden } from "#components/forms/inputs";
import { ArtistCard } from "#components/cards";
import { Button } from "#components/buttons";
import {
  ProfileHeader,
  Tabs,
  IArtistDetails,
  getArtist,
  getArtists,
} from "#entities/profiles";
import { validatePaysite } from "#entities/paysites";

import * as styles from "./new-linked-profile.module.scss";

interface IProps {
  profile: IArtistDetails;
}

interface IAction {
  message: string;
}

export function NewProfileLinkPage() {
  const { profile } = useLoaderData() as IProps;
  const [currentService, changeCurrentService] = useState<string>();
  const [currentQuery, changeCurrentQuery] = useState<string>();
  const [profileSuggestions, changeProfileSuggestions] =
    useState<Awaited<ReturnType<typeof getArtists>>>();
  const [selectedProfile, changeSelectedProfile] =
    useState<ElementType<Awaited<ReturnType<typeof getArtists>>["artists"]>>();
  const title = "Link new profile";
  const heading = "Link New Profile";

  useEffect(() => {
    (async () => {
      const profiles = await getArtists({
        service: currentService,
        query: currentQuery,
      });

      changeProfileSuggestions(profiles);
    })();
  }, [currentService, currentQuery]);

  return (
    <ProfilePageSkeleton
      name={["user", "new-linked-account"]}
      title={title}
      heading={heading}
      profile={profile}
    >
      <ProfileHeader
        service={profile.service}
        profileID={profile.id}
        profileName={profile.name}
      />

      <div className="paginator" id="paginator-top">
        <Tabs
          currentPage="linked_accounts"
          artistID={profile.id}
          service={profile.service}
        />
      </div>

      <p className="link-notice">
        If you believe this profile has other profiles on {SITE_NAME}, you can
        use this form to request they be linked.
      </p>

      <FormRouter<IAction>
        id="new_link_form"
        className="form--wide"
        method="POST"
        successElement={({ message }) => (
          <ul>
            <li>{message}</li>
          </ul>
        )}
      >
        <FormSection id="artist-section">
          <span>
            <label className="form__label" htmlFor="service">
              Service:
            </label>
            <select
              id="service"
              name="service"
              value={currentService}
              onChange={async (event) => {
                const service = event.currentTarget.value.trim();

                changeCurrentService(
                  service.length === 0 ? undefined : service
                );
              }}
            >
              <option value="">All</option>
              {AVAILABLE_PAYSITE_LIST.map((paysite) => (
                <option value={paysite.name}>{paysite.title}</option>
              ))}
            </select>
          </span>

          <span>
            <label className="form__label" htmlFor="creator_name">
              Profile Name:
            </label>
            <input
              id="creator_name"
              type="text"
              name="creator_name"
              value={currentQuery}
              onChange={async (event) => {
                const query = event.currentTarget.value.trim();

                changeCurrentQuery(query.length === 0 ? undefined : query);
              }}
            />
          </span>
          <InputHidden
            id="creator"
            name="creator"
            value={
              !selectedProfile
                ? undefined
                : `${selectedProfile.service}/${selectedProfile.id}`
            }
          />
        </FormSection>

        <FormSection id="reason-section">
          <label className="form__label" htmlFor="reason">
            Reason:
          </label>
          <input
            id="reason"
            name="reason"
            type="text"
            maxLength={140}
            placeholder="(optional) leave a reason for this link if needed"
          />
        </FormSection>

        <FormSection>
          <ButtonSubmit disabled={!selectedProfile}>Request link</ButtonSubmit>
        </FormSection>
      </FormRouter>

      <div className="card-list card-list--phone">
        <div id="lookup-result" className="card-list__items">
          {!profileSuggestions ? (
            <>Please select a creator.</>
          ) : profileSuggestions.count === 0 ? (
            <>No results found.</>
          ) : (
            profileSuggestions.artists.slice(0, 20).map((profile) => (
              <div
                key={`${profile.service}${profile.id}`}
                className={clsx(
                  profile.service === selectedProfile?.service &&
                    profile.id === selectedProfile?.id &&
                    styles.selected
                )}
              >
                <ArtistCard artist={profile} />
                <Button
                  disabled={
                    profile.service === selectedProfile?.service &&
                    profile.id === selectedProfile?.id
                  }
                  onClick={() => changeSelectedProfile(profile)}
                >
                  Select
                </Button>
              </div>
            ))
          )}
        </div>
      </div>
    </ProfilePageSkeleton>
  );
}

export const loader = createAccountPageLoader(async function loader({
  params,
}: LoaderFunctionArgs): Promise<IProps> {
  const service = params.service?.trim();
  {
    if (!service) {
      throw new Error("Service name is required.");
    }

    validatePaysite(service);
  }

  const profileID = params.creator_id?.trim();
  {
    if (!profileID) {
      throw new Error("Profile ID is required.");
    }
  }

  const profile = await getArtist(service, profileID);

  return { profile };
});

export async function action({
  params,
  request,
}: ActionFunctionArgs): Promise<IAction> {
  if (request.method !== "POST") {
    throw new Error(`Unknown method "${request.method}".`);
  }

  const service = params.service?.trim();
  {
    if (!service) {
      throw new Error("Service name is required.");
    }

    validatePaysite(service);
  }

  const profileID = params.creator_id?.trim();
  {
    if (!profileID) {
      throw new Error("Profile ID is required.");
    }
  }

  const formData = await request.formData();

  const inputData = (formData.get("creator") as string | null)
    ?.trim()
    .split("/");

  if (!inputData) {
    throw new Error("Input data is required.");
  }

  if (inputData.length !== 2) {
    throw new Error("Invalid input data length.");
  }

  const [suggestedService, suggestedProfileID] = inputData;

  const reason = (formData.get("reason") as string | null)?.trim();

  const { message } = await fetchAddProfileLink(
    service,
    profileID,
    suggestedService,
    suggestedProfileID,
    reason
  );

  return { message };
}
