import { TranslatedString } from "@gnu-taler/taler-util";
import {
  notifyError,
  notifyInfo,
  useLocalStorage,
  useMemoryStorage,
} from "@gnu-taler/web-util/browser";
import { VNode, h } from "preact";
import { useEffect, useState } from "preact/hooks";
import {
  UnwrapKeyError,
  createNewAccount,
  createNewSessionId,
  unlockAccount,
} from "../account.js";
import { createNewForm } from "../handlers/forms.js";

export function Officer() {
  const password = useMemoryStorage("password");
  const session = useLocalStorage("session");
  const officer = useLocalStorage("officer");
  const [keys, setKeys] = useState({ accountId: "", pub: "" });

  useEffect(() => {
    if (
      officer.value === undefined ||
      session.value === undefined ||
      password.value === undefined
    ) {
      return;
    }
    unlockAccount(session.value, officer.value, password.value)
      .then((keys) => setKeys(keys ?? { accountId: "", pub: "" }))
      .catch((e) => {
        if (e instanceof UnwrapKeyError) {
          console.log(e);
        }
      });
  }, [officer.value, session.value, password.value]);

  useEffect(() => {
    if (!session.value) {
      session.update(createNewSessionId());
    }
  }, []);

  const { value: sessionId } = session;
  if (!sessionId) {
    return <div>loading...</div>;
  }

  if (officer.value === undefined) {
    return (
      <CreateAccount
        sessionId={sessionId}
        onNewAccount={(id) => {
          password.reset();
          officer.update(id);
        }}
      />
    );
  }

  console.log("pwd", password.value);
  if (password.value === undefined) {
    return (
      <UnlockAccount
        sessionId={sessionId}
        accountId={officer.value}
        onAccountUnlocked={(pwd) => {
          password.update(pwd);
        }}
      />
    );
  }

  return (
    <div>
      <div>Officer</div>
      <h1>{sessionId}</h1>
      <h1 class="my-2 text-3xl font-bold tracking-tight text-gray-900 ">
        Public key
      </h1>
      <div>
        <p class="mt-6 leading-8 text-gray-700 break-all">
          -----BEGIN PUBLIC KEY-----
          <div>{keys.pub}</div>
          -----END PUBLIC KEY-----
        </p>
      </div>
      <h1 class="my-2 text-3xl font-bold tracking-tight text-gray-900 ">
        Private key
      </h1>
      <div>
        <p class="mt-6 leading-8 text-gray-700 break-all">
          -----BEGIN PRIVATE KEY-----
          <div>{keys.accountId}</div>
          -----END PRIVATE KEY-----
        </p>
      </div>
    </div>
  );
}

function CreateAccount({
  sessionId,
  onNewAccount,
}: {
  sessionId: string;
  onNewAccount: (accountId: string) => void;
}): VNode {
  const Form = createNewForm<{
    email: string;
    password: string;
  }>();

  return (
    <div class="flex min-h-full flex-col ">
      <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">
          Create account
        </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.Provider
            onSubmit={async (v) => {
              const keys = await createNewAccount(sessionId, v.password);
              onNewAccount(keys.accountId);
            }}
          >
            <div class="mb-4">
              <Form.InputLine
                label={"Email" as TranslatedString}
                name="email"
                type="email"
                required
              />
            </div>

            <div class="mb-4">
              <Form.InputLine
                label={"Password" as TranslatedString}
                name="password"
                type="password"
                required
              />
            </div>

            <div class="mt-8">
              <button
                type="submit"
                class="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"
              >
                Create
              </button>
            </div>
          </Form.Provider>
        </div>
      </div>
    </div>
  );
}

function UnlockAccount({
  sessionId,
  accountId,
  onAccountUnlocked,
}: {
  sessionId: string;
  accountId: string;
  onAccountUnlocked: (password: string) => void;
}): VNode {
  const Form = createNewForm<{
    sessionId: string;
    accountId: string;
    password: string;
  }>();

  return (
    <div class="flex min-h-full flex-col ">
      <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">
          Unlock account
        </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.Provider
            initialValue={{
              sessionId,
              accountId:
                accountId.substring(0, 6) +
                "..." +
                accountId.substring(accountId.length - 6),
            }}
            computeFormState={(v) => {
              return {
                accountId: {
                  disabled: true,
                },
                sessionId: {
                  disabled: true,
                },
              };
            }}
            onSubmit={async (v) => {
              try {
                // test login
                await unlockAccount(sessionId, accountId, v.password);

                onAccountUnlocked(v.password ?? "");
                notifyInfo("Account unlocked" as TranslatedString);
              } catch (e) {
                if (e instanceof UnwrapKeyError) {
                  notifyError(
                    "Could not unlock account" as any,
                    e.message as any,
                  );
                } else {
                  throw e;
                }
              }
            }}
          >
            <div class="mb-4">
              <Form.InputLine
                label={"Session" as TranslatedString}
                name="sessionId"
                type="text"
              />
            </div>
            <div class="mb-4">
              <Form.InputLine
                label={"AccountId" as TranslatedString}
                name="accountId"
                type="text"
              />
            </div>

            <div class="mb-4">
              <Form.InputLine
                label={"Password" as TranslatedString}
                name="password"
                type="password"
                required
              />
            </div>

            <div class="mt-8">
              <button
                type="submit"
                class="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"
              >
                Unlock
              </button>
            </div>
          </Form.Provider>
        </div>
      </div>
    </div>
  );
}
