/*
 This file is part of GNU Taler
 (C) 2022-2024 Taler Systems S.A.

 GNU Taler is free software; you can redistribute it and/or modify it under the
 terms of the GNU General Public License as published by the Free Software
 Foundation; either version 3, or (at your option) any later version.

 GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

 You should have received a copy of the GNU General Public License along with
 GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
import {
  Button,
  InternationalizationAPI,
  LocalNotificationBanner,
  ShowInputErrorLabel,
  useLocalNotificationHandler,
  useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { VNode, h } from "preact";
import {
  FormErrors,
  FormStatus,
  FormValues,
  RecursivePartial,
  useFormState,
} from "../hooks/form.js";
import { useOfficer } from "../hooks/officer.js";
import { usePreferences } from "../hooks/preferences.js";

type FormType = {
  password: string;
  repeat: string;
};
function createFormValidator(
  i18n: InternationalizationAPI,
  allowInsecurePassword: boolean,
) {
  return function check(
    state: RecursivePartial<FormValues<FormType>>,
  ): FormStatus<FormType> {
    const errors = undefinedIfEmpty<FormErrors<FormType>>({
      password: !state.password
        ? i18n.str`required`
        : allowInsecurePassword
          ? undefined
          : state.password.length < 8
            ? i18n.str`should have at least 8 characters`
            : !state.password.match(/[a-z]/) && state.password.match(/[A-Z]/)
              ? i18n.str`should have lowercase and uppercase characters`
              : !state.password.match(/\d/)
                ? i18n.str`should have numbers`
                : !state.password.match(/[^a-zA-Z\d]/)
                  ? i18n.str`should have at least one character which is not a number or letter`
                  : undefined,

      repeat: !state.repeat
        ? i18n.str`required`
        : state.password !== state.repeat
          ? i18n.str`doesn't match`
          : undefined,
    });

    if (errors === undefined) {
      return {
        status: "ok",
        result: state as FormType,
        errors,
      };
    }
    return {
      status: "fail",
      result: state,
      errors,
    };
  };
}

export function undefinedIfEmpty<T extends object>(obj: T): T | undefined {
  return Object.keys(obj).some(
    (k) => (obj as Record<string, T>)[k] !== undefined,
  )
    ? obj
    : undefined;
}

export function CreateAccount({
  onNewAccount,
}: {
  onNewAccount: () => void;
}): VNode {
  const { i18n } = useTranslationContext();
  // const Form = createNewForm<FormType>();
  const [settings] = usePreferences();
  const officer = useOfficer();

  const [notification, withErrorHandler] = useLocalNotificationHandler();

  const [form, status] = useFormState<FormType>(
    {
      password: undefined,
      repeat: undefined,
    },
    createFormValidator(i18n, settings.allowInsecurePassword),
  );

  const createAccountHandler =
    status.status === "fail" || officer.state !== "not-found"
      ? undefined
      : withErrorHandler(
          async () => officer.create(form.password!.value!),
          onNewAccount,
        );

  return (
    <div class="flex min-h-full flex-col ">
      <LocalNotificationBanner notification={notification} />

      <div class="sm:mx-auto sm:w-full sm:max-w-md">
        <h2 class="mt-6 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">
          <i18n.Translate>Create account</i18n.Translate>
        </h2>
      </div>

      <div class="mt-10 sm:mx-auto sm:w-full sm:max-w-[480px] ">
        <div class="bg-gray-100 px-6 py-6 shadow sm:rounded-lg sm:px-12">
          <form
            class="space-y-6"
            noValidate
            onSubmit={(e) => {
              e.preventDefault();
            }}
            autoCapitalize="none"
            autoCorrect="off"
          >
            <div>
              <label
                for="password"
                class="block text-sm font-medium leading-6 text-gray-900"
              >
                <i18n.Translate>Password</i18n.Translate>
              </label>
              <div class="mt-2">
                <input
                  ref={doAutoFocus}
                  type="text"
                  name="password"
                  id="password"
                  class="block w-full disabled:bg-gray-200 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
                  value={form.password?.value ?? ""}
                  enterkeyhint="next"
                  placeholder="strong password"
                  autocomplete="password"
                  title={i18n.str`Password`}
                  required
                  onChange={(e) => {
                    console.log("ASDASD", form.password?.onUpdate);
                    form.password?.onUpdate(e.currentTarget.value);
                  }}
                />
                <ShowInputErrorLabel
                  message={form.password?.error}
                  isDirty={form.password?.value !== undefined}
                />
              </div>
            </div>

            <div>
              <label
                for="repeat"
                class="block text-sm font-medium leading-6 text-gray-900"
              >
                <i18n.Translate>Repeat password</i18n.Translate>
              </label>
              <div class="mt-2">
                <input
                  type="text"
                  name="repeat"
                  id="repeat"
                  class="block w-full disabled:bg-gray-200 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
                  value={form.repeat?.value ?? ""}
                  enterkeyhint="next"
                  placeholder="identification"
                  autocomplete="repeat"
                  title={i18n.str`Repeat password`}
                  required
                  onChange={(e): void => {
                    form.repeat?.onUpdate(e.currentTarget.value);
                  }}
                />
                <ShowInputErrorLabel
                  message={form.repeat?.error}
                  isDirty={form.repeat?.value !== undefined}
                />
              </div>
            </div>

            <div class="mt-8">
              <Button
                type="submit"
                disabled={!createAccountHandler}
                class="disabled:opacity-50 disabled:cursor-default flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
                handler={createAccountHandler}
              >
                <i18n.Translate>Create</i18n.Translate>
              </Button>
            </div>
          </form>
        </div>
      </div>
    </div>
  );
}

/**
 * Show the element when the load ended
 * @param element
 */
export function doAutoFocus(element: HTMLElement | null) {
  if (element) {
    setTimeout(() => {
      element.focus({ preventScroll: true });
      element.scrollIntoView({
        behavior: "smooth",
        block: "center",
        inline: "center",
      });
    }, 100);
  }
}
