"use client";

/**
 * #2555 (эпик #2549) — login-форма для новой DB-backed session auth
 * (POST /api/v1/auth/login, см. `tradein-mvp/backend/app/api/v1/auth.py`).
 *
 * Не гейтится RouteGuard'ом (см. `components/auth/RouteGuard.tsx` —
 * `isLoginPage` bypass) — иначе редирект-петля: 401 от /me на /login тоже
 * пытался бы увести на /login.
 *
 * `next=` читаем вручную из `window.location.search` (SSR-guard), а НЕ
 * через `next/navigation` `useSearchParams()` — тот форсит Suspense boundary
 * и ломает `next build` (см. `app/v2/page.tsx: readUrlId` — тот же паттерн,
 * уже принятый в этом репо).
 */

import { useState } from "react";
import type { CSSProperties, FormEvent } from "react";
import { useRouter } from "next/navigation";
import { useMutation, useQueryClient } from "@tanstack/react-query";

import { apiFetch, HTTPError } from "@/lib/api";
import { ME_QUERY_KEY } from "@/lib/useMe";

interface LoginInput {
  username: string;
  password: string;
}

async function loginRequest(input: LoginInput): Promise<void> {
  await apiFetch<{ ok: boolean }>("/api/v1/auth/login", {
    method: "POST",
    body: JSON.stringify(input),
  });
}

function readNextParam(): string | null {
  if (typeof window === "undefined") return null;
  return new URLSearchParams(window.location.search).get("next");
}

/**
 * Open-redirect guard: принимаем только внутренний путь, начинающийся
 * ровно с одного "/" — не "//host" (protocol-relative URL) и не "/\host"
 * (браузеры местами трактуют backslash как forward slash в URL-парсинге).
 *
 * PR #2562 review finding 1: WHATWG URL-парсер (который `router.push`
 * использует под капотом) убирает ВСЕ ASCII tab/CR/LF из строки ПЕРЕД
 * парсингом — так `"/\t//evil"` для наивного regex выглядит как безопасный
 * путь с одним leading slash (символ в позиции 1 — таб, не "/" и не "\"),
 * а после навигации превращается в `"//evil"` (protocol-relative → чужой
 * origin). Убираем те же символы ДО валидации, чтобы regex видел ту же
 * строку, что увидит парсер.
 *
 * PR #2562 review finding 2: `next=/login` (или `/login?...`) после успешного
 * логина кидал бы юзера обратно на форму входа (RouteGuard не гейтит
 * `/login`) — dead-end. Фолбэк на "/" в этом случае.
 */
function sanitizeNext(next: string | null): string {
  if (!next) return "/";
  const cleaned = next.replace(/[\t\r\n]/g, "");
  if (!/^\/(?!\/|\\)/.test(cleaned)) return "/";
  if (
    cleaned === "/login" ||
    cleaned.startsWith("/login?") ||
    cleaned.startsWith("/login#")
  ) {
    return "/";
  }
  return cleaned;
}

function loginErrorMessage(error: unknown): string {
  if (error instanceof HTTPError) {
    if (error.status === 401) return "Неверный логин или пароль";
    if (error.status === 429) {
      return "Слишком много попыток. Попробуйте через несколько минут";
    }
  }
  return "Не удалось войти. Проверьте подключение и попробуйте ещё раз";
}

const cardStyle: CSSProperties = {
  background: "var(--bg-card)",
  border: "1px solid var(--border-card)",
  borderRadius: 12,
  padding: "32px 28px",
  maxWidth: 380,
  width: "100%",
};

const labelStyle: CSSProperties = {
  display: "block",
  fontSize: 12,
  fontWeight: 500,
  color: "var(--fg-secondary)",
  marginBottom: 6,
};

const inputStyle: CSSProperties = {
  width: "100%",
  boxSizing: "border-box",
  height: 40,
  padding: "0 12px",
  border: "1px solid var(--border-card)",
  borderRadius: 8,
  fontSize: 14,
  color: "var(--fg-primary)",
  background: "var(--bg-card)",
  fontFamily: "inherit",
};

