"use client";

import { useEffect, useMemo, useRef, useState } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useLang } from "@/context/LanguageContext";
import { LanguageSwitcher } from "@/components/LanguageSwitcher";
import { Alert, Spinner } from "@/components/ui";
import { api } from "@/lib/client";
import { IncrelogLogo } from "@/components/IncrelogLogo";
import {
  IconArrowRight,
  IconCheck,
  IconCheckCircle,
  IconClock,
  IconEye,
  IconEyeOff,
  IconKey,
  IconLock,
  IconMail,
  IconMessageCircle,
  IconUser,
} from "@/components/icons";

interface Channel {
  type: "EMAIL" | "SMS";
  masked: string;
}

const OTP_LENGTH = 6;

function ForgotFlow() {
  const { t } = useLang();
  const router = useRouter();
  const f = t.auth.forgot;

  const [step, setStep] = useState<1 | 2 | 3 | 4>(1);
  const [error, setError] = useState("");
  const [notice, setNotice] = useState("");

  // step 1 — identify
  const [institutionCode, setInstitutionCode] = useState("");
  const [username, setUsername] = useState("");
  const [email, setEmail] = useState("");
  const [identifying, setIdentifying] = useState(false);
  const [token, setToken] = useState("");
  const [accountName, setAccountName] = useState("");
  const [channels, setChannels] = useState<Channel[]>([]);
  const memberMode = institutionCode.trim().length > 0;

  // step 2 — channel + OTP
  const [channel, setChannel] = useState<Channel | null>(null);
  const [sending, setSending] = useState(false);
  const [otpSent, setOtpSent] = useState(false);
  const [otp, setOtp] = useState<string[]>(Array(OTP_LENGTH).fill(""));
  const [verifying, setVerifying] = useState(false);
  const [resetToken, setResetToken] = useState("");
  const [devCode, setDevCode] = useState("");
  const [cooldown, setCooldown] = useState(0);
  const [expiryLeft, setExpiryLeft] = useState(0);
  const otpRefs = useRef<(HTMLInputElement | null)[]>([]);

  // step 3 — new password
  const [password, setPassword] = useState("");
  const [confirm, setConfirm] = useState("");
  const [showPassword, setShowPassword] = useState(false);
  const [resetting, setResetting] = useState(false);

  useEffect(() => {
    if (cooldown <= 0) return;
    const id = setTimeout(() => setCooldown((c) => c - 1), 1000);
    return () => clearTimeout(id);
  }, [cooldown]);

  useEffect(() => {
    if (expiryLeft <= 0) return;
    const id = setTimeout(() => setExpiryLeft((c) => c - 1), 1000);
    return () => clearTimeout(id);
  }, [expiryLeft]);

  const otpValue = useMemo(() => otp.join(""), [otp]);

  function mapError(code: string): string {
    const map: Record<string, string> = {
      IDENTIFY_FAILED: f.errIdentify,
      SESSION_EXPIRED: f.errExpired,
      CHANNEL_UNAVAILABLE: f.errChannel,
      CHANNEL_NOT_CONFIGURED: f.errNotConfigured,
      COOLDOWN: f.errCooldown,
      TOO_MANY: f.errTooMany,
      OTP_EXPIRED: f.errOtpExpired,
      INVALID_CODE: f.errInvalidCode,
      TOO_MANY_ATTEMPTS: f.errAttempts,
      PASSWORD_TOO_SHORT: f.errShortPassword,
      SEND_FAILED: f.errSend,
      TARGET_REQUIRED: f.errTarget,
    };
    return map[code] ?? code;
  }

  async function identify(e: React.FormEvent) {
    e.preventDefault();
    setError("");
    setNotice("");
    setIdentifying(true);
    try {
      const res = await api<{
        token: string;
        name: string;
        channels: Channel[];
        institution: string | null;
      }>("/api/auth/forgot-password/identify", {
        method: "POST",
        body: JSON.stringify({
          email: memberMode ? "" : email.trim(),
          institutionCode: memberMode ? institutionCode.trim().toUpperCase() : "",
          username: memberMode ? username.trim() : "",
        }),
      });
      if (res.channels.length === 0) {
        setError(f.errNoChannels);
        return;
      }
      setToken(res.token);
      setAccountName(res.name);
      setChannels(res.channels);
      setChannel(res.channels[0]);
      setStep(2);
    } catch (err) {
      setError(mapError(err instanceof Error ? err.message : ""));
    } finally {
      setIdentifying(false);
    }
  }

  async function sendOtp(isResend = false) {
    if (!channel || !token) return;
    setError("");
    setNotice("");
    setSending(true);
    setDevCode("");
    try {
      const res = await api<{
        sent: boolean;
        masked: string;
        expiresAt: string;
        devCode?: string;
      }>("/api/auth/forgot-password/send", {
        method: "POST",
        body: JSON.stringify({ token, channel: channel.type }),
      });
      setOtpSent(true);
      setOtp(Array(OTP_LENGTH).fill(""));
      setCooldown(60);
      setExpiryLeft(Math.max(1, Math.floor((new Date(res.expiresAt).getTime() - Date.now()) / 1000)));
      if (res.devCode) setDevCode(res.devCode);
      if (isResend) setNotice(f.resent);
      setTimeout(() => otpRefs.current[0]?.focus(), 60);
    } catch (err) {
      setError(mapError(err instanceof Error ? err.message : ""));
    } finally {
      setSending(false);
    }
  }

  async function verify(e?: React.FormEvent) {
    e?.preventDefault();
    if (otpValue.length !== OTP_LENGTH || verifying) return;
    setError("");
    setVerifying(true);
    try {
      const res = await api<{ resetToken: string }>("/api/auth/forgot-password/verify", {
        method: "POST",
        body: JSON.stringify({ token, code: otpValue }),
      });
      setResetToken(res.resetToken);
      setStep(3);
    } catch (err) {
      setError(mapError(err instanceof Error ? err.message : ""));
      document.querySelector(".ems-otp-row")?.classList.add("shake");
      setTimeout(() => document.querySelector(".ems-otp-row")?.classList.remove("shake"), 400);
      setOtp(Array(OTP_LENGTH).fill(""));
      otpRefs.current[0]?.focus();
    } finally {
      setVerifying(false);
    }
  }

  async function reset(e: React.FormEvent) {
    e.preventDefault();
    setError("");
    if (password !== confirm) {
      setError(f.errMismatch);
      return;
    }
    setResetting(true);
    try {
      await api("/api/auth/forgot-password/reset", {
        method: "POST",
        body: JSON.stringify({ resetToken, password }),
      });
      setStep(4);
    } catch (err) {
      setError(mapError(err instanceof Error ? err.message : ""));
    } finally {
      setResetting(false);
    }
  }

  function setOtpDigit(idx: number, raw: string) {
    const digits = raw.replace(/\D/g, "");
    if (!digits) {
      setOtp((prev) => prev.map((d, i) => (i === idx ? "" : d)));
      return;
    }
    setOtp((prev) => {
      const next = [...prev];
      digits.split("").forEach((d, k) => {
        if (idx + k < OTP_LENGTH) next[idx + k] = d;
      });
      return next;
    });
    const focusIdx = Math.min(idx + digits.length, OTP_LENGTH - 1);
    otpRefs.current[focusIdx]?.focus();
  }

  function onOtpKeyDown(idx: number, e: React.KeyboardEvent<HTMLInputElement>) {
    if (e.key === "Backspace" && !otp[idx] && idx > 0) {
      otpRefs.current[idx - 1]?.focus();
      setOtp((prev) => prev.map((d, i) => (i === idx - 1 ? "" : d)));
    }
    if (e.key === "ArrowLeft" && idx > 0) otpRefs.current[idx - 1]?.focus();
    if (e.key === "ArrowRight" && idx < OTP_LENGTH - 1) otpRefs.current[idx + 1]?.focus();
  }

  function mmss(sec: number) {
    const m = Math.floor(sec / 60);
    const s = sec % 60;
    return `${m}:${String(s).padStart(2, "0")}`;
  }

  const steps = [f.step1, f.step2, f.step3];

  return (
    <div className="w-100" style={{ maxWidth: 470 }}>
      <div className="login-form card" style={{ borderRadius: 12, border: "none", boxShadow: "0 10px 40px rgba(36,105,92,0.12)" }}>
        <div className="card-body p-4 p-md-5">
          <div className="text-center mb-4">
            <span className="mb-3 d-inline-block">
              <IncrelogLogo size={56} />
            </span>
            <h4 className="f-w-700 mb-1">{f.title}</h4>
            <h6 className="text-muted f-w-500">
              {step === 1 ? f.subtitle1 : step === 2 ? f.subtitle2 : step === 3 ? f.subtitle3 : f.subtitle4}
            </h6>
          </div>

          {/* step indicator */}
          {step < 4 && (
            <div className="ems-forgot-steps mb-4">
              {steps.map((label, i) => {
                const n = (i + 1) as 1 | 2 | 3;
                return (
                  <div className={`ems-step ${step === n ? "active" : ""} ${step > n ? "done" : ""}`} key={n}>
                    {n > 1 && <span className="bar" />}
                    <span className="n">{step > n ? <IconCheck className="svg-12" /> : n}</span>
                    <span className="lbl d-none d-sm-inline">{label}</span>
                  </div>
                );
              })}
            </div>
          )}

          {error && (
            <div className="mb-3">
              <Alert type="error" onClose={() => setError("")}>{error}</Alert>
            </div>
          )}
          {notice && (
            <div className="mb-3">
              <Alert type="success" onClose={() => setNotice("")}>{notice}</Alert>
            </div>
          )}
          {devCode && (
            <div className="mb-3">
              <Alert type="info" onClose={() => setDevCode("")}>
                {f.devCode}: <b className="ems-otp-preview">{devCode}</b>
              </Alert>
            </div>
          )}

          {/* STEP 1 — identify the account */}
          {step === 1 && (
            <form className="theme-form" onSubmit={identify}>
              <div className="form-group">
                <label className="col-form-label pt-0 f-w-600">
                  {t.auth.institutionCode}{" "}
                  <span className="text-muted f-w-500 ems-fs-11">({t.common.optional})</span>
                </label>
                <div className="input-group">
                  <span className="input-group-text"><IconKey className="svg-16" /></span>
                  <input
                    className="form-control text-uppercase"
                    type="text"
                    value={institutionCode}
                    onChange={(e) => setInstitutionCode(e.target.value.toUpperCase())}
                    placeholder="HS-1001"
                    autoComplete="off"
                  />
                </div>
                <p className="mb-0 mt-1 ems-fs-11 text-muted">{t.auth.institutionCodeHint}</p>
              </div>
              {memberMode ? (
                <div className="form-group">
                  <label className="col-form-label pt-0 f-w-600">{t.auth.username}</label>
                  <div className="input-group">
                    <span className="input-group-text"><IconUser className="svg-16" /></span>
                    <input
                      className="form-control"
                      type="text"
                      required
                      value={username}
                      onChange={(e) => setUsername(e.target.value)}
                      placeholder="1001"
                      autoComplete="username"
                    />
                  </div>
                </div>
              ) : (
                <div className="form-group">
                  <label className="col-form-label pt-0 f-w-600">{t.common.email}</label>
                  <div className="input-group">
                    <span className="input-group-text"><IconMail className="svg-16" /></span>
                    <input
                      className="form-control"
                      type="email"
                      required
                      value={email}
                      onChange={(e) => setEmail(e.target.value)}
                      placeholder="admin@increlogems.com"
                      autoComplete="email"
                    />
                  </div>
                </div>
              )}
              <div className="form-group mb-4">
                <button className="btn btn-primary btn-block w-100" type="submit" disabled={identifying}>
                  {identifying && <span className="spinner-border spinner-border-sm me-2" />}
                  {f.findAccount}
                  {!identifying && <IconArrowRight className="svg-14 ms-1" />}
                </button>
              </div>
            </form>
          )}

          {/* STEP 2 — choose channel, verify OTP */}
          {step === 2 && (
            <div>
              <div className="d-flex align-items-center gap-2 mb-3 p-2" style={{ background: "rgba(36,105,92,.06)", borderRadius: 10 }}>
                <span
                  className="d-inline-flex align-items-center justify-content-center"
                  style={{ width: 34, height: 34, borderRadius: 9, background: "#24695c", color: "#fff" }}
                >
                  <IconUser className="svg-16" />
                </span>
                <div className="min-w-0">
                  <div className="f-w-700 ems-fs-13 text-truncate">{accountName}</div>
                  <div className="ems-fs-11 text-muted">{f.accountFound}</div>
                </div>
              </div>

              {!otpSent ? (
                <>
                  <label className="col-form-label pt-0 f-w-600">{f.chooseChannel}</label>
                  <div className="mb-3">
                    {channels.map((ch) => (
                      <button
                        type="button"
                        key={ch.type}
                        className={`ems-channel-card ${channel?.type === ch.type ? "selected" : ""}`}
                        onClick={() => setChannel(ch)}
                      >
                        <span className="ic">
                          {ch.type === "EMAIL" ? <IconMail className="svg-18" /> : <IconMessageCircle className="svg-18" />}
                        </span>
                        <span className="min-w-0">
                          <span className="ttl d-block">{ch.type === "EMAIL" ? f.viaEmail : f.viaSms}</span>
                          <span className="dst d-block text-truncate">{ch.masked}</span>
                        </span>
                        <span className="tick"><IconCheck className="svg-12" /></span>
                      </button>
                    ))}
                  </div>
                  <button
                    className="btn btn-primary btn-block w-100"
                    type="button"
                    disabled={!channel || sending}
                    onClick={() => sendOtp()}
                  >
                    {sending && <span className="spinner-border spinner-border-sm me-2" />}
                    {f.sendCode}
                  </button>
                </>
              ) : (
                <form onSubmit={verify}>
                  <p className="ems-fs-13 text-center mb-1">
                    {channel?.type === "EMAIL" ? f.codeSentEmail : f.codeSentSms}{" "}
                    <b>{channel?.masked}</b>
                  </p>
                  <div className="ems-otp-row" onPaste={(e) => {
                    e.preventDefault();
                    setOtpDigit(0, e.clipboardData.getData("text"));
                  }}>
                    {otp.map((d, i) => (
                      <input
                        key={i}
                        ref={(el) => { otpRefs.current[i] = el; }}
                        className={`ems-otp-box ${d ? "filled" : ""}`}
                        type="text"
                        inputMode="numeric"
                        autoComplete="one-time-code"
                        maxLength={OTP_LENGTH}
                        value={d}
                        onChange={(e) => setOtpDigit(i, e.target.value)}
                        onKeyDown={(e) => onOtpKeyDown(i, e)}
                        autoFocus={i === 0}
                      />
                    ))}
                  </div>
                  <div className="d-flex align-items-center justify-content-center gap-3 ems-fs-12 text-muted mt-1 mb-3">
                    {expiryLeft > 0 ? (
                      <span className="d-inline-flex align-items-center gap-1">
                        <IconClock className="svg-12" /> {f.expiresIn.replace("{time}", mmss(expiryLeft))}
                      </span>
                    ) : (
                      <span className="text-danger f-w-600">{f.codeExpired}</span>
                    )}
                  </div>
                  <button
                    className="btn btn-primary btn-block w-100 mb-2"
                    type="submit"
                    disabled={otpValue.length !== OTP_LENGTH || verifying || expiryLeft <= 0}
                  >
                    {verifying && <span className="spinner-border spinner-border-sm me-2" />}
                    {f.verify}
                  </button>
                  <div className="text-center">
                    {cooldown > 0 ? (
                      <span className="ems-fs-12 text-muted">{f.resendIn.replace("{sec}", String(cooldown))}</span>
                    ) : (
                      <button
                        type="button"
                        className="btn btn-link ems-fs-12 f-w-600 ems-text-teal p-0"
                        onClick={() => sendOtp(true)}
                        disabled={sending}
                      >
                        {f.resend}
                      </button>
                    )}
                  </div>
                </form>
              )}

              <button
                type="button"
                className="btn btn-link ems-fs-12 text-muted p-0 mt-3 d-block mx-auto"
                onClick={() => { setStep(1); setOtpSent(false); setOtp(Array(OTP_LENGTH).fill("")); }}
              >
                ← {f.useDifferentAccount}
              </button>
            </div>
          )}

          {/* STEP 3 — new password */}
          {step === 3 && (
            <form className="theme-form" onSubmit={reset}>
              <div className="form-group">
                <label className="col-form-label pt-0 f-w-600">{f.newPassword}</label>
                <div className="input-group">
                  <span className="input-group-text"><IconLock className="svg-16" /></span>
                  <input
                    className="form-control"
                    type={showPassword ? "text" : "password"}
                    required
                    minLength={6}
                    value={password}
                    onChange={(e) => setPassword(e.target.value)}
                    placeholder="**********"
                    autoComplete="new-password"
                  />
                  <div className="show-hide" onClick={() => setShowPassword((s) => !s)}>
                    <span className="show d-inline-flex align-items-center cursor-pointer px-2">
                      {showPassword ? <IconEyeOff className="svg-16" /> : <IconEye className="svg-16" />}
                    </span>
                  </div>
                </div>
                <p className="mb-0 mt-1 ems-fs-11 text-muted">{f.passwordHint}</p>
              </div>
              <div className="form-group">
                <label className="col-form-label pt-0 f-w-600">{f.confirmPassword}</label>
                <div className="input-group">
                  <span className="input-group-text"><IconCheckCircle className="svg-16" /></span>
                  <input
                    className="form-control"
                    type={showPassword ? "text" : "password"}
                    required
                    minLength={6}
                    value={confirm}
                    onChange={(e) => setConfirm(e.target.value)}
                    placeholder="**********"
                    autoComplete="new-password"
                    style={confirm && confirm !== password ? { borderColor: "#dc3545" } : undefined}
                  />
                </div>
                {confirm && confirm !== password && (
                  <p className="mb-0 mt-1 ems-fs-11 text-danger">{f.errMismatch}</p>
                )}
              </div>
              <div className="form-group mb-4">
                <button className="btn btn-primary btn-block w-100" type="submit" disabled={resetting || password !== confirm}>
                  {resetting && <span className="spinner-border spinner-border-sm me-2" />}
                  {f.resetButton}
                </button>
              </div>
            </form>
          )}

          {/* STEP 4 — success */}
          {step === 4 && (
            <div className="ems-forgot-success text-center py-3">
              <div
                className="circle rounded-circle d-inline-flex align-items-center justify-content-center mb-4"
                style={{ width: 84, height: 84, background: "rgba(40,167,69,0.12)", color: "#1e7e34" }}
              >
                <span className="d-inline-flex" style={{ transform: "scale(2.4)" }}>
                  <IconCheckCircle />
                </span>
              </div>
              <div className="txt">
                <h5 className="f-w-800 mb-2">{f.successTitle}</h5>
                <p className="text-muted ems-fs-13 mb-4">{f.successNote}</p>
                <button
                  className="btn btn-primary w-100"
                  type="button"
                  onClick={() => router.push("/login")}
                >
                  {f.backToLogin}
                </button>
              </div>
            </div>
          )}

          {step < 4 && (
            <p className="text-center mb-0 ems-fs-13 mt-3">
              <Link href="/login" className="ems-text-teal f-w-700 text-decoration-none">
                ← {f.backToLogin}
              </Link>
            </p>
          )}
        </div>
      </div>
    </div>
  );
}

export default function ForgotPasswordPage() {
  const { t } = useLang();

  return (
    <div className="ems-auth-wrapper">
      <div className="container-fluid py-3">
        <div className="d-flex justify-content-end py-2">
          <LanguageSwitcher />
        </div>
        <div className="login-card">
          <ForgotFlow />
        </div>
      </div>
    </div>
  );
}
