/*
 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,
  ButtonBetter,
  ErrorLoading,
  Loading,
  LocalNotificationBanner,
  useExchangeApiContext,
  useLocalNotificationBetter,
  useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
import { useKycInfo } from "../hooks/kyc.js";
import { FillForm } from "./FillForm.js";

type Props = {
  token: AccessToken;
};

function ShowReqList({
  token,
  onFormSelected,
}: {
  token: AccessToken;
  onFormSelected: (r: KycRequirementInformation) => void;
}): VNode {
  const { i18n } = useTranslationContext();
  const result = useKycInfo(token);

  if (!result) {
    return <Loading />;
  }
  if (result instanceof TalerError) {
    return <ErrorLoading 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 requirements = result.body.requirements;
  if (!requirements.length) {
    return (
      <Fragment>
        <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>
                Mandatory identification requirements are satisfied
              </i18n.Translate>
            </h2>
          </div>
          <div class="m-8">
            <Attention title={i18n.str`Process completed`} type="success">
              <i18n.Translate>You can close this window now.</i18n.Translate>
            </Attention>
          </div>
        </div>
      </Fragment>
    );
  }
  return (
    <Fragment>
      <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">
            {requirements.length === 1 ? (
              <i18n.Translate>
                Please, complete the following requirement:
              </i18n.Translate>
            ) : (
              <i18n.Translate>
                Please, 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 (
                <RequirementRow
                  requirement={req}
                  onFormSelected={() => {
                    onFormSelected(req);
                  }}
                />
              );
            })}
          </ul>
        </div>
      </div>
    </Fragment>
  );
}

export function Start({ token }: Props): VNode {
  const [req, setReq] = useState<KycRequirementInformation>();
  if (!req) {
    return (
      <Fragment>
        <ShowReqList
          token={token}
          onFormSelected={async (r) => {
            const reqId = r.id;
            if (r.form === "LINK" && reqId) {
            } else {
              setReq(r);
            }
          }}
        />
      </Fragment>
    );
  }
  return (
    <Fragment>
      <FillForm
        formId={req.form}
        requirement={req}
        token={token}
        onComplete={() => {
          setReq(undefined);
        }}
      />
    </Fragment>
  );
}

function LinkGenerator({ req }: { req: KycRequirementInformation }): VNode {
  const { i18n } = useTranslationContext();

  const [notification, safeFunctionHandler] = useLocalNotificationBetter();
  const { lib } = useExchangeApiContext();

  const start = safeFunctionHandler(async (id: string) => {
    return lib.exchange.startExternalKycProcess(id);
  },[req.id!]);
  start.onFail = (fail) => {
    switch (fail.case) {
      case HttpStatusCode.NotFound:
        return i18n.str`not found`;
      case HttpStatusCode.Conflict:
        return i18n.str`conflict`;
      case HttpStatusCode.PayloadTooLarge:
        return i18n.str`payload is too large`;
    }
  };
  start.onSuccess = (success) => {
    setRedirectUrl(success.redirect_url);
    return i18n.str`Link generated, you can proceed.`;
  };
  const [redirectUrl, setRedirectUrl] = useState<string>();
  const row = (
    <Fragment>
      <div class="flex min-w-0 gap-x-4">
        <LocalNotificationBanner notification={notification} />
        <div class="inline-block h-10 w-10 rounded-full">
          {!redirectUrl ? (
            <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="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"
              />
            </svg>
          ) : (
            <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">
          {redirectUrl ? (
            <p class="text-sm font-semibold leading-6 text-gray-900">
              <span class="absolute inset-x-0 -top-px bottom-0"></span>
              <i18n.Translate>{req.description}</i18n.Translate>
            </p>
          ) : (
            // href={redirectUrl}
            <p class="text-sm font-semibold leading-6 text-gray-900">
              <ButtonBetter onClick={start}>
                <span class="absolute inset-x-0 -top-px bottom-0"></span>
                <i18n.Translate context="KYC_REQUIREMENT_LINK_DESCRIPTION">
                  {req.description}
                </i18n.Translate>
              </ButtonBetter>
            </p>
          )}
        </div>
      </div>
      <div class="flex shrink-0 items-center gap-x-4">
        <div class="hidden sm:flex sm:flex-col sm:items-end">
          {!redirectUrl ? (
            <p class="text-sm leading-6 text-gray-900">
              <i18n.Translate>Generate link</i18n.Translate>
            </p>
          ) : (
            <p class="text-sm leading-6 text-gray-900">
              <i18n.Translate>Open link</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>
  );
  if (redirectUrl) {
    return (
      <li key={req.id} class="hover:bg-gray-50 sm:px-6 px-4 py-5">
        <a
          href={redirectUrl}
          target="_blank"
          rel="noreferrer"
          class="relative flex justify-between gap-x-6  "
        >
          {row}
        </a>
      </li>
    );
  }
  return (
    <li
      key={req.id}
      class="relative flex justify-between gap-x-6 px-4 py-5 hover:bg-gray-50 sm:px-6"
    >
      {row}
    </li>
  );
}

function RequirementRow({
  requirement: req,
  onFormSelected,
}: {
  requirement: KycRequirementInformation;
  onFormSelected: () => void;
}): VNode {
  const { i18n } = useTranslationContext();

  switch (req.form) {
    case "INFO": {
      return (
        <li
          key={req.id}
          class="relative flex justify-between gap-x-6 px-4 py-5 hover:bg-gray-50 sm:px-6"
        >
          <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 context="KYC_REQUIREMENT_INFO_DESCRIPTION">
                  {req.description}
                </i18n.Translate>
              </p>
              {/* <p class="mt-1 flex text-xs leading-5 text-gray-500">
                
              </p> */}
            </div>
          </div>
        </li>
      );
    }
    case "LINK": {
      return <LinkGenerator key={req.id} req={req} />;
    }
    default: {
      return (
        <li
          key={req.id}
          class="relative flex justify-between gap-x-6 px-4 py-5 hover:bg-gray-50 sm:px-6"
        >
          <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">
                <i18n.Translate>Fill form</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>
        </li>
      );
    }
  }
}

/**
 * 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;
}