export default function LoginPage() {
  const router = useRouter();
  const queryClient = useQueryClient();
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");

  const loginMutation = useMutation({
    mutationFn: loginRequest,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ME_QUERY_KEY });
      router.push(sanitizeNext(readNextParam()));
    },
  });

  function handleSubmit(e: FormEvent<HTMLFormElement>) {
    e.preventDefault();
    if (loginMutation.isPending) return;
    loginMutation.mutate({ username: username.trim(), password });
  }

  return (
    <main
      style={{
        minHeight: "100vh",
        background: "var(--bg-app)",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        padding: 24,
        fontFamily: "Inter, -apple-system, 'Segoe UI', system-ui, sans-serif",
      }}
    >
      <style>{`
        @keyframes login-spin { to { transform: rotate(360deg); } }
        .login-spinner { animation: login-spin .7s linear infinite; }
        .login-input:focus-visible {
          outline: none;
          border-color: var(--accent);
          box-shadow: 0 0 0 2px var(--accent-soft);
        }
        .login-submit:hover:not(:disabled) { background: var(--accent-hover); }
      `}</style>

      <form onSubmit={handleSubmit} style={cardStyle} aria-label="Вход в Меру">
        <h1
          style={{
            margin: "0 0 8px",
            fontSize: 22,
            fontWeight: 600,
            color: "var(--fg-primary)",
            lineHeight: 1.25,
          }}
        >
          Вход
        </h1>
        <p
          style={{
            margin: "0 0 24px",
            fontSize: 14,
            color: "var(--fg-secondary)",
            lineHeight: 1.5,
          }}
        >
          Войдите, чтобы продолжить работу с Мерой.
        </p>

        <div style={{ marginBottom: 16 }}>
          <label style={labelStyle} htmlFor="login-username">
            Логин
          </label>
          <input
            id="login-username"
            name="username"
            type="text"
            autoComplete="username"
            required
            autoFocus
            className="login-input"
            style={inputStyle}
            value={username}
            onChange={(e) => setUsername(e.target.value)}
            disabled={loginMutation.isPending}
          />
        </div>

        <div style={{ marginBottom: 24 }}>
          <label style={labelStyle} htmlFor="login-password">
            Пароль
          </label>
          <input
            id="login-password"
            name="password"
            type="password"
            autoComplete="current-password"
            required
            className="login-input"
            style={inputStyle}
            value={password}
            onChange={(e) => setPassword(e.target.value)}
            disabled={loginMutation.isPending}
          />
        </div>

        {loginMutation.isError ? (
          <p
            role="alert"
            style={{
              margin: "0 0 16px",
              padding: "8px 12px",
              borderRadius: 8,
              background: "var(--danger-soft)",
              color: "var(--danger)",
              fontSize: 13,
              lineHeight: 1.4,
            }}
          >
            {loginErrorMessage(loginMutation.error)}
          </p>
        ) : null}

        <button
          type="submit"
          className="login-submit"
          disabled={loginMutation.isPending}
          style={{
            width: "100%",
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            gap: 8,
            background: "var(--accent)",
            color: "#FFFFFF",
            border: "none",
            borderRadius: 8,
            padding: "10px 16px",
            fontSize: 14,
            fontWeight: 500,
            cursor: loginMutation.isPending ? "wait" : "pointer",
            opacity: loginMutation.isPending ? 0.75 : 1,
            fontFamily: "inherit",
          }}
        >
          {loginMutation.isPending ? (
            <>
              <svg
                className="login-spinner"
                width={16}
                height={16}
                viewBox="0 0 24 24"
                fill="none"
                aria-hidden="true"
              >
                <circle
                  cx="12"
                  cy="12"
                  r="9"
                  stroke="rgba(255,255,255,0.35)"
                  strokeWidth="3"
                />
                <path
                  d="M21 12a9 9 0 0 0-9-9"
                  stroke="#FFFFFF"
                  strokeWidth="3"
                  strokeLinecap="round"
                />
              </svg>
              Входим…
            </>
          ) : (
            "Войти"
          )}
        </button>
      </form>
    </main>
  );
}
