import os
import io
import base64
import uuid
from typing import List, Optional
from PIL import Image
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form
from fastapi.responses import FileResponse
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from jose import JWTError, jwt
from app.models.account_models import (
    EmailRequest, UserUpdateRequest, PasswordChangeRequest, 
    ForgotPasswordRequest, UserResponse, MessageResponse, 
    ExistResponse, StatsResponse
)
from app.models import Profile
from app.services.user import UserService
from app.utils import admin_required
from app.config.extensions import bcrypt
from app.services.mail import MailService
from app.config.settings import Config

router = APIRouter()
security = HTTPBearer()
config = Config()

UPLOAD_FOLDER = 'uploads'

# Ensure upload folder exists
os.makedirs(UPLOAD_FOLDER, exist_ok=True)


def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(security)):
    """Dependency to get current user from JWT token"""
    try:
        token = credentials.credentials
        payload = jwt.decode(
            token, 
            config.JWT_SECRET_KEY, 
            algorithms=[config.JWT_ALGORITHM]
        )
        email: str = payload.get("sub")
        if email is None:
            raise HTTPException(status_code=401, detail="Invalid token")
        return email
    except JWTError:
        raise HTTPException(status_code=401, detail="Invalid token")


@router.get("/me", response_model=UserResponse)
async def get_account_me(current_user_email: str = Depends(get_current_user)):
    """Get current user information based on JWT token"""
    user_info = UserService.get_user_by_email(current_user_email)
    if not user_info:
        raise HTTPException(status_code=404, detail="User not found")
    
    user_info.ensure_client_role()
    user_info.save()
    
    if not user_info.profile or user_info.profile is None:
        user_info.profile = Profile()
        user_info.save()
    
    return user_info.to_dict()


@router.patch("/me", response_model=UserResponse)
async def update_account_me(
    user_update: UserUpdateRequest,
    current_user_email: str = Depends(get_current_user)
):
    """Update current user information"""
    user_info = UserService.get_user_by_email(current_user_email)
    if not user_info:
        raise HTTPException(status_code=404, detail="User not found")
    
    # Update basic user fields
    update_data = user_update.dict(exclude_unset=True)
    
    for field in ['first_name', 'last_name', 'username']:
        if field in update_data:
            setattr(user_info, field, update_data.pop(field))
    
    # Handle avatar upload
    if 'avatar' in update_data:
        avatar_file = update_data.pop('avatar')
        if 'name' in avatar_file:
            file_path = os.path.join(UPLOAD_FOLDER, avatar_file["name"])
        else:
            file_path = os.path.join(UPLOAD_FOLDER, f"{uuid.uuid4()}.png")
        
        if 'base64file' in avatar_file:
            image = Image.open(io.BytesIO(base64.b64decode(avatar_file["base64file"].split(',')[1])))
            image.save(file_path)
            update_data["avatar"] = f"http://173.249.58.66:8082/account/avatar/{avatar_file['name']}"
    
    # Update profile fields
    for key, value in update_data.items():
        if hasattr(user_info.profile, key):
            setattr(user_info.profile, key, value)
    
    user_info.save()
    return user_info.to_dict()


@router.post("/exist", response_model=ExistResponse)
async def check_account_exists(email_request: EmailRequest):
    """Check if user exists based on email"""
    user_info = UserService.get_user_by_email(email_request.email)
    return {"exists": user_info is not None}


@router.delete("/deactivate", response_model=MessageResponse)
async def deactivate_account(current_user_email: str = Depends(get_current_user)):
    """Deactivate current user account"""
    try:
        user_info = UserService.get_user_by_email(current_user_email)
        if not user_info:
            raise HTTPException(status_code=404, detail="User not found")
        
        # Deactivate the user's account
        if user_info.is_active:
            user_info.toggle_active_status()
        
        # Archive the user's account
        if not user_info.deleted:
            user_info.archive()
        
        return {
            "message": "Your account has been deactivated. Please contact our administrator within 72 hours to discuss account reactivation. Failure to do so may result in permanent account deletion.",
            "status": 200
        }
    except Exception as e:
        if hasattr(e, 'code') and e.code is not None:
            raise HTTPException(status_code=e.code, detail=str(e))
        raise HTTPException(status_code=500, detail=f"An error occurred while processing your request: {str(e)}")


