"""Authentication routes."""
from flask import Blueprint, request, session
from flask_restx import Api, Resource, fields
from models.user import User
from services.auth_service import authenticate_user, register_user
from typing import Dict, Any

auth_bp = Blueprint('auth', __name__, url_prefix='/api')
auth_api = Api(auth_bp, doc=False, prefix='/auth')

# Request/Response models for Swagger
login_model = auth_api.model('Login', {
    'username': fields.String(required=True, description='Username'),
    'password': fields.String(required=True, description='Password')
})

user_response_model = auth_api.model('UserResponse', {
    'id': fields.Integer(description='User ID'),
    'username': fields.String(description='Username'),
    'email': fields.String(description='Email'),
    'role': fields.String(description='Fellowship member role'),
    'gold': fields.Integer(description='Current gold balance'),
})

login_response_model = auth_api.model('LoginResponse', {
    'message': fields.String(description='Success message'),
    'user': fields.Nested(user_response_model, description='User information')
})

signup_model = auth_api.model('Signup', {
    'username': fields.String(required=True, description='Desired username (minimum 3 characters)'),
    'password': fields.String(required=True, description='Desired password (minimum 8 characters and at least one number)'),
    'email': fields.String(required=False, description='Optional email address')
})


@auth_api.route('/signup')
class Signup(Resource):
    """Public signup endpoint for open SUT registration."""

    @auth_api.expect(signup_model, validate=False)
    @auth_api.response(201, 'Signup successful', login_response_model)
    @auth_api.response(400, 'Validation error')
    @auth_api.doc(description='Register user and create session')
    def post(self) -> tuple[Dict[str, Any], int]:
        """Register a user and immediately log them in."""
        data = request.get_json() or {}

        username = data.get('username')
        password = data.get('password')
        email = data.get('email')

        try:
            user = register_user(username=username, password=password, email=email)
        except ValueError as error:
            return {'error': str(error)}, 400

        session['user_id'] = user.id
        session['username'] = user.username

        return {
            'message': 'Signup successful',
            'user': user.to_dict(),
        }, 201

@auth_api.route('/login')
class Login(Resource):
    """User login endpoint."""
    
    @auth_api.expect(login_model)
    @auth_api.marshal_with(login_response_model)
    @auth_api.doc(description='Authenticate user and create session')
    def post(self) -> tuple[Dict[str, Any], int]:
        """Login user."""
        data = request.get_json()
        username = data.get('username')
        password = data.get('password')
        
        if not username or not password:
            return {'error': 'Username and password are required'}, 400
        
        user = authenticate_user(username, password)
        if not user:
            return {'error': 'Invalid credentials'}, 401
        
        # Create session
        session['user_id'] = user.id
        session['username'] = user.username
        
        return {
            'message': 'Login successful',
            'user': user.to_dict()
        }, 200

@auth_api.route('/logout')
class Logout(Resource):
    """User logout endpoint."""
    
    @auth_api.doc(description='Logout user and destroy session')
    def post(self) -> tuple[Dict[str, Any], int]:
        """Logout user."""
        session.clear()
        return {'message': 'Logout successful'}, 200

@auth_api.route('/me')
class CurrentUser(Resource):
    """Get current authenticated user."""
    
    @auth_api.marshal_with(user_response_model)
    @auth_api.doc(description='Get current authenticated user information')
    def get(self) -> tuple[Dict[str, Any], int]:
        """Get current user."""
        user_id = session.get('user_id')
        if not user_id:
            return {'error': 'Not authenticated'}, 401
        
        user = User.query.get(user_id)
        if not user:
            return {'error': 'User not found'}, 404
        
        return user.to_dict(), 200
