import { A, useNavigate } from "@solidjs/router";
import { createMemo, createSignal, For, onMount, Show } from "solid-js";
import { useAuth } from "~/lib/auth";
import PublicBackground from "~/components/PublicBackground";
import PublicHeader from "~/components/PublicHeader";
import CaptchaCanvas from "~/components/CaptchaCanvas";
import { isValidEmail } from "~/lib/form-validation";
import { fetchCaptcha } from "~/lib/api";

type RoleKey = "company" | "job_seeker" | "professional" | "customer";

function normalizeRoleValue(value: unknown): string {
  return String(value || "")
    .trim()
    .toUpperCase()
    .replace(/\s+/g, "_");
}

function extractRoleKey(value: unknown): string {
  const normalized = normalizeRoleValue(value);
  if (normalized && normalized !== "[OBJECT_OBJECT]") return normalized;
  if (!value || typeof value !== "object") return normalized;
  const maybe = value as Record<string, unknown>;
  return normalizeRoleValue(
    maybe.key ?? maybe.role_key ?? maybe.roleKey ?? maybe.name ?? maybe.role ?? maybe.id
  );
}

function normalizeRoleKeysList(value: unknown): string[] {
  if (!Array.isArray(value)) return [];
  return value.map((item) => extractRoleKey(item)).filter(Boolean);
}

function isJobSeekerRole(roleKey: string): boolean {
  return normalizeRoleValue(roleKey) === "JOB_SEEKER";
}

function firstNonJobSeekerRole(roleKeys: string[]): string | null {
  for (const roleKey of roleKeys) {
    if (!isJobSeekerRole(roleKey)) return roleKey;
  }
  return null;
}

function getStoredPreferredRole(emailHint?: string): string | null {
  if (typeof window === "undefined") return null;
  const keys = ["nxtgauge_signup_profile_v1", "nxtgauge_auth_user", "nxtgauge_user"];

  for (const key of keys) {
    const raw = window.localStorage.getItem(key);
    if (!raw) continue;
    try {
      const parsed = JSON.parse(raw) as Record<string, any>;
      const storedEmail = String(parsed?.email || "")
        .trim()
        .toLowerCase();
      if (emailHint && storedEmail && storedEmail !== emailHint.trim().toLowerCase()) continue;

      const selectedProfessionalRole = normalizeRoleValue(parsed?.selectedProfessionalRole);
      if (selectedProfessionalRole) return selectedProfessionalRole;

      const activeRole = normalizeRoleValue(parsed?.active_role || parsed?.role);
      if (activeRole) return activeRole;
    } catch {
      // Ignore malformed local storage payloads.
    }
  }

  return null;
}

function resolveActiveRole(rawBackendRole: unknown, emailHint?: string): string {
  const backendRole = normalizeRoleValue(rawBackendRole);
  if (backendRole) return backendRole;
  const preferredRole = getStoredPreferredRole(emailHint);
  if (preferredRole) return preferredRole;
  return "";
}

function PasswordVisibilityIcon(props: { visible: boolean }) {
  if (props.visible) {
    return (
      <svg viewBox="0 0 24 24" aria-hidden="true">
        <path d="M3 3l18 18" />
        <path d="M10.58 10.58a2 2 0 0 0 2.83 2.83" />
        <path d="M9.88 5.09A11 11 0 0 1 12 4.9c5.5 0 10 4.1 10 7.1 0 1.2-.72 2.53-1.95 3.72" />
        <path d="M6.1 6.1C3.54 7.58 2 9.79 2 12c0 3 4.48 7.1 10 7.1 1.72 0 3.36-.4 4.84-1.12" />
      </svg>
    );
  }
  return (
    <svg viewBox="0 0 24 24" aria-hidden="true">
      <path d="M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7-10-7-10-7z" />
      <circle cx="12" cy="12" r="3" />
    </svg>
  );
}

