"use client";

import NextLink from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
import {
  useEffect,
  useRef,
  useState,
  type ClipboardEvent,
  type SyntheticEvent,
} from "react";

import Box from "@mui/material/Box";
import Link from "@mui/material/Link";
import OutlinedInput from "@mui/material/OutlinedInput";
import Paper from "@mui/material/Paper";
import Typography from "@mui/material/Typography";

import { ArrowLeftIcon } from "@/features/auth/components/auth-icons";
import { AuthLogoHeader } from "@/features/auth/components/auth-logo-header";
import { AuthPrimaryButton } from "@/features/auth/components/auth-primary-button";
import { forgotPassword } from "@/features/auth/service/auth-service";

const OTP_LENGTH = 6;
const RESEND_SECONDS = 60;

type OtpInputRowProps = {
  digits: string[];
  error: boolean;
  onChange: (next: string[]) => void;
};

function OtpInputRow({ digits, error, onChange }: OtpInputRowProps) {
  const inputRefs = useRef<Array<HTMLInputElement | null>>([]);

  function updateDigit(index: number, nextValue: string) {
    const onlyDigit = nextValue.replace(/\D/g, "").slice(-1);

    const nextDigits = digits.map((currentDigit, currentIndex) =>
      currentIndex === index ? onlyDigit : currentDigit,
    );

    onChange(nextDigits);

    if (onlyDigit && index < OTP_LENGTH - 1) {
      inputRefs.current[index + 1]?.focus();
    }
  }

  function moveFocusBack(index: number, key: string) {
    if (key !== "Backspace") {
      return;
    }

    if (digits[index] || index === 0) {
      return;
    }

    inputRefs.current[index - 1]?.focus();
  }

  function handlePaste(event: ClipboardEvent<HTMLInputElement>) {
    const pasted = event.clipboardData
      .getData("text")
      .replace(/\D/g, "")
      .slice(0, OTP_LENGTH);

    if (!pasted) {
      return;
    }

    event.preventDefault();

    const nextDigits = Array.from({ length: OTP_LENGTH }, (_, index) =>
      pasted[index] ?? "",
    );

    onChange(nextDigits);

    const focusIndex = Math.min(pasted.length, OTP_LENGTH - 1);
    inputRefs.current[focusIndex]?.focus();
  }

  return (
    <Box
      sx={{
        display: "grid",
        gridTemplateColumns: `repeat(${OTP_LENGTH}, minmax(0, 1fr))`,
        gap: { xs: 1, sm: 2 },
      }}
    >
      {digits.map((digit, index) => (
        <OutlinedInput
          key={index}
          error={error}
          inputRef={(element) => {
            inputRefs.current[index] = element;
          }}
          inputProps={{
            "aria-label": `OTP digit ${index + 1}`,
            inputMode: "numeric",
            maxLength: 1,
            sx: {
              px: 0,
              py: "11px",
              textAlign: "center",
            },
          }}
          onChange={(event) => updateDigit(index, event.target.value)}
          onKeyDown={(event) => moveFocusBack(index, event.key)}
          onPaste={handlePaste}
          value={digit}
          sx={{
            height: 40,
            borderRadius: "10px",
            backgroundColor: "#ffffff",
            fontSize: 12,
            fontWeight: 600,
            color: "#535862",
            "& .MuiOutlinedInput-input": {
              textAlign: "center",
            },
            "& .MuiOutlinedInput-notchedOutline": {
              borderColor: error ? "#F04438" : "#e9eaeb",
            },
            "&:hover .MuiOutlinedInput-notchedOutline": {
              borderColor: error ? "#F04438" : "#d5d7da",
            },
            "&.Mui-focused .MuiOutlinedInput-notchedOutline": {
              borderColor: error ? "#F04438" : "#144167",
              borderWidth: 1,
            },
          }}
        />
      ))}
    </Box>
  );
}

