import json
from fastapi import APIRouter, Depends, Request
from sqlalchemy import select, update
from sqlalchemy.ext.asyncio import AsyncSession
from pydantic import BaseModel, ValidationError
from app.db.session import get_db
from app.models.user import User
from app.core.security import validate_token
from app.api.v1.category_api import decrypt_data
from app.utils.responses import custom_response
from app.core.logging import logger

router = APIRouter()

class ProfileUpdateRequest(BaseModel):
    fullname: str

@router.post("/profile/update")
async def update_profile(
    request: Request,
    db: AsyncSession = Depends(get_db),
    token_data: dict = Depends(validate_token)
):
    """
    Update user's first name. Follows history.py flow.
    """
    logger.info("Received request for /profile/update endpoint.")
    try:
        # Step 1: Authorization check
        if token_data.get('code') != 200:
            logger.warning(f"Unauthorized access attempt to /profile/update. Message: {token_data.get('message', 'N/A')}")
            return custom_response(code=token_data.get('code', 500), message=token_data.get('message', 'Unauthorized'))

        user_id = token_data.get('user_id')
        if not user_id:
            logger.warning("User not authenticated or user_id is missing from the token.")
            return custom_response(code=404, message="User not found or not authenticated")

        # Step 2: Read raw encrypted data
        try:
            encrypted_data = await request.body()
            logger.debug(f"Encrypted request body: {encrypted_data}")
        except Exception as e:
            logger.error(f"Failed to read request body for /profile/update: {str(e)}", exc_info=True)
            return custom_response(code=400, message=f"Failed to read request body: {str(e)}")

        # Step 3: Decrypt data
        decrypted_data = decrypt_data(encrypted_data)
        logger.debug(f"Decrypted data: {decrypted_data}")

        # Step 4: Parse decrypted JSON and validate schema
        try:
            decrypted_json = decrypted_data
            params = ProfileUpdateRequest.model_validate(decrypted_json)
            logger.info(f"Successfully parsed and validated payload for /profile/update: {params}")
        except json.JSONDecodeError:
            logger.warning(f"Invalid JSON after decryption for /profile/update. Decrypted data: {decrypted_data}")
            return custom_response(code=400, message="Invalid JSON after decryption")
        except ValidationError as ve:
            logger.warning(f"Validation failed for /profile/update request. Errors: {ve.errors()}")
            return custom_response(code=422, data=ve.errors(), message="Validation failed")

        # Step 5: Check if user exists
        result = await db.execute(select(User).where(User.user_id == user_id))
        user = result.scalars().first()
        if not user:
            logger.warning(f"User with user_id {user_id} not found in DB.")
            return custom_response(code=404, message="User not found")

        # Step 6: Update fname
        await db.execute(
            update(User)
            .where(User.user_id == user_id)
            .values(fullname=params.fullname)
        )
        await db.commit()
        logger.info(f"Updated firstname for user_id {user_id} to '{params.fullname}'.")

        return custom_response(code=200, message="Profile updated successfully", data={"user_id": user_id, "firstname": params.fullname})

    except Exception as e:
        await db.rollback()
        logger.error(f"Error updating profile: {str(e)}", exc_info=True)
        return custom_response(code=500, message=f"Internal server error: {str(e)}")