/*
 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 {
  AccessToken,
  HttpStatusCode,
  KycRequirementInformation,
  TalerError,
  assertUnreachable,
} from "@gnu-taler/taler-util";
import {
  Attention,
  Button,
  Loading,
  LocalNotificationBanner,
  useExchangeApiContext,
  useLocalNotificationHandler,
  useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useEffect, useState } from "preact/hooks";
import { ErrorLoadingWithDebug } from "../components/ErrorLoadingWithDebug.js";
import { useKycInfo } from "../hooks/kyc.js";
import { FillForm } from "./FillForm.js";

type Props = {
  onLoggedOut: () => void;
  token: AccessToken;
};

export function ShowReqList({
  token,
  onFormSelected,
}: {
  token: AccessToken;
  onFormSelected: (r: KycRequirementInformation) => void;
}): VNode {
  const { i18n } = useTranslationContext();
  const [notification, withErrorHandler] = useLocalNotificationHandler();
  // const { lib } = useExchangeApiContext();
  // const { state, start } = useSessionState();
  const result = useKycInfo(token);

  const firstAccount =
    result &&
    !(result instanceof TalerError) &&
    result.type === "ok" &&
    result.body.requirements.length > 0
      ? result.body.requirements[0]
      : undefined;
  useEffect(() => {
    if (firstAccount) onFormSelected(firstAccount);
  }, [firstAccount]);

  if (!result) {
    return <Loading />;
  }
  if (result instanceof TalerError) {
    return <ErrorLoadingWithDebug error={result} />;
  }

  if (result.type === "fail") {
    switch (result.case) {
      case HttpStatusCode.NotModified: {
        return <div> not modified </div>;
      }
      case HttpStatusCode.NoContent: {
        return <div> not requirements </div>;
      }
      case HttpStatusCode.Accepted: {
        return <div> accepted </div>;
      }
      default: {
        assertUnreachable(result);
      }
    }
  }

  const errors = undefinedIfEmpty({
    // password: !password ? i18n.str`required` : undefined,
    // url: !url
    //   ? i18n.str`required`
    //   : !safeToURL(url)
    //     ? i18n.str`invalid format`
    //     : undefined,
  });

  // const onStart =
  //   !!errors
  //     ? undefined
  //     : withErrorHandler(
  //       async () => {
  //         return {
  //           type: "ok",
  //           body: {},
  //         }
  //         // return lib.exchange.uploadKycForm(
  //         //   "clientId",
  //         //   createRFC8959AccessTokenEncoded(password),
  //         // );
  //       },
  //       (ok) => {
  //         // start({
  //         //   nonce: ok.body.nonce,
  //         //   clientId,
  //         //   redirectURL: url,
  //         //   state: encodeCrock(randomBytes(32)),
  //         // });

  //         onCreated();
  //       },
  //       // () => {
  //       //   // switch (fail.case) {
  //       //   //   case HttpStatusCode.NotFound:
  //       //   //     return i18n.str`Client doesn't exist.`;
  //       //   // }
  //       // },
  //     );

  // const requirements: typeof result.body.requirements = [{
  //   description: "this is the form description, click to show the form field bla bla bla",
  //   form: "asdasd" as KycBuiltInFromId,
  //   description_i18n: {},
  //   id: "ASDASD" as KycRequirementInformationId,
  // }, {
  //   description: "this is the description of the link and service provider.",
  //   form: "LINK",
  //   description_i18n: {},
  //   id: "ASDASD" as KycRequirementInformationId,
  // }, {
  //   description: "you can't click this because this is only information, wait until AML officer replies.",
  //   form: "INFO",
  //   description_i18n: {},
  //   id: "ASDASD" as KycRequirementInformationId,
  // }]
  const requirements = result.body.requirements;
  if (!result.body.requirements.length) {
    return (
      <Fragment>
        <LocalNotificationBanner notification={notification} />
        <div class="isolate bg-white px-6 py-12">
          <div class="mx-auto max-w-2xl text-center">
            <h2 class="text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">
              <i18n.Translate>No requirements for this account</i18n.Translate>
            </h2>
          </div>
          <div class="m-8">
            <Attention title={i18n.str`Kyc completed`} type="success">
              <i18n.Translate>You can close this now</i18n.Translate>
            </Attention>
          </div>
        </div>
      </Fragment>
    );
  }
  return (
    <Fragment>
      <LocalNotificationBanner notification={notification} />

      <div class="isolate bg-white px-6 py-12">
        <div class="mx-auto max-w-2xl text-center">
          <h2 class="text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">
            <i18n.Translate>
              Complete any of the following requirements
            </i18n.Translate>
          </h2>
        </div>

        <div class="mt-8">
          <ul
            role="list"
            class=" divide-y divide-gray-100 overflow-hidden bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl"
          >
            {requirements.map((req, idx) => {
              return (
                <li
                  key={idx}
                  class="relative flex justify-between gap-x-6 px-4 py-5 hover:bg-gray-50 sm:px-6"
                >
                  <RequirementRow
                    requirement={req}
                    onFormSelected={() => {
                      onFormSelected(req);
                    }}
                  />
                </li>
              );
            })}
          </ul>
        </div>
      </div>
    </Fragment>
  );
}
export function Start({ token, onLoggedOut }: Props): VNode {
  const [req, setReq] = useState<KycRequirementInformation>();
  // if (!state) {
  //   return <Loading />;
  // }

  if (!req) {
    return <ShowReqList token={token} onFormSelected={(r) => setReq(r)} />;
  }
  return (
    <FillForm
      formId={req.form}
      requirement={req}
      token={token}
      onComplete={() => {
        setReq(undefined);
      }}
    />
  );
}

function RequirementRow({
  requirement: req,
  onFormSelected,
}: {
  requirement: KycRequirementInformation;
  onFormSelected: () => void;
}): VNode {
  const { i18n } = useTranslationContext();
  const { lib } = useExchangeApiContext();
  const [notification, withErrorHandler] = useLocalNotificationHandler();
  const reqId = req.id;
  const startHandler = !reqId
    ? undefined
    : withErrorHandler(
        async () => {
          return lib.exchange.startExternalKycProcess(reqId);
        },
        (res) => {
          window.open(res.body.redirect_url, "_blank");
        },
      );

  switch (req.form) {
    case "INFO": {
      return (
        <Fragment>
          <div class="flex min-w-0 gap-x-4">
            <div class="inline-block h-10 w-10 rounded-full">
              <svg
                xmlns="http://www.w3.org/2000/svg"
                fill="none"
                viewBox="0 0 24 24"
                stroke-width="1.5"
                stroke="currentColor"
                class="size-6"
              >
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"
                />
              </svg>
            </div>
            <div class="min-w-0 flex-auto">
              <p class="text-sm font-semibold leading-6 text-gray-900">
                <span class="absolute inset-x-0 -top-px bottom-0"></span>
                <i18n.Translate>Information</i18n.Translate>
              </p>
              <p class="mt-1 flex text-xs leading-5 text-gray-500">
                {req.description}
              </p>
            </div>
          </div>
        </Fragment>
      );
    }
    case "LINK": {
      return (
        <Fragment>
          <div class="flex min-w-0 gap-x-4">
            <div class="inline-block h-10 w-10 rounded-full">
              <svg
                xmlns="http://www.w3.org/2000/svg"
                fill="none"
                viewBox="0 0 24 24"
                stroke-width="1.5"
                stroke="currentColor"
                class="size-6"
              >
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"
                />
              </svg>
            </div>
            <div class="min-w-0 flex-auto">
              <p class="text-sm font-semibold leading-6 text-gray-900">
                <Button type="submit" handler={startHandler}>
                  <span class="absolute inset-x-0 -top-px bottom-0"></span>
                  <i18n.Translate>Begin KYC process</i18n.Translate>
                </Button>
              </p>
              <p class="mt-1 flex text-xs leading-5 text-gray-500">
                {req.description}
              </p>
            </div>
          </div>
          <div class="flex shrink-0 items-center gap-x-4">
            <div class="hidden sm:flex sm:flex-col sm:items-end">
              <p class="text-sm leading-6 text-gray-900">
                <i18n.Translate>Start</i18n.Translate>
              </p>
            </div>
            <svg
              class="h-5 w-5 flex-none text-gray-400"
              viewBox="0 0 20 20"
              fill="currentColor"
              aria-hidden="true"
            >
              <path
                fill-rule="evenodd"
                d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z"
                clip-rule="evenodd"
              />
            </svg>
          </div>
        </Fragment>
      );
    }
    default: {
      return (
        <Fragment>
          <div class="flex min-w-0 gap-x-4">
            <div class="inline-block h-10 w-10 rounded-full">
              <svg
                xmlns="http://www.w3.org/2000/svg"
                fill="none"
                viewBox="0 0 24 24"
                stroke-width="1.5"
                stroke="currentColor"
                class="size-6"
              >
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z"
                />
              </svg>
            </div>
            <div class="min-w-0 flex-auto">
              <p class="text-sm font-semibold leading-6 text-gray-900">
                <button onClick={onFormSelected}>
                  <span class="absolute inset-x-0 -top-px bottom-0"></span>
                  <i18n.Translate>Form</i18n.Translate>
                </button>
              </p>
              <p class="mt-1 flex text-xs leading-5 text-gray-500">
                {req.description}
              </p>
            </div>
          </div>
          <div class="flex shrink-0 items-center gap-x-4">
            <div class="hidden sm:flex sm:flex-col sm:items-end">
              <p class="text-sm leading-6 text-gray-900">Fill form</p>
            </div>
            <svg
              class="h-5 w-5 flex-none text-gray-400"
              viewBox="0 0 20 20"
              fill="currentColor"
              aria-hidden="true"
            >
              <path
                fill-rule="evenodd"
                d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z"
                clip-rule="evenodd"
              />
            </svg>
          </div>
        </Fragment>
      );
    }
  }
}

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

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