import { ColumnLayout, Container, Header, ProgressBar, Spinner } from "@cloudscape-design/components";
import { useContext, useEffect, useState } from "react";
import QRCode from "react-qr-code";
import { Action } from "../types/Action";
import { ResponseHandler } from "../handlers/RepsonseHandler";
import { useNavigate } from "react-router-dom";
import { AlertContext } from "../contexts/AlertContext";

export async function loader({ params }: {params: {action: string}}) {
  return { action: params.action };
}

const WAIT_MS: number = 3000;
const COUNTDOWN_TIME_SECONDS = 100;

export interface IAuthPageProps {
  subdomain: string;
  action: Action;
  options?: RequestInit;
  responseHandler: ResponseHandler;
  handlerMetadata?: any;
};

export default function AuthFlow(props: IAuthPageProps) {
  const { subdomain, action, options, responseHandler, handlerMetadata } = props;
  const [ loading, setLoading ] = useState<boolean>(true);
  const [ qrContent, setQrContent ] = useState<string>("");
  const [ challenge, setChallenge ] = useState<string>("");
  const [ countdown, setCountdown ] = useState<number>(COUNTDOWN_TIME_SECONDS);

  const { setContent } = useContext(AlertContext);

  const navigate = useNavigate();

  useEffect(() => {
    fetch(`/api/lnurl/login?subdomain=${subdomain}`)
      .then(res => {
        if (res.status === 429) {
          throw new Error("Too many requests, try again later");
        }
        return res;
      })
      .then(res => res.json())
      .then(res => {
        setQrContent(res.lnurl);
        setLoading(false);
        setChallenge(res.challenge);
        setCountdown(COUNTDOWN_TIME_SECONDS);
      })
      .catch((err) => {
        console.log(err);
        setContent({
          type: "error",
          message: err?.message || "Unknown error occurred",
        });
        navigate("/");
      });
  }, [action]);

  useEffect(() => {
    if (challenge === "") {
      return;
    }

    const timer = setInterval(() => {
      fetch(`/api/actions/${action}/${challenge}`, options)
        .then(res => {
          if (res.status === 401) {
            throw new Error("Challenge not met");
          }

          return res;
        })
        .then((res) => responseHandler(res, (err) => {
          if (err) {
            setContent({
              message: err.message,
              type: "error",
            })
          } else {
            setContent({
              type: "success",
              message: `${action} success!`
            })
          }
          setChallenge("");
          navigate("/");
        }, handlerMetadata))
        .catch((err) => console.error(err));      
    }, WAIT_MS);

    return () => {
      clearInterval(timer);
    }
  }, [challenge]);

  useEffect(() => {
    if (countdown === 0) {
      setContent({
        type: "error",
        message: "Authentication timed out after 100s, try again",
      });
      navigate("/");
      return;
    }
    const countdownTimer = setTimeout(() => {
      setCountdown(countdown - 1);
    }, 1000);

    return () => {
      clearTimeout(countdownTimer);
    }
  }, [countdown]);

  return ( 
    <ColumnLayout columns={3}>
      <div></div>
      <Container>
        <ColumnLayout columns={1}>
          <Header>Authentication for <code>{action}</code> on <code>{subdomain}</code></Header>
          {loading && <Spinner size="big" />}
          {!loading && (
            <>
              <ColumnLayout columns={3}>
                <div></div>
                <QRCode value={qrContent} />
              </ColumnLayout>
              <ProgressBar 
                label={"Remaining Time"} 
                description={"Complete authentication before the timer expires"} 
                additionalInfo={"Authentication expires after 100s to keep your files secure. Please complete the login challenge within the time remaining"} 
                value={countdown}
              />
            </>
          )}
        </ColumnLayout>
      </Container>
    </ColumnLayout>
    
  )
}