/*
 This file is part of GNU Taler
 (C) 2021-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/>
 */

/**
 *
 * @author Sebastian Javier Marchano (sebasjm)
 */

import {
  HttpStatusCode,
  Paytos,
  TalerError,
  TalerMerchantApi,
  assertUnreachable,
  parsePaytoUri,
} from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
import { ErrorLoadingMerchant } from "../../../../components/ErrorLoadingMerchant.js";
import { Loading } from "../../../../components/exception/loading.js";
import {
  ConfirmModal,
  ValidBankAccount,
} from "../../../../components/modal/index.js";
import { useInstanceKYCDetailsLongPolling } from "../../../../hooks/instance.js";
import { ListPage } from "./ListPage.js";

const TALER_SCREEN_ID = 40;

interface Props {
  // onGetInfo: (id: string) => void;
  // onShowInstructions: (id: string) => void;
}

export default function ListKYC(_p: Props): VNode {
  const result = useInstanceKYCDetailsLongPolling();

  const [showingInstructions, setShowingInstructions] = useState<
    TalerMerchantApi.MerchantAccountKycRedirect | undefined
  >(undefined);
  if (!result) return <Loading />;
  if (result instanceof TalerError) {
    return <ErrorLoadingMerchant error={result} />;
  }
  /**
   * This component just render known kyc requirements.
   * If query fail then is safe to hide errors.
   */
  if (result.type === "fail") {
    switch (result.case) {
      case HttpStatusCode.GatewayTimeout: {
        return <div />;
      }
      case HttpStatusCode.BadGateway: {
        break;
        // return (
        //   <ListPage
        //     status={result.body}
        //     onGetInfo={_p.onGetInfo}
        //     onShowInstructions={() => {
        //       setShowingInstructions(true)
        //     }}
        //   />
        // );
      }
      case HttpStatusCode.ServiceUnavailable: {
        return <div />;
      }
      case HttpStatusCode.Unauthorized: {
        return <div />;
      }
      case HttpStatusCode.NotFound: {
        return <div />;
      }
      default: {
        assertUnreachable(result);
      }
    }
  }
  const status = result.body;

  if (!status) {
    return <div>no kyc required</div>;
  }
  return (
    <Fragment>
      {showingInstructions !== undefined ? (
        <ShowInstructionForKycRedirect
          e={showingInstructions}
          onCancel={() => setShowingInstructions(undefined)}
        />
      ) : undefined}
      <ListPage
        status={status}
        // onGetInfo={async (exchange, ac) => {
        //   new URL()
        // }}
        onShowInstructions={(e) => {
          setShowingInstructions(e);
        }}
      />
    </Fragment>
  );
}

