import {
  ActionFunctionArgs,
  redirect,
  useSearchParams,
} from "react-router";
import { createArtistsPageURL, createLoginPageURL } from "#lib/urls";
import { getLocalStorageItem } from "#storage/local";
import { KemonoLink } from "#components/links";
import { PageSkeleton } from "#components/pages";
import { FormRouter, FormSection } from "#components/forms";
import { registerAccount } from "#entities/account";

const USERNAME_REGEX = /^[a-z0-9_@+.-]{3,15}$/;
const NOT_ALLOWED_CHARS_REGEX = /[^a-z0-9_@+.\-]/g;

export function RegisterPage() {
  const [searchParams] = useSearchParams();
  const title = "Register account";
  const heading = "Register Account";
  const location =
    searchParams.get("location") ?? String(createArtistsPageURL());

  return (
    <PageSkeleton name="register" title={title} heading={heading}>
      <div className="site-section__register-cta">
        Already have an account?{" "}
        <KemonoLink url={String(createLoginPageURL(location))}>
          Log in!
        </KemonoLink>
      </div>

      <FormRouter
        id="register_form"
        className="form"
        method="POST"
        data-pattern={USERNAME_REGEX}
        submitButton={(state) => "Register"}
      >
        <input type="hidden" name="location" defaultValue={location} />

        <input id="serialized-favorites" type="hidden" name="favorites" />

        <FormSection>
          <label className="form__label" htmlFor="new-username">
            Username:
          </label>

          <input
            id="new-username"
            className="left-align-text form__input form__input--text"
            type="text"
            name="username"
          />
        </FormSection>

        <FormSection>
          <label className="form__label" htmlFor="new-password">
            Password:
          </label>

          <input
            id="new-password"
            className="left-align-text form__input form__input--password"
            type="password"
            name="password"
            autoComplete="new-password"
          />
        </FormSection>

        <FormSection>
          <label className="form__label" htmlFor="password-confirm">
            Confirm Password:
          </label>

          <input
            id="password-confirm"
            className="left-align-text form__input form__input--password"
            type="password"
            name="confirm_password"
            autoComplete="new-password"
          />
        </FormSection>
      </FormRouter>
    </PageSkeleton>
  );
}

export async function action({ request }: ActionFunctionArgs) {
  try {
    if (request.method !== "POST") {
      throw new Error(`Unknown method "${request.method}".`);
    }

    const data = await request.formData();

    const location = data.get("location") as string;
    const favorites = getLegacyFavoriteProfiles();

    let userName: string | undefined = undefined;
    {
      const inputValue = (data.get("username") as string | null)
        ?.toLowerCase()
        .replace(NOT_ALLOWED_CHARS_REGEX, "")
        .trim();

      if (!inputValue) {
        throw new Error("Username is required.");
      }

      if (inputValue.length < 3 || inputValue.length > 15) {
        throw new Error(
          "Username must be at least 3 characters and no more than 15 characters long."
        );
      }

      if (!inputValue.match(USERNAME_REGEX)) {
        throw new Error(`Username doesn't match pattern "${USERNAME_REGEX}".`);
      }

      userName = inputValue;
    }

    let password: string | undefined;
    {
      const inputValue = (data.get("password") as string | null)?.trim();

      if (!inputValue) {
        throw new Error("Password is required.");
      }

      if (inputValue.length < 5) {
        throw new Error("Password must have at least 5 characters.");
      }

      password = inputValue;
    }

    const confirmPassword = (
      data.get("confirm_password") as string | null
    )?.trim();
    {
      if (confirmPassword !== password) {
        throw new Error("Passwords don't match.");
      }
    }

    await registerAccount(userName, password, confirmPassword, favorites);

    return redirect(location);
  } catch (error) {
    return error;
  }
}

function getLegacyFavoriteProfiles(): string | undefined {
  const value = getLocalStorageItem("favorites");

  if (!value) {
    return;
  }

  const favorites: { service: string; artist_id: string }[] = [];
  const artists = value.split(",");

  for (const artist of artists) {
    const split = artist.split(":");

    if (split.length != 2) {
      continue;
    }

    const fav = {
      service: split[0],
      artist_id: split[1],
    };

    favorites.push(fav);
  }

  if (favorites.length === 0) {
    return;
  }

  return JSON.stringify(favorites);
}