export default function LoginRoute() {
  const navigate = useNavigate();
  const auth = useAuth();
  const [email, setEmail] = createSignal("");
  const [password, setPassword] = createSignal("");
  const [otp, setOtp] = createSignal(["", "", "", "", "", ""]);
  const [showVerify, setShowVerify] = createSignal(false);
  const [showPassword, setShowPassword] = createSignal(false);
  const [captchaId, setCaptchaId] = createSignal("");
  const [captchaChallenge, setCaptchaChallenge] = createSignal("");
  const [captchaInput, setCaptchaInput] = createSignal("");
  const [error, setError] = createSignal("");
  const [submitting, setSubmitting] = createSignal(false);
  const [roleGuess, setRoleGuess] = createSignal<RoleKey>("job_seeker");
  const [roleHint, setRoleHint] = createSignal("");
  const [checkingRole, setCheckingRole] = createSignal(false);

  const otpCode = createMemo(() => otp().join(""));

  const loadCaptcha = async () => {
    setCaptchaInput("");
    try {
      const challenge = await fetchCaptcha();
      setCaptchaId(challenge.captcha_id);
      setCaptchaChallenge(challenge.challenge);
    } catch {
      setCaptchaId("");
      setCaptchaChallenge("");
    }
  };

  onMount(() => {
    void loadCaptcha();
  });

  const formatRoleLabel = (value: string): string =>
    String(value || "")
      .trim()
      .replace(/[_\s]+/g, " ")
      .toLowerCase()
      .replace(/\b\w/g, (ch) => ch.toUpperCase());

  const lookupRoleByEmail = async (emailValue: string) => {
    const normalized = emailValue.trim().toLowerCase();
    if (!normalized || !isValidEmail(normalized)) {
      setRoleHint("");
      return;
    }
    setCheckingRole(true);
    try {
      const response = await fetch("/api/auth/check-email", {
        method: "POST",
        headers: { "Content-Type": "application/json", Accept: "application/json" },
        credentials: "include",
        body: JSON.stringify({ email: normalized }),
      });
      const payload = await response.json().catch(() => ({}));
      if (!response.ok || !payload?.exists) {
        setRoleHint("");
        return;
      }
      const detectedRole = normalizeRoleValue(
        payload?.active_role || payload?.role || payload?.roles?.[0]
      );
      if (!detectedRole) {
        const fallbackRole = normalizeRoleValue(getStoredPreferredRole(normalized));
        setRoleHint(fallbackRole ? `Role: ${formatRoleLabel(fallbackRole)}` : "Role: Not assigned");
        return;
      }
      setRoleHint(`Role: ${formatRoleLabel(detectedRole)}`);
      const roleLower = detectedRole.toLowerCase();
      if (
        roleLower === "company" ||
        roleLower === "customer" ||
        roleLower === "job_seeker" ||
        roleLower === "professional"
      ) {
        setRoleGuess(roleLower as RoleKey);
      }
    } catch {
      setRoleHint("");
    } finally {
      setCheckingRole(false);
    }
  };

  const setOtpDigit = (index: number, value: string) => {
    const clean = value.replace(/\D/g, "").slice(0, 1);
    setOtp((prev) => {
      const next = prev.slice();
      next[index] = clean;
      return next;
    });
    // Defer focus until after SolidJS reactive flush so the next input exists in DOM
    queueMicrotask(() => {
      if (clean && index < 5) {
        const nextEl = document.querySelector<HTMLInputElement>(`#login-otp-${index + 1}`);
        if (nextEl) nextEl.focus();
      }
    });
  };

  const saveUser = (user: any) => {
    const fullName = String(user?.full_name || user?.fullName || "").trim();
    const [firstName, ...rest] = fullName.split(" ");
    const lastName = rest.join(" ");
    // Trust the passed-in role and never force a JOB_SEEKER fallback.
    const preferredRole = getStoredPreferredRole(String(user?.email || email()));
    const normalizedRole = normalizeRoleValue(
      user?.active_role || user?.role || preferredRole || ""
    );
    const storedRole = normalizedRole ? normalizedRole.toLowerCase() : "";
    const selectedRoleForStorage =
      isJobSeekerRole(normalizedRole) && preferredRole && !isJobSeekerRole(preferredRole)
        ? preferredRole
        : normalizedRole;

    const payload = {
      firstName: firstName || "",
      lastName: lastName || "",
      fullName: fullName || "",
      name: fullName || "",
      displayName: fullName || "",
      email: String(user?.email || email())
        .trim()
        .toLowerCase(),
      roleKey: storedRole,
      role: storedRole,
      active_role: normalizedRole,
      selectedProfessionalRole: selectedRoleForStorage,
      user,
    };
    if (typeof window !== "undefined") {
      window.sessionStorage.setItem("nxtgauge_auth_user", JSON.stringify(payload));
      window.sessionStorage.setItem("nxtgauge_user", JSON.stringify(payload));
      window.sessionStorage.setItem("nxtgauge_signup_profile_v1", JSON.stringify(payload));
    }
  };

  const login = async () => {
    if (submitting()) return;
    setError("");
    if (!isValidEmail(email())) {
      setError("Enter a valid email address.");
      return;
    }
    if (!password().trim()) {
      setError("Password is required.");
      return;
    }
    if (!captchaInput().trim()) {
      setError("Enter the captcha answer to continue.");
      return;
    }
    setSubmitting(true);
    try {
      const res = await fetch("/api/auth/login", {
        method: "POST",
        headers: { "Content-Type": "application/json", Accept: "application/json" },
        credentials: "include",
        body: JSON.stringify({
          email: email().trim().toLowerCase(),
          password: password(),
          captcha_id: captchaId(),
          captcha_answer: captchaInput().trim(),
        }),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) {
        const code = String(data?.code || "").toUpperCase();
        if (code === "EMAIL_NOT_VERIFIED") {
          setShowVerify(true);
          setError("Email not verified. Enter OTP sent to your inbox.");
          return;
        }
        if (code === "CAPTCHA_FAILED") {
          setError(String(data?.error || "Invalid or expired captcha. Please try again."));
          void loadCaptcha();
          return;
        }
        setError(String(data?.error || data?.message || "Invalid login credentials."));
        return;
      }

      const accessToken = String(data?.access_token || "").trim();
      const normalizedEmail = email().trim().toLowerCase();
      const userEmail = String(data?.user?.email || normalizedEmail).trim().toLowerCase();
      const availableRoleKeys = normalizeRoleKeysList(data?.user?.roles || data?.roles);
      const backendActiveRoleKey =
        extractRoleKey(
          data?.user?.active_role ||
            data?.active_role ||
            data?.role ||
            data?.role_code
        ) ||
        firstNonJobSeekerRole(availableRoleKeys) ||
        "";
      const preferredRoleKey = getStoredPreferredRole(userEmail);
      let discoveredRoleKeys = [...availableRoleKeys];
      let discoveredActiveRole = backendActiveRoleKey;

      if (discoveredRoleKeys.length === 0 || isJobSeekerRole(discoveredActiveRole)) {
        try {
          const checkRes = await fetch("/api/auth/check-email", {
            method: "POST",
            headers: { "Content-Type": "application/json", Accept: "application/json" },
            credentials: "include",
            body: JSON.stringify({ email: userEmail }),
          });
          const checkPayload = await checkRes.json().catch(() => ({}));
          if (checkRes.ok && checkPayload?.exists) {
            const checkRoles = normalizeRoleKeysList(checkPayload?.roles);
            if (checkRoles.length > 0) {
              discoveredRoleKeys = Array.from(new Set([...discoveredRoleKeys, ...checkRoles]));
            }
            const checkActive = extractRoleKey(checkPayload?.active_role || checkPayload?.role);
            if (checkActive) {
              discoveredActiveRole = checkActive;
            }
          }
        } catch {
          // Ignore check-email failures; continue with login payload roles.
        }
      }

      // Choose the role we *want* to activate:
      // 1) Prefer the stored role selection (from signup/switch services) when it isn't JOB_SEEKER.
      //    If backend doesn't return roles, still attempt to activate it via switch-role.
      // 2) Otherwise, if backend returns JOB_SEEKER but other roles exist, pick the first non-JOB_SEEKER role.
      let requestedRoleKey: string | null = null;
      if (
        preferredRoleKey &&
        !isJobSeekerRole(preferredRoleKey) &&
        (discoveredRoleKeys.length === 0 || discoveredRoleKeys.includes(preferredRoleKey))
      ) {
        requestedRoleKey = preferredRoleKey;
      } else if (isJobSeekerRole(discoveredActiveRole)) {
        requestedRoleKey = firstNonJobSeekerRole(discoveredRoleKeys);
      }

      let finalAccessToken = accessToken;
      let desiredRoleKey = discoveredActiveRole;
      if (finalAccessToken && requestedRoleKey && requestedRoleKey !== discoveredActiveRole) {
        try {
          const switchRes = await fetch("/api/auth/switch-role", {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
              Accept: "application/json",
              Authorization: `Bearer ${finalAccessToken}`,
            },
            credentials: "include",
            body: JSON.stringify({ role_key: requestedRoleKey }),
          });
          const switchPayload = await switchRes.json().catch(() => ({}));
          const switchedToken = String(switchPayload?.access_token || "").trim();
          if (switchRes.ok && switchedToken) {
            finalAccessToken = switchedToken;
            desiredRoleKey = requestedRoleKey;
          }
        } catch {
          // Ignore switch failures; fall back to backend active role token.
        }
      }

      if (typeof window !== "undefined" && finalAccessToken) {
        window.sessionStorage.setItem("nxtgauge_access_token", finalAccessToken);
        window.sessionStorage.setItem("nxtgauge_frontend_access_token", finalAccessToken);
      }

      const finalRole = normalizeRoleValue(
        desiredRoleKey ||
          backendActiveRoleKey ||
          preferredRoleKey ||
          firstNonJobSeekerRole(discoveredRoleKeys) ||
          ""
      );
      if (!finalRole) {
        setError("No active role is assigned to this account. Please contact support.");
        return;
      }
      const userPayload = {
        id: String(data?.user?.id || ""),
        email: userEmail,
        full_name: String(data?.user?.full_name || data?.user?.name || data?.name || ""),
        active_role: finalRole,
        email_verified: Boolean(data?.user?.email_verified ?? true),
      };
      saveUser({ ...userPayload });
      if (auth.refreshUser) {
        auth.refreshUser(userPayload);
      }
      navigate(`/dashboard?role=${encodeURIComponent(finalRole)}`, { replace: true });
    } catch {
      setError("Network error during login. Please try again.");
    } finally {
      setSubmitting(false);
    }
  };

  const resendOtp = async () => {
    if (submitting()) return;
    setError("");
    setSubmitting(true);
    try {
      const res = await fetch("/api/auth/resend-otp", {
        method: "POST",
        headers: { "Content-Type": "application/json", Accept: "application/json" },
        credentials: "include",
        body: JSON.stringify({ email: email().trim().toLowerCase() }),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) {
        setError(String(data?.error || data?.message || "Unable to resend OTP."));
      }
    } finally {
      setSubmitting(false);
    }
  };

  const verifyThenLogin = async () => {
    if (submitting()) return;
    setError("");
    if (otpCode().length !== 6) {
      setError("Enter a valid 6-digit OTP.");
      return;
    }
    setSubmitting(true);
    try {
      const verifyRes = await fetch("/api/auth/verify-email", {
        method: "POST",
        headers: { "Content-Type": "application/json", Accept: "application/json" },
        credentials: "include",
        body: JSON.stringify({ otp: otpCode() }),
      });
      const verifyData = await verifyRes.json().catch(() => ({}));
      if (!verifyRes.ok) {
        setError(String(verifyData?.error || verifyData?.message || "OTP verification failed."));
        return;
      }
      await login();
    } finally {
      setSubmitting(false);
    }
  };

  if (typeof window !== 'undefined') {
    (window as any).__loginVerifyOtp = verifyThenLogin;
    (window as any).__setLoginOtp = setOtp;
    (window as any).__loginOtp = otp;
  }

  return (
    <main class="auth-page">
      <PublicBackground />
      <PublicHeader />

      <div class="auth-layout">
        <section class="auth-visual card glass-dark">
          <img class="auth-visual-img" src="/images/auth-company-1.jpg" alt="Public Workspace" />
          <div class="auth-visual-overlay" />
          <div class="auth-visual-content">
            <p class="eyebrow">Public Workspace</p>
            <h1 class="title light">Welcome Back To Nxtgauge</h1>
            <p class="subtitle light">
              Sign in to manage your profile, portfolio, and verification in one place.
            </p>
          </div>
        </section>

        <section class="auth-form card glass-light">
          <h2 class="title">Sign In</h2>

          <div class="field">
            <label class="label" for="login-email">
              EMAIL
            </label>
            <input
              id="login-email"
              type="email"
              class="input"
              value={email()}
              onInput={(e) => {
                const value = e.currentTarget.value;
                setEmail(value);
                void lookupRoleByEmail(value);
              }}
              onBlur={(e) => {
                void lookupRoleByEmail(e.currentTarget.value);
              }}
              placeholder="Enter your email"
            />
            <p
              class="validation-note"
              style={{ color: email().trim() && isValidEmail(email()) ? "#fd6116" : "#6e7591" }}
            >
              {email().trim() && isValidEmail(email())
                ? "✓ Valid email format"
                : "• Enter a valid email format"}
            </p>
            <Show when={roleHint() || checkingRole()}>
              <p class="validation-note" style={{ color: "#0f766e" }}>
                {checkingRole() ? "Checking account role..." : `• ${roleHint()}`}
              </p>
            </Show>
          </div>

          <div class="field">
            <label class="label" for="login-password">
              PASSWORD
            </label>
            <div class="auth-password-wrap">
              <input
                id="login-password"
                type={showPassword() ? "text" : "password"}
                class="input"
                value={password()}
                onInput={(e) => setPassword(e.currentTarget.value)}
                placeholder="Enter your password"
              />
              <button
                class="auth-toggle-visibility"
                type="button"
                onClick={() => setShowPassword((prev) => !prev)}
                aria-label={showPassword() ? "Hide password" : "Show password"}
              >
                <PasswordVisibilityIcon visible={showPassword()} />
              </button>
            </div>
          </div>

          <div class="field">
            <label class="label">CAPTCHA</label>
            <div class="auth-captcha-row">
              <button
                class="auth-captcha-refresh"
                type="button"
                aria-label="Refresh captcha"
                onClick={() => void loadCaptcha()}
              >
                ↻
              </button>
              <CaptchaCanvas challenge={captchaChallenge()} class="auth-captcha-canvas" />
              <input
                class="input"
                value={captchaInput()}
                onInput={(e) => setCaptchaInput(e.currentTarget.value)}
                placeholder="Enter answer"
              />
            </div>
          </div>

          <Show when={showVerify()}>
            <label class="label">EMAIL OTP</label>
            <div class="otp-row">
              <For each={Array.from({ length: 6 }, (_, index) => index)}>
                {(index) => (
                  <input
                    id={`login-otp-${index}`}
                    class="otp-input"
                    inputMode="numeric"
                    maxlength={1}
                    value={otp()[index]}
                    onInput={(e) => setOtpDigit(index, e.currentTarget.value)}
                  />
                )}
              </For>
            </div>
            <div class="auth-footer-row">
              <p class="note">Didn’t receive code?</p>
              <button
                class="auth-forgot-link"
                type="button"
                onClick={() => void resendOtp()}
                disabled={submitting()}
              >
                Resend OTP
              </button>
            </div>
          </Show>

          <button
            class="auth-submit-btn"
            type="button"
            onClick={() => void login()}
            disabled={submitting()}
          >
            {submitting() ? "Signing In..." : "Sign In"}
          </button>

          <Show when={showVerify()}>
            <button
              class="auth-submit-btn"
              type="button"
              onClick={() => void verifyThenLogin()}
              disabled={submitting()}
            >
              {submitting() ? "Verifying..." : "Verify Email and Login"}
            </button>
          </Show>

          <div class="auth-footer-row">
            <p class="footer-text">Secure login with email verification.</p>
            <p class="note">
              New user? <A href="/signup">Sign Up</A>
            </p>
            <p class="note">
              <A href="/forgot-password">Forgot Password?</A>
            </p>
          </div>

          <Show when={error()}>
            <p class="error">{error()}</p>
          </Show>
        </section>
      </div>
    </main>
  );
}
