"use client";

import * as React from "react";
import { signInCredentials } from "@/lib/credentials-sign-in";
import { REMEMBER_EMAIL_STORAGE_KEY } from "@/lib/client-sign-out";
import { useRouter } from "next/navigation";
import { useQueryState, parseAsString } from "nuqs";
import { useQueryClient } from "@tanstack/react-query";
import { prefetchDashboardSections } from "@/features/dashboard/api/prefetch-dashboard-sections";
import {
  fetchGroupedPipelineStages,
  fetchPipelinesClientCacheRevision,
  fetchPipelinesList,
  pipelinesKeys,
} from "@/hooks/use-pipelines-query";
import {
  writeLeadsPipelineStagesReady,
  writePipelinesRevisionPayload,
} from "@/lib/query-persist-storage";
import { Button } from "@/components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Eye, EyeOff, Loader2 } from "lucide-react";
import {
  InputOTP,
  InputOTPGroup,
  InputOTPSlot,
} from "@/components/ui/input-otp";
import { parseTwoFactorRequiredMessage } from "@/lib/two-factor-login-message";
import Link from "next/link";
import {
  ensureClientPublicIpForLogin,
  getStoredClientPublicIp,
} from "@/lib/client-public-ip";
import {
  CLIENT_GEO_KEYS,
  ensureClientGeoForLogin,
} from "@/lib/client-geo";
import { getSession } from "next-auth/react";
import { seedCachedSession } from "@/api/session-cache";
import type { PermissionSource } from "@/lib/permissions";
import { PROFILE_SETTINGS_PATH } from "@/lib/app-paths";
import { hasNoAppPermissions, getFirstAccessiblePath } from "@/lib/permissions";