function ShowInstructionForKycRedirect({
  e,
  onCancel,
}: {
  e: TalerMerchantApi.MerchantAccountKycRedirect;
  onCancel: () => void;
}): VNode {
  const { i18n } = useTranslationContext();
  switch (e.status) {
    case TalerMerchantApi.MerchantAccountKycStatus.KYC_WIRE_REQUIRED:
      const uri = Paytos.fromString(e.payto_uri);
      if (uri.type === "fail") {
        return (
          <ConfirmModal
            label={i18n.str`Ok`}
            description={i18n.str`Wire account is invalid`}
            active
            onCancel={onCancel}
          >
            <p style={{ paddingTop: 0 }}>
              <i18n.Translate>
                The backend service responded with "{e.payto_uri}" which is
                invalid.
              </i18n.Translate>
            </p>
          </ConfirmModal>
        );
      }
      const tgs = (e.payto_kycauths ?? [])
        .map((d) => Paytos.fromString(d))
        .filter((d) => {
          if (d.type !== "ok") {
            // FIXME: maybe this need to be shown to the user more promptly
            console.error("server replied with a wrong payto://", d);
          }
          return d.type === "ok";
        })
        .map((d) => d.body);
      return (
        <ValidBankAccount origin={uri.body} targets={tgs} onCancel={onCancel} />
      );
    case TalerMerchantApi.MerchantAccountKycStatus.NO_EXCHANGE_KEY: {
      return (
        <ConfirmModal
          label={i18n.str`Ok`}
          description={i18n.str`No exchange keys`}
          active
          onCancel={onCancel}
        >
          <p style={{ paddingTop: 0 }}>
            <i18n.Translate>
              The backend service is still synchronizing with the payment
              service provider.
            </i18n.Translate>
          </p>
        </ConfirmModal>
      );
    }
    case TalerMerchantApi.MerchantAccountKycStatus.KYC_WIRE_IMPOSSIBLE: {
      return (
        <ConfirmModal
          label={i18n.str`Ok`}
          description={i18n.str`Can't wire from this account`}
          active
          onCancel={onCancel}
        >
          <p style={{ paddingTop: 0 }}>
            <i18n.Translate>
              The core banking system cannot perform wire transfers between the
              payment service provider's accounts and your bank accounts. Thus
              you cannot use this payment service provider. the exchange.
            </i18n.Translate>
          </p>
        </ConfirmModal>
      );
    }

    case TalerMerchantApi.MerchantAccountKycStatus.KYC_REQUIRED: {
      return (
        <ConfirmModal
          label={i18n.str`Test`}
          description={i18n.str`KYC Required`}
          active
          onCancel={onCancel}
        >
          <p style={{ paddingTop: 0 }}>
            <i18n.Translate>
              The payment provider requires more information.
            </i18n.Translate>{" "}
            {e.access_token === undefined ? undefined : (
              <a
                href={`${e.exchange_url}kyc-spa/${e.access_token}`}
                target="_blank"
                rel="noreferrer"
              >
                <i18n.Translate>
                  Click here to complete this step.
                </i18n.Translate>
              </a>
            )}
          </p>
          {e.access_token !== undefined ? undefined : (
            <p style={{ paddingTop: 0 }}>
              <i18n.Translate>
                We are waiting for the access token to be present. Check again
                later.
              </i18n.Translate>
            </p>
          )}
        </ConfirmModal>
      );
    }
    case TalerMerchantApi.MerchantAccountKycStatus.AWAITING_AML_REVIEW: {
      return (
        <ConfirmModal
          label={i18n.str`Ok`}
          description={i18n.str`Awaiting AML review`}
          active
          onCancel={onCancel}
        >
          <p style={{ paddingTop: 0 }}>
            <i18n.Translate>
              This account is can't be used. The payment service provider is
              doing manual review of the account information.
            </i18n.Translate>
          </p>
        </ConfirmModal>
      );
    }
    case TalerMerchantApi.MerchantAccountKycStatus.READY: {
      return (
        <ConfirmModal
          label={i18n.str`Ok`}
          description={i18n.str`Ready`}
          active
          onCancel={onCancel}
        >
          <p style={{ paddingTop: 0 }}>
            <i18n.Translate>
              This account is ready to be used with the payment service
              provider.
            </i18n.Translate>
          </p>
        </ConfirmModal>
      );
    }
    case TalerMerchantApi.MerchantAccountKycStatus.LOGIC_BUG: {
      return (
        <ConfirmModal
          label={i18n.str`Ok`}
          description={i18n.str`Logic bug`}
          active
          onCancel={onCancel}
        >
          <p style={{ paddingTop: 0 }}>
            <i18n.Translate>
              The backend service detected an internal error, contact the system
              administrator or check again later.
            </i18n.Translate>
          </p>
        </ConfirmModal>
      );
    }
    case TalerMerchantApi.MerchantAccountKycStatus.EXCHANGE_INTERNAL_ERROR: {
      return (
        <ConfirmModal
          label={i18n.str`Ok`}
          description={i18n.str`Internal error`}
          active
          onCancel={onCancel}
        >
          <p style={{ paddingTop: 0 }}>
            <i18n.Translate>
              The payment service provider detected an internal error, contact
              the system administrator or check again later.
            </i18n.Translate>
          </p>
        </ConfirmModal>
      );
    }
    case TalerMerchantApi.MerchantAccountKycStatus.EXCHANGE_GATEWAY_TIMEOUT: {
      return (
        <ConfirmModal
          label={i18n.str`Ok`}
          description={i18n.str`Logic bug`}
          active
          onCancel={onCancel}
        >
          <p style={{ paddingTop: 0 }}>
            <i18n.Translate>
              The backend service couldn't contact the payment service provider
              due to a timeout, contact the system administrator or check again
              later.
            </i18n.Translate>
          </p>
        </ConfirmModal>
      );
    }
    case TalerMerchantApi.MerchantAccountKycStatus.EXCHANGE_UNREACHABLE: {
      return (
        <ConfirmModal
          label={i18n.str`Ok`}
          description={i18n.str`Logic bug`}
          active
          onCancel={onCancel}
        >
          <p style={{ paddingTop: 0 }}>
            <i18n.Translate>
              Unable to reach the payment service provider, contact the system
              administrator or check again later.
            </i18n.Translate>
          </p>
        </ConfirmModal>
      );
    }
    case TalerMerchantApi.MerchantAccountKycStatus.EXCHANGE_STATUS_INVALID:
      {
        return (
          <ConfirmModal
            label={i18n.str`Ok`}
            description={i18n.str`Logic bug`}
            active
            onCancel={onCancel}
          >
            <p style={{ paddingTop: 0 }}>
              <i18n.Translate>
                The payment service provider replied with a invalid status,
                contact the system administrator or check again later.
              </i18n.Translate>
            </p>
          </ConfirmModal>
        );
      }
      return <div />;
    default:
      assertUnreachable(e.status);
  }
}
