# retoor <retoor@molodetz.nl>

import logging
from typing import Annotated
from fastapi import Depends, APIRouter, Request
from fastapi.responses import HTMLResponse
from devplacepy.database import get_table, get_int_setting, is_account_active
from devplacepy.templating import templates
from devplacepy.utils import (
    verify_password_async,
    create_session,
    get_current_user,
    safe_next,
    cookie_secure,
)
from devplacepy.seo import base_seo_context
from devplacepy.models import LoginForm
from devplacepy.config import SECONDS_PER_DAY
from devplacepy.responses import respond, action_result, wants_json, json_error
from devplacepy.schemas import AuthPageOut
from devplacepy.services.audit import record as audit
from devplacepy.dependencies import json_or_form

logger = logging.getLogger(__name__)
router = APIRouter()

@router.get("/login", response_class=HTMLResponse)
async def login_page(request: Request, next: str | None = None):
    user = get_current_user(request)
    if user:
        return action_result(request, safe_next(next))
    seo_ctx = base_seo_context(
        request,
        title="Sign In",
        description="Sign in to DevPlace to connect with developers.",
        robots="noindex,nofollow",
    )
    return respond(
        request,
        "login.html",
        {
            **seo_ctx,
            "request": request,
            "page": "login",
            "next_url": safe_next(next, ""),
        },
        model=AuthPageOut,
    )

@router.post("/login")
async def login(request: Request, data: Annotated[LoginForm, Depends(json_or_form(LoginForm))]):
    email = data.email.strip().lower()
    password = data.password
    remember_me = data.remember_me == "on"

    errors = []
    users = get_table("users")
    user = users.find_one(email=email)

    if not user or not await verify_password_async(password, user["password_hash"]):
        errors.append("Invalid email or password")
    elif not is_account_active(user):
        errors.append("Account is deactivated")

    if errors:
        audit.record(
            request,
            "auth.login.failure",
            user=None,
            actor_kind="guest",
            result="failure",
            metadata={"email": email},
            summary=f"failed login attempt for {email}",
        )
        if wants_json(request):
            return json_error(401, "; ".join(errors), errors=errors)
        seo_ctx = base_seo_context(request, title="Sign In", robots="noindex,nofollow")
        return templates.TemplateResponse(
            request,
            "login.html",
            {
                **seo_ctx,
                "request": request,
                "errors": errors,
                "email": email,
                "next_url": safe_next(data.next, ""),
            },
        )

    days = (
        get_int_setting("session_remember_days", 30)
        if remember_me
        else get_int_setting("session_max_age_days", 7)
    )
    max_age = max(1, days) * SECONDS_PER_DAY
    token = create_session(user["uid"], max_age)
    response = action_result(
        request, safe_next(data.next), data={"username": user["username"]}
    )
    response.set_cookie(
        key="session",
        value=token,
        max_age=max_age,
        httponly=True,
        samesite="lax",
        secure=cookie_secure(request),
    )
    logger.info(f"User {user['username']} logged in")
    audit.record(
        request,
        "auth.login.success",
        user=user,
        target_type="user",
        target_uid=user["uid"],
        target_label=user["username"],
        metadata={"remember_me": remember_me, "max_age_seconds": max_age},
        summary=f"user {user['username']} logged in",
        links=[audit.target("user", user["uid"], user["username"])],
    )
    return response
