from fastapi import Request, status, HTTPException
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
from sqlalchemy.exc import IntegrityError
from jose.exceptions import JWTError
import traceback

async def validation_exception_handler(request: Request, exc: RequestValidationError):
    errors = []
    for error in exc.errors():
        field = '.'.join((str(loc) for loc in error['loc'] if loc != 'body'))
        errors.append({'field': field, 'message': error['msg']})
    first_error = errors[0]['message'] if errors else 'Validation error'
    return JSONResponse(status_code=status.HTTP_400_BAD_REQUEST, content={'status': 'error', 'message': first_error, 'errors': errors})

async def integrity_error_handler(request: Request, exc: IntegrityError):
    error_msg = str(exc.orig) if hasattr(exc, 'orig') else str(exc)
    if 'Duplicate entry' in error_msg or 'UNIQUE constraint' in error_msg:
        return JSONResponse(status_code=status.HTTP_400_BAD_REQUEST, content={'status': 'error', 'message': 'Duplicate entry', 'errors': [{'message': 'This record already exists'}]})
    return JSONResponse(status_code=status.HTTP_400_BAD_REQUEST, content={'status': 'error', 'message': 'Database integrity error'})

async def jwt_error_handler(request: Request, exc: JWTError):
    return JSONResponse(status_code=status.HTTP_401_UNAUTHORIZED, content={'status': 'error', 'message': 'Invalid token'})

async def http_exception_handler(request: Request, exc: HTTPException):
    if isinstance(exc.detail, dict):
        return JSONResponse(status_code=exc.status_code, content=exc.detail)
    return JSONResponse(status_code=exc.status_code, content={'status': 'error', 'message': str(exc.detail) if exc.detail else 'An error occurred'})

async def general_exception_handler(request: Request, exc: Exception):
    from ..config.logging_config import get_logger
    from ..config.settings import settings
    logger = get_logger(__name__)
    request_id = getattr(request.state, 'request_id', None)
    logger.error(f'Unhandled exception: {type(exc).__name__}: {str(exc)}', extra={'request_id': request_id, 'path': request.url.path, 'method': request.method, 'exception_type': type(exc).__name__}, exc_info=True)
    if isinstance(exc, Exception) and hasattr(exc, 'status_code'):
        status_code = exc.status_code
        if hasattr(exc, 'detail'):
            detail = exc.detail
            if isinstance(detail, dict):
                return JSONResponse(status_code=status_code, content=detail)
            message = str(detail) if detail else 'An error occurred'
        else:
            message = str(exc) if str(exc) else 'Internal server error'
    else:
        status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
        message = str(exc) if str(exc) else 'Internal server error'
    response_content = {'status': 'error', 'message': message}
    if settings.is_development:
        response_content['stack'] = traceback.format_exc()
    return JSONResponse(status_code=status_code, content=response_content)