"""Teste US-002 (PRD 3.3): SessionMiddleware + helper-e sesiune in app/web/session.py."""

from __future__ import annotations

import os
import tempfile

import pytest
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from starlette.middleware.sessions import SessionMiddleware
from starlette.testclient import TestClient


# ---- App minimal pentru teste (fara init_db, fara DB) ----

def _make_app(web_auth_required: bool = True, session_secret: str = "test-secret-dev") -> FastAPI:
    """Construieste un app FastAPI minimal cu SessionMiddleware + rute de test."""
    mini = FastAPI()
    mini.add_middleware(
        SessionMiddleware,
        secret_key=session_secret,
        session_cookie="autopass_session",
        https_only=False,
        same_site="strict",
    )

    @mini.get("/set-session")
    def set_sess(request: Request, account_id: int = 1, user_id: int = 1):
        from app.web.session import set_session
        set_session(request, account_id, user_id)
        return {"ok": True}

    @mini.get("/get-session")
    def get_sess(request: Request):
        from app.web.session import current_account, current_user_id
        return {
            "account_id": current_account(request),
            "user_id": current_user_id(request),
        }

    @mini.get("/protected")
    def protected(request: Request):
        from app.web.session import require_login
        aid = require_login(request)
        return {"account_id": aid}

    @mini.get("/logout")
    def logout_ep(request: Request):
        from app.web.session import clear_session
        clear_session(request)
        return {"ok": True}

    @mini.get("/web-account")
    def web_account_ep(request: Request):
        from app.web.session import web_account
        return {"account_id": web_account(request)}

    # Handler pentru LoginRequired
    from app.web.session import LoginRequired
    from starlette.responses import RedirectResponse

    @mini.exception_handler(LoginRequired)
    async def login_required_handler(request: Request, exc: LoginRequired):
        return RedirectResponse("/login", status_code=303)

    return mini


@pytest.fixture()
def client_auth(monkeypatch):
    """Client cu web_auth_required=True."""
    monkeypatch.setenv("AUTOPASS_WEB_AUTH_REQUIRED", "true")
    from app.config import get_settings
    get_settings.cache_clear()
    app = _make_app(web_auth_required=True)
    with TestClient(app, follow_redirects=False) as c:
        yield c
    get_settings.cache_clear()


@pytest.fixture()
def client_dev(monkeypatch):
    """Client cu web_auth_required=False (dev bypass)."""
    monkeypatch.setenv("AUTOPASS_WEB_AUTH_REQUIRED", "false")
    from app.config import get_settings
    get_settings.cache_clear()
    app = _make_app(web_auth_required=False)
    with TestClient(app, follow_redirects=False) as c:
        yield c
    get_settings.cache_clear()


def test_ruta_protejata_redirect_login(client_auth):
    """Fara sesiune si web_auth_required=True -> 303 redirect catre /login."""
    resp = client_auth.get("/protected")
    assert resp.status_code == 303
    assert resp.headers["location"] == "/login"


def test_sesiune_seteaza_si_citeste_cont(client_auth):
    """set_session stocheaza account_id si user_id; current_account/current_user_id le citesc."""
    client_auth.get("/set-session?account_id=5&user_id=7")
    resp = client_auth.get("/get-session")
    assert resp.status_code == 200
    data = resp.json()
    assert data["account_id"] == 5
    assert data["user_id"] == 7


def test_logout_curata_sesiunea(client_auth):
    """clear_session sterge account_id si user_id din sesiune."""
    client_auth.get("/set-session?account_id=3&user_id=4")
    # Verifica ca sesiunea e setata
    data_before = client_auth.get("/get-session").json()
    assert data_before["account_id"] == 3
    # Logout
    client_auth.get("/logout")
    data_after = client_auth.get("/get-session").json()
    assert data_after["account_id"] is None
    assert data_after["user_id"] is None


def test_dev_bypass_cont_1(client_dev, monkeypatch):
    """web_auth_required=False -> web_account() returneaza 1 (DEFAULT_ACCOUNT_ID) fara sesiune."""
    resp = client_dev.get("/web-account")
    assert resp.status_code == 200
    assert resp.json()["account_id"] == 1


def test_set_session_curata_sesiunea_anterioara(client_auth):
    """set_session face clear() inainte de a seta (C3 anti-fixare sesiune)."""
    # Seteaza sesiune initiala cu cont 10
    client_auth.get("/set-session?account_id=10&user_id=10")
    data_initial = client_auth.get("/get-session").json()
    assert data_initial["account_id"] == 10
    # Re-login cu cont nou 20 — sesiunea veche trebuie stearsa inainte
    client_auth.get("/set-session?account_id=20&user_id=20")
    data_nou = client_auth.get("/get-session").json()
    assert data_nou["account_id"] == 20
    assert data_nou["user_id"] == 20


def test_ruta_protejata_cu_sesiune_trece(client_auth):
    """Cu sesiune setata si web_auth_required=True -> ruta protejata raspunde 200."""
    client_auth.get("/set-session?account_id=5&user_id=5")
    resp = client_auth.get("/protected")
    assert resp.status_code == 200
    assert resp.json()["account_id"] == 5


def test_web_auth_required_default_true(monkeypatch):
    """Default-ul de productie: auth web e ON daca AUTOPASS_WEB_AUTH_REQUIRED nu e setat.

    Dev rapid pe cont 1 = opt-out explicit (AUTOPASS_WEB_AUTH_REQUIRED=false).
    """
    monkeypatch.delenv("AUTOPASS_WEB_AUTH_REQUIRED", raising=False)
    from app.config import Settings, get_settings
    get_settings.cache_clear()
    assert Settings().web_auth_required is True
    get_settings.cache_clear()
