# app/api/v1/vendor/auth.py
"""
Vendor team authentication endpoints.

Implements dual token storage with path restriction:
- Sets HTTP-only cookie with path=/vendor (restricted to vendor routes only)
- Returns token in response for localStorage (API calls)

This prevents:
- Vendor cookies from being sent to admin routes
- Admin cookies from being sent to vendor routes
- Cross-context authentication confusion
"""

import logging

from fastapi import APIRouter, Depends, Request, Response
from pydantic import BaseModel
from sqlalchemy.orm import Session

from app.api.deps import get_current_vendor_api
from app.core.database import get_db
from app.core.environment import should_use_secure_cookies
from app.exceptions import InvalidCredentialsException
from app.services.auth_service import auth_service
from middleware.vendor_context import get_current_vendor
from models.database.user import User
from models.schema.auth import LogoutResponse, UserLogin, VendorUserResponse

router = APIRouter(prefix="/auth")
logger = logging.getLogger(__name__)


# Response model for vendor login
class VendorLoginResponse(BaseModel):
    access_token: str
    token_type: str
    expires_in: int
    user: dict
    vendor: dict
    vendor_role: str


@router.post("/login", response_model=VendorLoginResponse)
def vendor_login(
    user_credentials: UserLogin,
    request: Request,
    response: Response,
    db: Session = Depends(get_db),
):
    """
    Vendor team member login.

    Authenticates users who are part of a vendor team.
    Validates against vendor context if available.

    Sets token in two places:
    1. HTTP-only cookie with path=/vendor (for browser page navigation)
    2. Response body (for localStorage and API calls)

    Prevents admin users from logging into vendor portal.
    """
    # Try to get vendor from middleware first
    vendor = get_current_vendor(request)

    # If no vendor from middleware, try to get from request body
    if not vendor and hasattr(user_credentials, "vendor_code"):
        vendor_code = getattr(user_credentials, "vendor_code", None)
        if vendor_code:
            vendor = auth_service.get_vendor_by_code(db, vendor_code)

    # Authenticate user
    login_result = auth_service.login_user(db=db, user_credentials=user_credentials)
    user = login_result["user"]

    # CRITICAL: Prevent admin users from using vendor login
    if user.role == "admin":
        logger.warning(f"Admin user attempted vendor login: {user.username}")
        raise InvalidCredentialsException(
            "Admins cannot access vendor portal. Please use admin portal."
        )

    # Determine vendor and role
    vendor_role = "Member"

    if vendor:
        # Check if user has access to this vendor
        has_access, role = auth_service.get_user_vendor_role(db, user, vendor)

        if has_access:
            vendor_role = role
        else:
            logger.warning(
                f"User {user.username} attempted login to vendor {vendor.vendor_code} "
                f"but is not authorized"
            )
            raise InvalidCredentialsException("You do not have access to this vendor")
    else:
        # No vendor context - find which vendor this user belongs to
        vendor, vendor_role = auth_service.find_user_vendor(user)

        if not vendor:
            raise InvalidCredentialsException("User is not associated with any vendor")

    logger.info(
        f"Vendor team login successful: {user.username} "
        f"for vendor {vendor.vendor_code} as {vendor_role}"
    )

    # Create vendor-scoped access token with vendor information
    token_data = auth_service.auth_manager.create_access_token(
        user=user,
        vendor_id=vendor.id,
        vendor_code=vendor.vendor_code,
        vendor_role=vendor_role,
    )

    # Set HTTP-only cookie for browser navigation
    # CRITICAL: path=/vendor restricts cookie to vendor routes only
    response.set_cookie(
        key="vendor_token",
        value=token_data["access_token"],
        httponly=True,  # JavaScript cannot access (XSS protection)
        secure=should_use_secure_cookies(),  # HTTPS only in production/staging
        samesite="lax",  # CSRF protection
        max_age=token_data["expires_in"],  # Match JWT expiry
        path="/vendor",  # RESTRICTED TO VENDOR ROUTES ONLY
    )

    logger.debug(
        f"Set vendor_token cookie with {token_data['expires_in']}s expiry "
        f"(path=/vendor, httponly=True, secure={should_use_secure_cookies()})"
    )

    # Return full login response with vendor-scoped token
    return VendorLoginResponse(
        access_token=token_data["access_token"],
        token_type=token_data["token_type"],
        expires_in=token_data["expires_in"],
        user={
            "id": user.id,
            "username": user.username,
            "email": user.email,
            "role": user.role,
            "is_active": user.is_active,
        },
        vendor={
            "id": vendor.id,
            "vendor_code": vendor.vendor_code,
            "subdomain": vendor.subdomain,
            "name": vendor.name,
            "is_active": vendor.is_active,
            "is_verified": vendor.is_verified,
        },
        vendor_role=vendor_role,
    )


@router.post("/logout", response_model=LogoutResponse)
def vendor_logout(response: Response):
    """
    Vendor team member logout.

    Clears the vendor_token cookie.
    Client should also remove token from localStorage.
    """
    logger.info("Vendor logout")

    # Clear the cookie (must match path used when setting)
    response.delete_cookie(
        key="vendor_token",
        path="/vendor",
    )

    logger.debug("Deleted vendor_token cookie")

    return LogoutResponse(message="Logged out successfully")


@router.get("/me", response_model=VendorUserResponse)
def get_current_vendor_user(
    user: User = Depends(get_current_vendor_api), db: Session = Depends(get_db)
):
    """
    Get current authenticated vendor user.

    This endpoint can be called to verify authentication and get user info.
    Requires Authorization header (header-only authentication for API endpoints).
    """
    return VendorUserResponse(
        id=user.id,
        username=user.username,
        email=user.email,
        role=user.role,
        is_active=user.is_active,
    )
