"""
Approval workflow routes.
"""
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from sqlalchemy.exc import ProgrammingError
from typing import Optional
from ...shared.config.database import get_db
from ...shared.config.logging_config import get_logger
from ...security.middleware.auth import get_current_user, authorize_roles
from ...auth.models.user import User
from ...system.services.approval_service import approval_service
from ...system.models.approval_workflow import ApprovalRequest, ApprovalStatus, ApprovalType
from ...shared.utils.response_helpers import success_response

logger = get_logger(__name__)
router = APIRouter(prefix='/approvals', tags=['approvals'])

@router.get('/pending')
async def get_pending_approvals(
    approval_type: Optional[str] = Query(None),
    page: int = Query(1, ge=1),
    limit: int = Query(50, ge=1, le=100),
    current_user: User = Depends(authorize_roles('admin', 'accountant')),
    db: Session = Depends(get_db)
):
    """Get pending approval requests."""
    try:
        approval_type_enum = None
        if approval_type:
            try:
                approval_type_enum = ApprovalType(approval_type)
            except ValueError:
                raise HTTPException(status_code=400, detail=f'Invalid approval_type: {approval_type}')
        
        offset = (page - 1) * limit
        approvals = approval_service.get_pending_approvals(
            db=db,
            approval_type=approval_type_enum,
            limit=limit,
            offset=offset
        )
        
        return success_response(data={
            'approvals': [{
                'id': app.id,
                'approval_type': app.approval_type.value,
                'status': app.status.value,
                'resource_type': app.resource_type,
                'resource_id': app.resource_id,
                'requested_by': app.requested_by,
                'requested_at': app.requested_at.isoformat() if app.requested_at else None,
                'priority': app.priority,
                'notes': app.notes,
                'request_data': app.request_data,
                'current_data': app.current_data
            } for app in approvals]
        })
    except HTTPException:
        raise
    except ProgrammingError as e:
        # Handle missing table gracefully
        if "doesn't exist" in str(e) and "approval_requests" in str(e):
            logger.warning('Approval requests table does not exist. Returning empty list. Run migrations to create the table.')
            return success_response(data={'approvals': []})
        logger.error(f'Database error getting pending approvals: {str(e)}', exc_info=True)
        raise HTTPException(status_code=500, detail='Database error occurred')
    except Exception as e:
        logger.error(f'Error getting pending approvals: {str(e)}', exc_info=True)
        raise HTTPException(status_code=500, detail=str(e))

@router.post('/{request_id}/approve')
async def approve_request(
    request_id: int,
    notes: Optional[str] = None,
    current_user: User = Depends(authorize_roles('admin', 'accountant')),
    db: Session = Depends(get_db)
):
    """Approve an approval request."""
    try:
        approval = await approval_service.approve_request(
            db=db,
            request_id=request_id,
            approved_by=current_user.id,
            notes=notes
        )
        
        return success_response(
            data={'approval': {
                'id': approval.id,
                'status': approval.status.value,
                'approved_by': approval.approved_by,
                'approved_at': approval.approved_at.isoformat() if approval.approved_at else None
            }},
            message='Approval request approved successfully'
        )
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except ProgrammingError as e:
        if "doesn't exist" in str(e) and "approval_requests" in str(e):
            logger.warning('Approval requests table does not exist. Run migrations to create the table.')
            raise HTTPException(status_code=503, detail='Approval system not available. Please run database migrations.')
        logger.error(f'Database error approving request: {str(e)}', exc_info=True)
        raise HTTPException(status_code=500, detail='Database error occurred')
    except Exception as e:
        logger.error(f'Error approving request: {str(e)}', exc_info=True)
        raise HTTPException(status_code=500, detail=str(e))

