# services/production/app/api/equipment.py
"""
Equipment API - CRUD operations on Equipment model
"""

from fastapi import APIRouter, Depends, HTTPException, Path, Query
from typing import Optional
from uuid import UUID
import structlog

from shared.auth.decorators import get_current_user_dep
from shared.auth.access_control import require_user_role
from shared.routing import RouteBuilder
from shared.security import create_audit_logger, AuditSeverity, AuditAction
from app.core.database import get_db
from app.services.production_service import ProductionService
from app.models import AuditLog
from app.schemas.equipment import (
    EquipmentCreate,
    EquipmentUpdate,
    EquipmentResponse,
    EquipmentListResponse,
    EquipmentDeletionSummary
)
from app.models.production import EquipmentStatus, EquipmentType
from app.core.config import settings

logger = structlog.get_logger()
route_builder = RouteBuilder('production')
router = APIRouter(tags=["production-equipment"])

# Initialize audit logger with the production service's AuditLog model
audit_logger = create_audit_logger("production-service", AuditLog)


def get_production_service() -> ProductionService:
    """Dependency injection for production service"""
    from app.core.database import database_manager
    return ProductionService(database_manager, settings)


@router.get(
    route_builder.build_base_route("equipment"),
    response_model=EquipmentListResponse
)
async def list_equipment(
    tenant_id: UUID = Path(...),
    status: Optional[EquipmentStatus] = Query(None, description="Filter by status"),
    type: Optional[EquipmentType] = Query(None, description="Filter by equipment type"),
    is_active: Optional[bool] = Query(None, description="Filter by active status"),
    page: int = Query(1, ge=1, description="Page number"),
    page_size: int = Query(50, ge=1, le=100, description="Page size"),
    current_user: dict = Depends(get_current_user_dep),
    production_service: ProductionService = Depends(get_production_service)
):
    """List equipment with filters: status, type, active status"""
    try:
        filters = {
            "status": status,
            "type": type,
            "is_active": is_active
        }

        equipment_list = await production_service.get_equipment_list(tenant_id, filters, page, page_size)

        logger.info("Retrieved equipment list",
                   tenant_id=str(tenant_id), filters=filters)

        return equipment_list

    except Exception as e:
        logger.error("Error listing equipment",
                    error=str(e), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to list equipment")


@router.post(
    route_builder.build_base_route("equipment"),
    response_model=EquipmentResponse
)
async def create_equipment(
    equipment_data: EquipmentCreate,
    tenant_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    production_service: ProductionService = Depends(get_production_service),
    db = Depends(get_db)
):
    """Create a new equipment item"""
    try:
        equipment = await production_service.create_equipment(tenant_id, equipment_data)

        logger.info("Created equipment",
                   equipment_id=str(equipment.id), tenant_id=str(tenant_id))

        # Audit log the equipment creation
        await audit_logger.log_event(
            db_session=db,
            tenant_id=str(tenant_id),
            user_id=current_user.get('user_id'),
            action=AuditAction.CREATE.value,
            resource_type="equipment",
            resource_id=str(equipment.id),
            severity=AuditSeverity.INFO.value,
            audit_metadata={"equipment_name": equipment.name, "equipment_type": equipment.type.value}
        )

        return EquipmentResponse.model_validate(equipment)

    except ValueError as e:
        logger.warning("Validation error creating equipment",
                      error=str(e), tenant_id=str(tenant_id))
        raise HTTPException(status_code=400, detail=str(e))

    except Exception as e:
        logger.error("Error creating equipment",
                    error=str(e), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to create equipment")


@router.get(
    route_builder.build_base_route("equipment/{equipment_id}"),
    response_model=EquipmentResponse
)
async def get_equipment(
    tenant_id: UUID = Path(...),
    equipment_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    production_service: ProductionService = Depends(get_production_service)
):
    """Get a specific equipment item"""
    try:
        equipment = await production_service.get_equipment(tenant_id, equipment_id)

        if not equipment:
            raise HTTPException(status_code=404, detail="Equipment not found")

        logger.info("Retrieved equipment",
                   equipment_id=str(equipment_id), tenant_id=str(tenant_id))

        return EquipmentResponse.model_validate(equipment)

    except HTTPException:
        raise
    except Exception as e:
        logger.error("Error retrieving equipment",
                    error=str(e), equipment_id=str(equipment_id), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to retrieve equipment")


@router.put(
    route_builder.build_base_route("equipment/{equipment_id}"),
    response_model=EquipmentResponse
)
async def update_equipment(
    equipment_data: EquipmentUpdate,
    tenant_id: UUID = Path(...),
    equipment_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    production_service: ProductionService = Depends(get_production_service),
    db = Depends(get_db)
):
    """Update an equipment item"""
    try:
        equipment = await production_service.update_equipment(tenant_id, equipment_id, equipment_data)

        if not equipment:
            raise HTTPException(status_code=404, detail="Equipment not found")

        logger.info("Updated equipment",
                   equipment_id=str(equipment_id), tenant_id=str(tenant_id))

        # Audit log the equipment update
        await audit_logger.log_event(
            db_session=db,
            tenant_id=str(tenant_id),
            user_id=current_user.get('user_id'),
            action=AuditAction.UPDATE.value,
            resource_type="equipment",
            resource_id=str(equipment_id),
            severity=AuditSeverity.INFO.value,
            audit_metadata={"updates": equipment_data.model_dump(exclude_unset=True)}
        )

        return EquipmentResponse.model_validate(equipment)

    except HTTPException:
        raise
    except ValueError as e:
        logger.warning("Validation error updating equipment",
                      error=str(e), equipment_id=str(equipment_id), tenant_id=str(tenant_id))
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        logger.error("Error updating equipment",
                    error=str(e), equipment_id=str(equipment_id), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to update equipment")


@router.get(
    route_builder.build_base_route("equipment/{equipment_id}/deletion-summary"),
    response_model=EquipmentDeletionSummary
)
async def get_equipment_deletion_summary(
    tenant_id: UUID = Path(...),
    equipment_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    production_service: ProductionService = Depends(get_production_service)
):
    """Get deletion summary for equipment (dependency check)"""
    try:
        summary = await production_service.get_equipment_deletion_summary(tenant_id, equipment_id)

        logger.info("Retrieved equipment deletion summary",
                   equipment_id=str(equipment_id), tenant_id=str(tenant_id))

        return EquipmentDeletionSummary(**summary)

    except Exception as e:
        logger.error("Error getting equipment deletion summary",
                    error=str(e), equipment_id=str(equipment_id), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to get deletion summary")


@router.delete(
    route_builder.build_base_route("equipment/{equipment_id}")
)
async def delete_equipment(
    tenant_id: UUID = Path(...),
    equipment_id: UUID = Path(...),
    permanent: bool = Query(False, description="Permanent delete (hard delete) if true"),
    current_user: dict = Depends(get_current_user_dep),
    production_service: ProductionService = Depends(get_production_service),
    db = Depends(get_db)
):
    """Delete an equipment item. Use permanent=true for hard delete (requires admin role)"""
    try:
        # Hard delete requires admin role
        if permanent:
            user_role = current_user.get('role', '').lower()
            if user_role not in ['admin', 'owner']:
                raise HTTPException(
                    status_code=403,
                    detail="Hard delete requires admin or owner role"
                )

            success = await production_service.hard_delete_equipment(tenant_id, equipment_id)
            delete_type = "hard_delete"
            severity = AuditSeverity.CRITICAL.value
        else:
            success = await production_service.delete_equipment(tenant_id, equipment_id)
            delete_type = "soft_delete"
            severity = AuditSeverity.WARNING.value

        if not success:
            raise HTTPException(status_code=404, detail="Equipment not found")

        logger.info(f"{'Hard' if permanent else 'Soft'} deleted equipment",
                   equipment_id=str(equipment_id), tenant_id=str(tenant_id))

        # Audit log the equipment deletion
        await audit_logger.log_event(
            db_session=db,
            tenant_id=str(tenant_id),
            user_id=current_user.get('user_id'),
            action=AuditAction.DELETE.value,
            resource_type="equipment",
            resource_id=str(equipment_id),
            severity=severity,
            audit_metadata={"action": delete_type, "permanent": permanent}
        )

        return {"message": f"Equipment {'permanently deleted' if permanent else 'deleted'} successfully"}

    except HTTPException:
        raise
    except Exception as e:
        logger.error("Error deleting equipment",
                    error=str(e), equipment_id=str(equipment_id), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to delete equipment")