function LoginForm() {
  const router = useRouter();
  const queryClient = useQueryClient();
  const dashboardUrl = "/leads";
  const [callbackUrl] = useQueryState(
    "callbackUrl",
    parseAsString.withDefault(dashboardUrl),
  );
  const [email, setEmail] = React.useState("");
  const [password, setPassword] = React.useState("");
  const [showPassword, setShowPassword] = React.useState(false);
  const [error, setError] = React.useState("");
  const [loading, setLoading] = React.useState(false);
  const [prefetching, setPrefetching] = React.useState(false);
  const [step, setStep] = React.useState<"password" | "2fa">("password");
  const [twoFactorMode, setTwoFactorMode] = React.useState<"totp" | "backup">(
    "totp",
  );
  const [twoFactorCode, setTwoFactorCode] = React.useState("");
  const [backupCode, setBackupCode] = React.useState("");
  const [rememberMe, setRememberMe] = React.useState(false);

  React.useEffect(() => {
    if (typeof window !== "undefined") {
      const savedEmail = localStorage.getItem(REMEMBER_EMAIL_STORAGE_KEY);
      if (savedEmail) {
        setEmail(savedEmail);
        setRememberMe(true);
      }
    }
  }, []);

  React.useEffect(() => {
    void ensureClientPublicIpForLogin();
  }, []);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setError("");
    setLoading(true);

    try {
      await ensureClientPublicIpForLogin();
      await ensureClientGeoForLogin();
      const clientPublicIp = getStoredClientPublicIp();
      const lat = sessionStorage.getItem(CLIENT_GEO_KEYS.lat) || "";
      const lng = sessionStorage.getItem(CLIENT_GEO_KEYS.lng) || "";
      const acc = sessionStorage.getItem(CLIENT_GEO_KEYS.acc) || "";

      const deviceMac =
        typeof window !== "undefined"
          ? sessionStorage.getItem("saleshub_device_mac")?.trim() || undefined
          : undefined;

      const result = await signInCredentials({
        email,
        password,
        clientPublicIp: clientPublicIp || undefined,
        deviceMac,
        latitude: lat,
        longitude: lng,
        accuracy: acc,
        ...(step === "2fa" &&
        twoFactorMode === "totp" &&
        twoFactorCode.trim().length === 6
          ? { twoFactorToken: twoFactorCode.trim() }
          : {}),
        ...(step === "2fa" && twoFactorMode === "backup" && backupCode.trim()
          ? { twoFactorBackupCode: backupCode.trim() }
          : {}),
        callbackUrl,
        redirect: false,
      });

      if (result?.error || !result?.ok) {
        setLoading(false);
        const errorMessage = result?.error || "Invalid email or password";

        const need2fa = parseTwoFactorRequiredMessage(errorMessage);
        if (need2fa && step === "password") {
          setStep("2fa");
          setTwoFactorMode("totp");
          setTwoFactorCode("");
          setBackupCode("");
          setError("");
          return;
        }

        if (errorMessage.toLowerCase().includes("inactive")) {
          setError(
            "Your account has been deactivated. Please contact an administrator.",
          );
        } else if (errorMessage.toLowerCase().includes("invalid credentials")) {
          setError("Invalid email or password");
        } else if (errorMessage.toLowerCase().includes("backup code")) {
          setError("Invalid backup code or key. Check dashes and try again.");
        } else if (errorMessage.toLowerCase().includes("verification code")) {
          setError("Invalid authenticator code. Try again.");
        } else {
          setError(errorMessage);
        }
        return;
      }

      // Start prefetching
      setLoading(false);
      setPrefetching(true);

      const nextUrl = result.url ?? callbackUrl ?? dashboardUrl;

      const sessionAfterSignIn = await getSession();
      seedCachedSession(sessionAfterSignIn);
      const backendUser = (
        sessionAfterSignIn as { backendUser?: PermissionSource } | null
      )?.backendUser;
      const destination =
        sessionAfterSignIn && backendUser
          ? getFirstAccessiblePath(backendUser)
          : nextUrl;

      try {
        if (
          destination !== "/profile" &&
          destination !== PROFILE_SETTINGS_PATH
        ) {
          // Prefetch basic data to make the transition smoother
          const pipelineStale = 1000 * 60 * 60 * 24 * 365;
          // Warm `/leads` board: pipelines list + **Lead** stages-grouped before navigation.
          // Deal stages-grouped stays deferred to `BackgroundPrefetcher` (idle) to cut load.
          await Promise.allSettled([
            queryClient.prefetchQuery({
              queryKey: pipelinesKeys.lists(),
              queryFn: fetchPipelinesList,
              staleTime: pipelineStale,
            }),
            queryClient.prefetchQuery({
              queryKey: pipelinesKeys.grouped({ stageType: "Lead" }),
              queryFn: () => fetchGroupedPipelineStages({ stageType: "Lead" }),
              staleTime: pipelineStale,
            }),
            prefetchDashboardSections(queryClient, "Lead", undefined),
          ]);

          if (typeof window !== "undefined") {
            try {
              const rev = await fetchPipelinesClientCacheRevision();
              const userKey = email.trim().toLowerCase();
              writePipelinesRevisionPayload({
                userKey,
                pipelinesList: rev.pipelinesList,
                stagesGroupedLead: rev.stagesGroupedLead,
                stagesGroupedDeal: rev.stagesGroupedDeal,
              });
              writeLeadsPipelineStagesReady({
                userKey,
                stagesGroupedLeadRev: rev.stagesGroupedLead,
                at: Date.now(),
              });
            } catch {
              // revision is optional; board still works from prefetch cache
            }
          }
        }
      } catch (prefetchErr) {
        console.warn("Prefetching during login failed:", prefetchErr);
      }

      setPrefetching(false);
      setStep("password");
      setTwoFactorMode("totp");
      setTwoFactorCode("");
      setBackupCode("");
      if (rememberMe) {
        localStorage.setItem(REMEMBER_EMAIL_STORAGE_KEY, email);
      } else {
        localStorage.removeItem(REMEMBER_EMAIL_STORAGE_KEY);
      }

      router.replace(destination);
      router.refresh();
    } catch (err) {
      setLoading(false);
      setPrefetching(false);
      setError("An unexpected error occurred. Please try again.");
      console.error("Login error:", err);
    }
  };

  return (
    <Card className="w-full max-w-[400px] bg-white/95 backdrop-blur-md border border-white/60 shadow-[0px_2px_20px_rgba(0,0,0,0.06),0_8px_32px_rgba(108,99,255,0.08)] rounded-2xl">
      <CardHeader className="space-y-4 pt-8">
        <div className="flex justify-center">
          <div className="w-12 h-12 rounded-xl bg-accent flex items-center justify-center text-xl font-extrabold text-white shadow-lg">
            J
          </div>
        </div>
        <div className="text-center space-y-1">
          <CardTitle className="text-2xl font-bold font-['Lexend'] tracking-tight text-[#101828]">
            Welcome back
          </CardTitle>
          <CardDescription className="text-[#575a62] text-xs uppercase tracking-widest font-semibold">
            Jumppace Sales Hub
          </CardDescription>
        </div>
      </CardHeader>
      <CardContent className="space-y-4">
        <form onSubmit={handleSubmit} className="space-y-4">
          {error && (
            <div className="p-3 rounded-lg bg-red-50 border border-red-200">
              <p className="text-sm text-red-600 font-medium">{error}</p>
            </div>
          )}
          {step === "2fa" ? (
            <div className="space-y-4">
              <div className="flex rounded-lg border border-[#E4E6EF] p-0.5 bg-[#F9FAFB]">
                <button
                  type="button"
                  className={`flex-1 rounded-md py-2 text-xs font-semibold transition-colors ${
                    twoFactorMode === "totp"
                      ? "bg-white text-[#101828] shadow-sm"
                      : "text-[#575a62] hover:text-[#101828]"
                  }`}
                  onClick={() => {
                    setTwoFactorMode("totp");
                    setBackupCode("");
                    setError("");
                  }}
                >
                  Authenticator app
                </button>
                <button
                  type="button"
                  className={`flex-1 rounded-md py-2 text-xs font-semibold transition-colors ${
                    twoFactorMode === "backup"
                      ? "bg-white text-[#101828] shadow-sm"
                      : "text-[#575a62] hover:text-[#101828]"
                  }`}
                  onClick={() => {
                    setTwoFactorMode("backup");
                    setTwoFactorCode("");
                    setError("");
                  }}
                >
                  Backup code / key
                </button>
              </div>
              {twoFactorMode === "totp" ? (
                <>
                  <p className="text-sm text-[#575a62] text-center">
                    Open your authenticator app and enter the 6-digit code for{" "}
                    <span className="font-semibold text-[#101828]">
                      SalesHub
                    </span>
                    .
                  </p>
                  <div className="flex justify-center py-2">
                    <InputOTP
                      maxLength={6}
                      value={twoFactorCode}
                      onChange={(value) =>
                        setTwoFactorCode(value.replace(/\D/g, ""))
                      }
                    >
                      <InputOTPGroup className="gap-2">
                        <InputOTPSlot
                          index={0}
                          className="h-11 w-10 rounded-lg border-[#E4E6EF]"
                        />
                        <InputOTPSlot
                          index={1}
                          className="h-11 w-10 rounded-lg border-[#E4E6EF]"
                        />
                        <InputOTPSlot
                          index={2}
                          className="h-11 w-10 rounded-lg border-[#E4E6EF]"
                        />
                        <InputOTPSlot
                          index={3}
                          className="h-11 w-10 rounded-lg border-[#E4E6EF]"
                        />
                        <InputOTPSlot
                          index={4}
                          className="h-11 w-10 rounded-lg border-[#E4E6EF]"
                        />
                        <InputOTPSlot
                          index={5}
                          className="h-11 w-10 rounded-lg border-[#E4E6EF]"
                        />
                      </InputOTPGroup>
                    </InputOTP>
                  </div>
                </>
              ) : (
                <>
                  <p className="text-sm text-[#575a62] text-center leading-relaxed">
                    Paste <strong>one</strong> line from the{" "}
                    <strong>2FA recovery email</strong> (or the list shown in
                    settings right after you enabled 2FA). Short codes use{" "}
                    <strong>three</strong> blocks (e.g.{" "}
                    <span className="font-mono text-[11px]">
                      XXXX-XXXX-XXXX
                    </span>
                    ); long keys use <strong>six</strong> blocks.
                  </p>
                  <p className="text-[11px] text-amber-800/90 text-center bg-amber-50 border border-amber-200/80 rounded-lg px-2 py-1.5">
                    The <strong>authenticator secret</strong> (QR / manual setup
                    key) is <strong>not</strong> a backup code — it will always
                    show invalid here.
                  </p>
                  <Input
                    autoComplete="one-time-code"
                    placeholder="e.g. A1B2-C3D4-E5F6 (code) or six XXXX blocks (key)"
                    value={backupCode}
                    onChange={(e) => setBackupCode(e.target.value)}
                    className="bg-white/80 border-[#E4E6EF] text-[#101828] text-sm h-11 font-mono tracking-wide"
                  />
                </>
              )}
              <button
                type="button"
                className="w-full py-2 text-xs text-[#575a62] hover:text-[#101828] transition-colors"
                onClick={() => {
                  setStep("password");
                  setTwoFactorCode("");
                  setBackupCode("");
                  setError("");
                }}
              >
                ← Back to password
              </button>
            </div>
          ) : (
            <>
              <div className="space-y-2">
                <Label
                  htmlFor="email"
                  className="text-[#575a62] text-xs font-semibold uppercase tracking-wider"
                >
                  Email address
                </Label>
                <Input
                  id="email"
                  type="email"
                  placeholder="name@company.com"
                  value={email}
                  onChange={(e) => setEmail(e.target.value)}
                  required
                  className="bg-white/80 border-[#E4E6EF] focus-visible:ring-accent/50 text-[#101828] placeholder:text-[#6B7280] text-sm h-11"
                />
              </div>
              <div className="space-y-2">
                <Label
                  htmlFor="password"
                  className="text-[#575a62] text-xs font-semibold uppercase tracking-wider"
                >
                  Password
                </Label>
                <div className="relative">
                  <Input
                    id="password"
                    type={showPassword ? "text" : "password"}
                    value={password}
                    onChange={(e) => setPassword(e.target.value)}
                    required
                    className="bg-white/80 border-[#E4E6EF] focus-visible:ring-accent/50 text-[#101828] placeholder:text-[#6B7280] text-sm h-11 pr-10"
                  />
                  <button
                    type="button"
                    onClick={() => setShowPassword(!showPassword)}
                    className="absolute right-3 top-1/2 -translate-y-1/2 text-[#6B7280] hover:text-[#101828] transition-colors"
                    tabIndex={-1}
                  >
                    {showPassword ? <EyeOff size={16} /> : <Eye size={16} />}
                  </button>
                </div>
                <div className="flex items-center justify-between">
                  <div className="flex items-center space-x-2">
                    <Checkbox
                      id="remember"
                      checked={rememberMe}
                      onCheckedChange={(checked) => setRememberMe(!!checked)}
                      className="border-[#E4E6EF] data-[state=checked]:bg-accent data-[state=checked]:border-accent"
                    />
                    <Label
                      htmlFor="remember"
                      className="text-[#575a62] text-[11px] font-semibold uppercase tracking-wider cursor-pointer"
                    >
                      Remember me
                    </Label>
                  </div>
                  <Link
                    href="/forgot-password"
                    className="text-xs font-medium text-accent hover:underline"
                  >
                    Forgot password?
                  </Link>
                </div>
              </div>
            </>
          )}
          <Button
            type="submit"
            variant="premium"
            className="w-full h-11 text-sm mt-2"
            disabled={
              loading ||
              prefetching ||
              (step === "2fa" &&
                twoFactorMode === "totp" &&
                twoFactorCode.trim().length !== 6) ||
              (step === "2fa" &&
                twoFactorMode === "backup" &&
                !backupCode.trim())
            }
          >
            {loading || prefetching ? (
              <>
                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                {prefetching ? "Preparing dashboard..." : "Signing in..."}
              </>
            ) : step === "2fa" ? (
              "Verify and sign in"
            ) : (
              "Sign In to Dashboard"
            )}
          </Button>
        </form>
      </CardContent>
    </Card>
  );
}

export default function LoginPage() {
  return (
    <React.Suspense
      fallback={
        <Card className="w-full max-w-[400px] bg-white/95 border border-white/60 rounded-2xl shadow-lg animate-pulse">
          <CardHeader className="space-y-4 pt-8">
            <div className="h-12 w-12 rounded-xl bg-[#E4E6EF] mx-auto" />
            <div className="h-6 w-32 bg-[#E4E6EF] rounded mx-auto" />
            <div className="h-4 w-48 bg-[#E4E6EF] rounded mx-auto" />
          </CardHeader>
          <CardContent className="space-y-4">
            <div className="h-10 bg-[#E4E6EF] rounded" />
            <div className="h-10 bg-[#E4E6EF] rounded" />
            <div className="h-11 bg-[#E4E6EF] rounded" />
          </CardContent>
        </Card>
      }
    >
      <LoginForm />
    </React.Suspense>
  );
}