export function OtpScreen() {
  const router = useRouter();
  const searchParams = useSearchParams();
  const email = searchParams.get("email") ?? "";

  const [digits, setDigits] = useState<string[]>(() =>
    Array.from({ length: OTP_LENGTH }, () => ""),
  );
  const [otpError, setOtpError] = useState("");
  const [message, setMessage] = useState("");
  const [secondsLeft, setSecondsLeft] = useState(RESEND_SECONDS);
  const [isResending, setIsResending] = useState(false);

  useEffect(() => {
    if (secondsLeft <= 0) {
      return;
    }

    const timer = window.setTimeout(() => {
      setSecondsLeft((value) => value - 1);
    }, 1000);

    return () => window.clearTimeout(timer);
  }, [secondsLeft]);

  function handleSubmit(event: SyntheticEvent<HTMLFormElement>) {
    event.preventDefault();
    setOtpError("");

    if (!email) {
      setOtpError("Missing email. Please start from the forgot password page.");
      return;
    }

    const otp = digits.join("");

    if (otp.length !== OTP_LENGTH) {
      setOtpError("Please enter the 6-digit OTP.");
      return;
    }

    const query = new URLSearchParams({ email, otp });
    router.push(`/auth/reset-password?${query.toString()}`);
  }

  async function handleResend() {
    if (secondsLeft > 0 || isResending) {
      return;
    }

    if (!email) {
      setOtpError("Missing email. Please start from the forgot password page.");
      return;
    }

    try {
      setIsResending(true);
      setMessage("");
      setOtpError("");

      await forgotPassword({ email });

      setMessage("A new OTP has been sent to your email.");
      setSecondsLeft(RESEND_SECONDS);
    } catch (error) {
      setOtpError(
        error instanceof Error ? error.message : "Unable to resend the OTP.",
      );
    } finally {
      setIsResending(false);
    }
  }

  const canResend = secondsLeft <= 0 && !isResending;
  const countdownLabel = secondsLeft.toString().padStart(2, "0") + "s";

  return (
    <Box
      sx={{
        minHeight: "100dvh",
        display: "flex",
        alignItems: { xs: "flex-start", md: "center" },
        justifyContent: "center",
        px: { xs: 2, sm: 3 },
        py: { xs: 2, sm: 3 },
      }}
    >
      <Paper
        elevation={0}
        sx={{
          width: "100%",
          maxWidth: 560,
          borderRadius: { xs: "20px", md: "12px" },
          border: "1px solid #edf8fd",
          backgroundColor: "#ffffff",
        }}
      >
        <Box
          component="form"
          onSubmit={handleSubmit}
          sx={{
            px: { xs: 3, sm: 5 },
            pt: { xs: 3, sm: 3.5 },
            pb: { xs: 5, sm: 6 },
            minHeight: { md: 730 },
          }}
        >
          <Link
            component={NextLink}
            href="/auth/forgot-password"
            underline="none"
            sx={{
              display: "inline-flex",
              alignItems: "center",
              gap: 1,
              fontSize: 14,
              fontWeight: 500,
              color: "#717680",
            }}
          >
            <ArrowLeftIcon />
            Back
          </Link>

          <Box
            sx={{
              mt: { xs: 8, sm: 10 },
              maxWidth: 401,
              mx: "auto",
              display: "flex",
              flexDirection: "column",
              gap: 4.5,
            }}
          >
            <AuthLogoHeader title="Enter the OTP" />

            <Box sx={{ width: "100%" }}>
              <Typography
                component="label"
                sx={{
                  display: "block",
                  mb: 2,
                  fontSize: 12,
                  fontWeight: 500,
                  lineHeight: 1,
                  color: "#414651",
                }}
              >
                OTP Number
                {email ? (
                  <Box
                    component="span"
                    sx={{ ml: 0.75, color: "#717680", fontWeight: 400 }}
                  >
                    sent to {email}
                  </Box>
                ) : null}
              </Typography>

              <OtpInputRow
                digits={digits}
                error={Boolean(otpError)}
                onChange={(next) => {
                  setDigits(next);
                  setOtpError("");
                }}
              />

              {otpError ? (
                <Typography
                  sx={{
                    mt: 1,
                    color: "#F04438",
                    fontSize: 12,
                    fontWeight: 600,
                    lineHeight: 1.4,
                  }}
                >
                  {otpError}
                </Typography>
              ) : null}

              {message ? (
                <Typography
                  sx={{
                    mt: 1,
                    color: "#17B26A",
                    fontSize: 12,
                    fontWeight: 600,
                    lineHeight: 1.4,
                  }}
                >
                  {message}
                </Typography>
              ) : null}

              <Box
                sx={{
                  mt: 1.5,
                  display: "flex",
                  alignItems: "center",
                  justifyContent: "space-between",
                  fontSize: 12,
                  fontWeight: 600,
                  color: "#717680",
                }}
              >
                <Typography
                  component="span"
                  sx={{ fontSize: 12, fontWeight: 600 }}
                >
                  {countdownLabel}
                </Typography>

                <Link
                  component="button"
                  type="button"
                  onClick={handleResend}
                  disabled={!canResend}
                  underline="none"
                  sx={{
                    fontSize: 12,
                    fontWeight: 600,
                    color: canResend ? "#1570EF" : "#717680",
                    cursor: canResend ? "pointer" : "not-allowed",
                    background: "none",
                    border: "none",
                    p: 0,
                  }}
                >
                  {isResending ? "Sending..." : "Resend"}
                </Link>
              </Box>
            </Box>

            <AuthPrimaryButton type="submit">Next</AuthPrimaryButton>
          </Box>
        </Box>
      </Paper>
    </Box>
  );
}
