from fastapi import APIRouter, Depends, HTTPException, Query, Body
from sqlalchemy.orm import Session
from typing import Optional, List, Dict, Any
from ...shared.config.database import get_db
from ...security.middleware.auth import authorize_roles, get_current_user
from ...auth.models.user import User
from ..models.workflow import WorkflowType, WorkflowStatus, WorkflowTrigger
from ..services.workflow_service import WorkflowService
from pydantic import BaseModel

router = APIRouter(prefix='/workflows', tags=['workflows'])

# Request/Response Models
class WorkflowCreate(BaseModel):
    name: str
    description: Optional[str] = None
    workflow_type: str
    trigger: str
    steps: List[Dict[str, Any]]
    trigger_config: Optional[Dict[str, Any]] = None
    sla_hours: Optional[int] = None

class WorkflowUpdate(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None
    steps: Optional[List[Dict[str, Any]]] = None
    status: Optional[str] = None
    trigger_config: Optional[Dict[str, Any]] = None
    sla_hours: Optional[int] = None

class WorkflowTriggerRequest(BaseModel):
    booking_id: Optional[int] = None
    room_id: Optional[int] = None
    user_id: Optional[int] = None
    metadata: Optional[Dict[str, Any]] = None

# Workflow CRUD
@router.post('/')
async def create_workflow(
    workflow_data: WorkflowCreate,
    current_user: User = Depends(authorize_roles('admin')),
    db: Session = Depends(get_db)
):
    """Create a new workflow"""
    try:
        workflow = WorkflowService.create_workflow(
            db=db,
            name=workflow_data.name,
            workflow_type=WorkflowType(workflow_data.workflow_type),
            trigger=WorkflowTrigger(workflow_data.trigger),
            steps=workflow_data.steps,
            created_by=current_user.id,
            description=workflow_data.description,
            trigger_config=workflow_data.trigger_config,
            sla_hours=workflow_data.sla_hours
        )
        return {'status': 'success', 'data': {
            'id': workflow.id,
            'name': workflow.name,
            'workflow_type': workflow.workflow_type.value,
            'trigger': workflow.trigger.value,
            'status': workflow.status.value,
            'created_at': workflow.created_at.isoformat()
        }}
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.get('/')
async def get_workflows(
    workflow_type: Optional[str] = Query(None),
    status: Optional[str] = Query(None),
    skip: int = Query(0, ge=0),
    limit: int = Query(100, ge=1, le=1000),
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Get workflows"""
    try:
        workflows = WorkflowService.get_workflows(
            db=db,
            workflow_type=WorkflowType(workflow_type) if workflow_type else None,
            status=WorkflowStatus(status) if status else None,
            skip=skip,
            limit=limit
        )
        return {'status': 'success', 'data': [{
            'id': w.id,
            'name': w.name,
            'description': w.description,
            'workflow_type': w.workflow_type.value,
            'trigger': w.trigger.value,
            'status': w.status.value,
            'sla_hours': w.sla_hours,
            'steps': w.steps,
            'trigger_config': w.trigger_config,
            'created_at': w.created_at.isoformat(),
            'updated_at': w.updated_at.isoformat()
        } for w in workflows]}
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.get('/{workflow_id}')
async def get_workflow(
    workflow_id: int,
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Get workflow by ID"""
    try:
        workflow = WorkflowService.get_workflow_by_id(db, workflow_id)
        if not workflow:
            raise HTTPException(status_code=404, detail='Workflow not found')
        
        return {'status': 'success', 'data': {
            'id': workflow.id,
            'name': workflow.name,
            'description': workflow.description,
            'workflow_type': workflow.workflow_type.value,
            'trigger': workflow.trigger.value,
            'status': workflow.status.value,
            'sla_hours': workflow.sla_hours,
            'steps': workflow.steps,
            'trigger_config': workflow.trigger_config,
            'created_at': workflow.created_at.isoformat(),
            'updated_at': workflow.updated_at.isoformat()
        }}
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.put('/{workflow_id}')
async def update_workflow(
    workflow_id: int,
    workflow_data: WorkflowUpdate,
    current_user: User = Depends(authorize_roles('admin')),
    db: Session = Depends(get_db)
):
    """Update workflow"""
    try:
        workflow = WorkflowService.update_workflow(
            db=db,
            workflow_id=workflow_id,
            name=workflow_data.name,
            description=workflow_data.description,
            steps=workflow_data.steps,
            status=WorkflowStatus(workflow_data.status) if workflow_data.status else None,
            trigger_config=workflow_data.trigger_config,
            sla_hours=workflow_data.sla_hours
        )
        if not workflow:
            raise HTTPException(status_code=404, detail='Workflow not found')
        
        return {'status': 'success', 'data': {
            'id': workflow.id,
            'name': workflow.name,
            'status': workflow.status.value,
            'updated_at': workflow.updated_at.isoformat()
        }}
    except HTTPException:
        raise
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.delete('/{workflow_id}')
async def delete_workflow(
    workflow_id: int,
    current_user: User = Depends(authorize_roles('admin')),
    db: Session = Depends(get_db)
):
    """Delete workflow"""
    try:
        success = WorkflowService.delete_workflow(db, workflow_id)
        if not success:
            raise HTTPException(status_code=404, detail='Workflow not found')
        
        return {'status': 'success', 'message': 'Workflow deleted successfully'}
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# Workflow Instances
@router.post('/{workflow_id}/trigger')
async def trigger_workflow(
    workflow_id: int,
    trigger_data: WorkflowTriggerRequest,
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Trigger a workflow"""
    try:
        instance = WorkflowService.trigger_workflow(
            db=db,
            workflow_id=workflow_id,
            booking_id=trigger_data.booking_id,
            room_id=trigger_data.room_id,
            user_id=trigger_data.user_id,
            metadata=trigger_data.metadata
        )
        if not instance:
            raise HTTPException(status_code=404, detail='Workflow not found or inactive')
        
        return {'status': 'success', 'data': {
            'id': instance.id,
            'workflow_id': instance.workflow_id,
            'status': instance.status,
            'started_at': instance.started_at.isoformat(),
            'due_date': instance.due_date.isoformat() if instance.due_date else None
        }}
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.get('/instances/')
async def get_workflow_instances(
    workflow_id: Optional[int] = Query(None),
    booking_id: Optional[int] = Query(None),
    status: Optional[str] = Query(None),
    skip: int = Query(0, ge=0),
    limit: int = Query(100, ge=1, le=1000),
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Get workflow instances"""
    try:
        instances = WorkflowService.get_workflow_instances(
            db=db,
            workflow_id=workflow_id,
            booking_id=booking_id,
            status=status,
            skip=skip,
            limit=limit
        )
        return {'status': 'success', 'data': [{
            'id': i.id,
            'workflow_id': i.workflow_id,
            'booking_id': i.booking_id,
            'room_id': i.room_id,
            'user_id': i.user_id,
            'status': i.status,
            'started_at': i.started_at.isoformat(),
            'completed_at': i.completed_at.isoformat() if i.completed_at else None,
            'due_date': i.due_date.isoformat() if i.due_date else None
        } for i in instances]}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.post('/instances/{instance_id}/complete')
async def complete_workflow_instance(
    instance_id: int,
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Complete workflow instance"""
    try:
        instance = WorkflowService.complete_workflow_instance(db, instance_id)
        if not instance:
            raise HTTPException(status_code=404, detail='Workflow instance not found')
        
        return {'status': 'success', 'data': {
            'id': instance.id,
            'status': instance.status,
            'completed_at': instance.completed_at.isoformat() if instance.completed_at else None
        }}
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# Predefined workflow types
@router.get('/types/pre-arrival')
async def get_pre_arrival_workflows(
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Get pre-arrival workflows"""
    try:
        workflows = WorkflowService.get_pre_arrival_workflows(db)
        return {'status': 'success', 'data': [{
            'id': w.id,
            'name': w.name,
            'description': w.description,
            'trigger': w.trigger.value,
            'sla_hours': w.sla_hours
        } for w in workflows]}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.get('/types/room-preparation')
async def get_room_preparation_workflows(
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Get room preparation workflows"""
    try:
        workflows = WorkflowService.get_room_preparation_workflows(db)
        return {'status': 'success', 'data': [{
            'id': w.id,
            'name': w.name,
            'description': w.description,
            'trigger': w.trigger.value,
            'sla_hours': w.sla_hours
        } for w in workflows]}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