@router.post('/{request_id}/reject')
async def reject_request(
    request_id: int,
    rejection_reason: str,
    current_user: User = Depends(authorize_roles('admin', 'accountant')),
    db: Session = Depends(get_db)
):
    """Reject an approval request."""
    try:
        approval = await approval_service.reject_request(
            db=db,
            request_id=request_id,
            rejected_by=current_user.id,
            rejection_reason=rejection_reason
        )
        
        return success_response(
            data={'approval': {
                'id': approval.id,
                'status': approval.status.value,
                'rejection_reason': approval.rejection_reason
            }},
            message='Approval request rejected'
        )
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except ProgrammingError as e:
        if "doesn't exist" in str(e) and "approval_requests" in str(e):
            logger.warning('Approval requests table does not exist. Run migrations to create the table.')
            raise HTTPException(status_code=503, detail='Approval system not available. Please run database migrations.')
        logger.error(f'Database error rejecting request: {str(e)}', exc_info=True)
        raise HTTPException(status_code=500, detail='Database error occurred')
    except Exception as e:
        logger.error(f'Error rejecting request: {str(e)}', exc_info=True)
        raise HTTPException(status_code=500, detail=str(e))

@router.get('/my-requests')
async def get_my_approval_requests(
    status: Optional[str] = Query(None),
    page: int = Query(1, ge=1),
    limit: int = Query(50, ge=1, le=100),
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Get current user's approval requests."""
    try:
        status_enum = None
        if status:
            try:
                status_enum = ApprovalStatus(status)
            except ValueError:
                raise HTTPException(status_code=400, detail=f'Invalid status: {status}')
        
        offset = (page - 1) * limit
        approvals = approval_service.get_user_approvals(
            db=db,
            user_id=current_user.id,
            status=status_enum,
            limit=limit,
            offset=offset
        )
        
        return success_response(data={
            'approvals': [{
                'id': app.id,
                'approval_type': app.approval_type.value,
                'status': app.status.value,
                'resource_type': app.resource_type,
                'resource_id': app.resource_id,
                'requested_at': app.requested_at.isoformat() if app.requested_at else None,
                'approved_at': app.approved_at.isoformat() if app.approved_at else None,
                'rejection_reason': app.rejection_reason
            } for app in approvals]
        })
    except HTTPException:
        raise
    except ProgrammingError as e:
        if "doesn't exist" in str(e) and "approval_requests" in str(e):
            logger.warning('Approval requests table does not exist. Returning empty list. Run migrations to create the table.')
            return success_response(data={'approvals': []})
        logger.error(f'Database error getting user approvals: {str(e)}', exc_info=True)
        raise HTTPException(status_code=500, detail='Database error occurred')
    except Exception as e:
        logger.error(f'Error getting user approvals: {str(e)}', exc_info=True)
        raise HTTPException(status_code=500, detail=str(e))

@router.delete('/{request_id}')
async def cancel_approval_request(
    request_id: int,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Cancel an approval request (only by requester or admin)."""
    try:
        approval = db.query(ApprovalRequest).filter(ApprovalRequest.id == request_id).first()
        
        if not approval:
            raise HTTPException(status_code=404, detail='Approval request not found')
        
        # Only requester or admin can cancel
        if approval.requested_by != current_user.id and current_user.role.name != 'admin':
            raise HTTPException(status_code=403, detail='Not authorized to cancel this request')
        
        # Only pending requests can be cancelled
        if approval.status != ApprovalStatus.pending:
            raise HTTPException(status_code=400, detail='Only pending requests can be cancelled')
        
        approval.status = ApprovalStatus.cancelled
        db.commit()
        
        logger.info(f'Approval request {request_id} cancelled by user {current_user.id}')
        return success_response(message='Approval request cancelled successfully')
    except HTTPException:
        raise
    except ProgrammingError as e:
        if "doesn't exist" in str(e) and "approval_requests" in str(e):
            logger.warning('Approval requests table does not exist. Run migrations to create the table.')
            raise HTTPException(status_code=503, detail='Approval system not available. Please run database migrations.')
        logger.error(f'Database error cancelling approval request: {str(e)}', exc_info=True)
        raise HTTPException(status_code=500, detail='Database error occurred')
    except Exception as e:
        logger.error(f'Error cancelling approval request: {str(e)}', exc_info=True)
        raise HTTPException(status_code=500, detail=str(e))