@router.get("/stats", response_model=StatsResponse)
async def get_account_stats():
    """Get account statistics"""
    stats = [
        {
            'stats': '21,459',
            'title': 'Session',
            'trendDiff': '+29',
            'icon': 'tabler:user',
            'subtitle': 'Total Users'
        },
        {
            'stats': '4,567',
            'trendDiff': '+18',
            'title': 'Paid Users',
            'avatarColor': 'error',
            'icon': 'tabler:user-plus',
            'subtitle': 'Last week analytics'
        },
        {
            'stats': '19,860',
            'trendDiff': '-14',
            'trend': 'negative',
            'title': 'Active Users',
            'avatarColor': 'success',
            'icon': 'tabler:user-check',
            'subtitle': 'Last week analytics'
        },
        {
            'stats': '237',
            'trendDiff': '+42',
            'title': 'Pending Users',
            'avatarColor': 'warning',
            'icon': 'tabler:user-exclamation',
            'subtitle': 'Last week analytics'
        }
    ]
    return {"statsHorizontalWithDetails": stats}


@router.get("/avatar/{file_name}")
async def get_avatar(file_name: str):
    """Serve avatar image files"""
    image_directory = "/app/uploads"
    file_path = os.path.join(image_directory, file_name)
    
    if not os.path.exists(file_path):
        raise HTTPException(status_code=404, detail="Image not found")
    
    return FileResponse(file_path, media_type="image/png")


@router.post("/{username}/upload_image", response_model=MessageResponse)
async def upload_user_image(
    username: str,
    image: UploadFile = File(...)
):
    """Upload image for a specific user"""
    user = UserService.get_user_by_email_or_username(username)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    
    file_path = f"{UPLOAD_FOLDER}/{user['username']}_{image.filename}"
    
    with open(file_path, "wb") as buffer:
        content = await image.read()
        buffer.write(content)
    
    # Update user profile with avatar
    if user['profile']:
        user['profile'].avatar = file_path
        user['profile'].save()
    else:
        user['profile'] = Profile(avatar=file_path)
        user.save()
    
    return {"message": "Image uploaded successfully"}


@router.get("/users", response_model=List[UserResponse])
async def get_all_users(current_user_email: str = Depends(get_current_user)):
    """Get all users (admin only)"""
    # Note: admin_required decorator needs to be implemented as a dependency
    users = UserService.all()
    return [user for user in users]


@router.get("/users/{public_id}", response_model=UserResponse)
async def get_user_info(
    public_id: str,
    current_user_email: str = Depends(get_current_user)
):
    """Get specific user information (admin only)"""
    user = UserService.get_user_by_id(public_id)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    return user


@router.delete("/users/{public_id}", response_model=MessageResponse)
async def delete_user(
    public_id: str,
    current_user_email: str = Depends(get_current_user)
):
    """Delete a specific user (admin only)"""
    user = UserService.get_user_by_id(public_id)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    
    user.delete()
    return {"message": "User deleted successfully"}


@router.post("/change-password/{token}", response_model=MessageResponse)
async def change_password(
    token: str,
    password_request: PasswordChangeRequest,
    current_user_email: str = Depends(get_current_user)
):
    """Change user password with token"""
    current_user = UserService.get_user_by_email(password_request.email)
    if not current_user:
        raise HTTPException(status_code=401, detail="Invalid email")
    
    # Update the password
    UserService.change_password(
        user_id=current_user['public_id'],
        new_password=password_request.password
    )
    return {"message": "Password updated successfully"}


@router.post("/forgot-password", response_model=MessageResponse)
async def forgot_password(forgot_request: ForgotPasswordRequest):
    """Send password reset email"""
    current_user = UserService.get_user_by_email(forgot_request.email)
    if not current_user:
        raise HTTPException(status_code=401, detail="Invalid email")
    
    # Generate reset token
    from jose import jwt
    from datetime import datetime, timedelta
    
    additional_claims = {
        "is_superuser": current_user.is_superuser,
        "is_active": current_user.is_active,
        "is_staff": current_user.is_staff,
        "is_admin": current_user.is_admin,
    }
    
    token_data = {
        "sub": current_user.email,
        "exp": datetime.utcnow() + timedelta(hours=24),
        **additional_claims
    }
    
    token = jwt.encode(token_data, config.JWT_SECRET_KEY, algorithm=config.JWT_ALGORITHM)
    reset_link = f'http://0.0.0.0:8002/api/account/change_password/{token}'
    
    # Send email (implement template rendering)
    MailService.send_email(
        subject="Password Reset Request",
        recipient=current_user.email,
        message=f"Click here to reset your password: {reset_link}",
        html=True
    )
    
    return {
        "message": "Password reset link sent to your email",
        "reset_link": reset_link
    }