# services/production/app/api/quality_templates.py
"""
Quality Check Templates API - CRUD operations on quality check templates
"""

from fastapi import APIRouter, Depends, HTTPException, Path, Query, status
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, RouteCategory
from app.core.database import get_db
from app.services.quality_template_service import QualityTemplateService
from app.models.production import ProcessStage, QualityCheckTemplate
from app.schemas.quality_templates import (
    QualityCheckTemplateCreate,
    QualityCheckTemplateUpdate,
    QualityCheckTemplateResponse,
    QualityCheckTemplateList,
    QualityCheckType
)

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


# ===== Quality Template CRUD Endpoints =====

@router.get(
    route_builder.build_base_route("quality-templates"),
    response_model=QualityCheckTemplateList
)
async def list_quality_templates(
    tenant_id: UUID = Path(...),
    stage: Optional[ProcessStage] = Query(None, description="Filter by process stage"),
    check_type: Optional[QualityCheckType] = Query(None, description="Filter by check type"),
    is_active: Optional[bool] = Query(True, description="Filter by active status"),
    skip: int = Query(0, ge=0, description="Number of templates to skip"),
    limit: int = Query(100, ge=1, le=1000, description="Number of templates to return"),
    current_user: dict = Depends(get_current_user_dep),
    db = Depends(get_db)
):
    """
    List quality check templates with filtering and pagination

    Filters:
    - stage: Filter by applicable process stage
    - check_type: Filter by type of quality check
    - is_active: Filter by active status (default: True)
    """
    try:
        service = QualityTemplateService(db)

        templates, total = await service.get_templates(
            tenant_id=str(tenant_id),
            stage=stage,
            check_type=check_type.value if check_type else None,
            is_active=is_active,
            skip=skip,
            limit=limit
        )

        logger.info("Retrieved quality templates",
                   tenant_id=str(tenant_id),
                   total=total,
                   filters={"stage": stage, "check_type": check_type, "is_active": is_active})

        return QualityCheckTemplateList(
            templates=[QualityCheckTemplateResponse.from_orm(t) for t in templates],
            total=total,
            skip=skip,
            limit=limit
        )

    except Exception as e:
        logger.error("Error listing quality templates",
                    error=str(e), tenant_id=str(tenant_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to retrieve quality templates"
        )


@router.post(
    route_builder.build_base_route("quality-templates"),
    response_model=QualityCheckTemplateResponse,
    status_code=status.HTTP_201_CREATED
)
@require_user_role(['admin', 'owner', 'member'])
async def create_quality_template(
    template_data: QualityCheckTemplateCreate,
    tenant_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    db = Depends(get_db)
):
    """Create a new quality check template"""
    try:
        service = QualityTemplateService(db)

        # Add created_by from current user
        template_dict = template_data.dict()
        template_dict['created_by'] = UUID(current_user["user_id"])
        template_create = QualityCheckTemplateCreate(**template_dict)

        # Create template via service (handles validation and business rules)
        template = await service.create_template(
            tenant_id=str(tenant_id),
            template_data=template_create
        )

        # Commit the transaction to persist changes
        await db.commit()

        logger.info("Created quality template",
                   template_id=str(template.id),
                   template_name=template.name,
                   tenant_id=str(tenant_id))

        return QualityCheckTemplateResponse.from_orm(template)

    except ValueError as e:
        # Business rule validation errors
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        logger.error("Error creating quality template",
                    error=str(e), tenant_id=str(tenant_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to create quality template"
        )


@router.get(
    route_builder.build_resource_detail_route("quality-templates", "template_id"),
    response_model=QualityCheckTemplateResponse
)
async def get_quality_template(
    tenant_id: UUID = Path(...),
    template_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    db = Depends(get_db)
):
    """Get a specific quality check template"""
    try:
        service = QualityTemplateService(db)

        template = await service.get_template(
            tenant_id=str(tenant_id),
            template_id=template_id
        )

        if not template:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Quality template not found"
            )

        return QualityCheckTemplateResponse.from_orm(template)

    except HTTPException:
        raise
    except Exception as e:
        logger.error("Error getting quality template",
                    error=str(e),
                    template_id=str(template_id),
                    tenant_id=str(tenant_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to retrieve quality template"
        )


@router.put(
    route_builder.build_resource_detail_route("quality-templates", "template_id"),
    response_model=QualityCheckTemplateResponse
)
@require_user_role(['admin', 'owner', 'member'])
async def update_quality_template(
    template_data: QualityCheckTemplateUpdate,
    tenant_id: UUID = Path(...),
    template_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    db = Depends(get_db)
):
    """Update a quality check template"""
    try:
        service = QualityTemplateService(db)

        # Update template via service (handles validation and business rules)
        template = await service.update_template(
            tenant_id=str(tenant_id),
            template_id=template_id,
            template_data=template_data
        )

        if not template:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Quality template not found"
            )

        # Commit the transaction to persist changes
        await db.commit()

        logger.info("Updated quality template",
                   template_id=str(template_id),
                   tenant_id=str(tenant_id))

        return QualityCheckTemplateResponse.from_orm(template)

    except ValueError as e:
        # Business rule validation errors
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error("Error updating quality template",
                    error=str(e),
                    template_id=str(template_id),
                    tenant_id=str(tenant_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to update quality template"
        )


@router.delete(
    route_builder.build_resource_detail_route("quality-templates", "template_id"),
    status_code=status.HTTP_204_NO_CONTENT
)
@require_user_role(['admin', 'owner'])
async def delete_quality_template(
    tenant_id: UUID = Path(...),
    template_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    db = Depends(get_db)
):
    """
    Delete a quality check template

    Note: Service layer determines whether to use soft or hard delete
    based on business rules (checking dependencies, etc.)
    """
    try:
        service = QualityTemplateService(db)

        # Delete template via service (handles business rules)
        success = await service.delete_template(
            tenant_id=str(tenant_id),
            template_id=template_id
        )

        if not success:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Quality template not found"
            )

        # Commit the transaction to persist changes
        await db.commit()

        logger.info("Deleted quality template",
                   template_id=str(template_id),
                   tenant_id=str(tenant_id))

    except HTTPException:
        raise
    except Exception as e:
        await db.rollback()
        logger.error("Error deleting quality template",
                    error=str(e),
                    template_id=str(template_id),
                    tenant_id=str(tenant_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to delete quality template"
        )


# ===== Additional Quality Template Operations =====

@router.get(
    route_builder.build_custom_route(
        RouteCategory.BASE,
        ["quality-templates", "stages", "{stage}"]
    ),
    response_model=QualityCheckTemplateList
)
async def get_templates_for_stage(
    tenant_id: UUID = Path(...),
    stage: ProcessStage = Path(...),
    is_active: bool = Query(True, description="Filter by active status"),
    current_user: dict = Depends(get_current_user_dep),
    db = Depends(get_db)
):
    """Get all quality templates applicable to a specific process stage"""
    try:
        service = QualityTemplateService(db)

        templates = await service.get_templates_for_stage(
            tenant_id=str(tenant_id),
            stage=stage,
            is_active=is_active
        )

        logger.info("Retrieved templates for stage",
                   tenant_id=str(tenant_id),
                   stage=stage,
                   count=len(templates))

        return QualityCheckTemplateList(
            templates=[QualityCheckTemplateResponse.from_orm(t) for t in templates],
            total=len(templates),
            skip=0,
            limit=len(templates)
        )

    except Exception as e:
        logger.error("Error getting templates for stage",
                    error=str(e),
                    stage=stage,
                    tenant_id=str(tenant_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to retrieve templates for stage"
        )


@router.post(
    route_builder.build_resource_action_route("quality-templates", "template_id", "duplicate"),
    response_model=QualityCheckTemplateResponse,
    status_code=status.HTTP_201_CREATED
)
@require_user_role(['admin', 'owner', 'member'])
async def duplicate_quality_template(
    tenant_id: UUID = Path(...),
    template_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    db = Depends(get_db)
):
    """Duplicate an existing quality check template"""
    try:
        service = QualityTemplateService(db)

        # Duplicate template via service (handles business rules)
        duplicate = await service.duplicate_template(
            tenant_id=str(tenant_id),
            template_id=template_id
        )

        if not duplicate:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Quality template not found"
            )

        logger.info("Duplicated quality template",
                   original_id=str(template_id),
                   duplicate_id=str(duplicate.id),
                   tenant_id=str(tenant_id))

        return QualityCheckTemplateResponse.from_orm(duplicate)

    except HTTPException:
        raise
    except Exception as e:
        logger.error("Error duplicating quality template",
                    error=str(e),
                    template_id=str(template_id),
                    tenant_id=str(tenant_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to duplicate quality template"
        )


@router.post(
    route_builder.build_operations_route("quality-templates/validate"),
    response_model=dict
)
@require_user_role(['admin', 'owner', 'member'])
async def validate_quality_template(
    template_data: dict,
    tenant_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
):
    """
    Validate quality template configuration without creating it

    Returns validation result with any errors found
    """
    try:
        errors = []

        # Basic validation
        if not template_data.get('name'):
            errors.append("Template name is required")

        if not template_data.get('check_type'):
            errors.append("Check type is required")

        # Validate measurement fields
        check_type = template_data.get('check_type')
        if check_type in ['measurement', 'temperature', 'weight']:
            if template_data.get('min_value') is not None and template_data.get('max_value') is not None:
                if template_data['min_value'] >= template_data['max_value']:
                    errors.append("Minimum value must be less than maximum value")

        # Validate weight
        weight = template_data.get('weight', 1.0)
        if weight < 0 or weight > 10:
            errors.append("Weight must be between 0 and 10")

        is_valid = len(errors) == 0

        logger.info("Validated quality template",
                   tenant_id=str(tenant_id),
                   valid=is_valid,
                   error_count=len(errors))

        return {
            "valid": is_valid,
            "errors": errors
        }

    except Exception as e:
        logger.error("Error validating quality template",
                    error=str(e), tenant_id=str(tenant_id))
        return {
            "valid": False,
            "errors": [f"Validation error: {str(e)}"]
        }
