# ================================================================
# services/production/app/api/production.py
# ================================================================
"""
Production API endpoints
"""

from fastapi import APIRouter, Depends, HTTPException, Path, Query
from typing import Optional, List
from datetime import date, datetime, timedelta
from uuid import UUID
import structlog

from shared.auth.decorators import get_current_user_dep
from app.core.database import get_db
from app.services.production_service import ProductionService
from app.schemas.production import (
    ProductionBatchCreate, ProductionBatchUpdate, ProductionBatchStatusUpdate,
    ProductionBatchResponse, ProductionBatchListResponse,
    DailyProductionRequirements, ProductionDashboardSummary, ProductionMetrics,
)
from app.core.config import settings

logger = structlog.get_logger()

router = APIRouter(tags=["production"])


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




# ================================================================
# DASHBOARD ENDPOINTS
# ================================================================

@router.get("/tenants/{tenant_id}/production/dashboard-summary", response_model=ProductionDashboardSummary)
async def get_dashboard_summary(
    tenant_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    production_service: ProductionService = Depends(get_production_service)
):
    """Get production dashboard summary using shared auth"""
    try:
        # Extract tenant from user context for security
        current_tenant = current_user.get("tenant_id")
        if str(tenant_id) != current_tenant:
            raise HTTPException(status_code=403, detail="Access denied to this tenant")

        summary = await production_service.get_dashboard_summary(tenant_id)

        logger.info("Retrieved production dashboard summary",
                   tenant_id=str(tenant_id), user_id=current_user.get("user_id"))

        return summary

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


@router.get("/tenants/{tenant_id}/production/daily-requirements", response_model=DailyProductionRequirements)
async def get_daily_requirements(
    tenant_id: UUID = Path(...),
    date: Optional[date] = Query(None, description="Target date for production requirements"),
    current_user: dict = Depends(get_current_user_dep),
    production_service: ProductionService = Depends(get_production_service)
):
    """Get daily production requirements"""
    try:
        current_tenant = current_user.get("tenant_id")
        if str(tenant_id) != current_tenant:
            raise HTTPException(status_code=403, detail="Access denied to this tenant")
        
        target_date = date or datetime.now().date()
        requirements = await production_service.calculate_daily_requirements(tenant_id, target_date)
        
        logger.info("Retrieved daily production requirements", 
                   tenant_id=str(tenant_id), date=target_date.isoformat())
        
        return requirements
        
    except Exception as e:
        logger.error("Error getting daily production requirements", 
                    error=str(e), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to get daily requirements")


@router.get("/tenants/{tenant_id}/production/requirements", response_model=dict)
async def get_production_requirements(
    tenant_id: UUID = Path(...),
    date: Optional[date] = Query(None, description="Target date for production requirements"),
    current_user: dict = Depends(get_current_user_dep),
    production_service: ProductionService = Depends(get_production_service)
):
    """Get production requirements for procurement planning"""
    try:
        current_tenant = current_user.get("tenant_id")
        if str(tenant_id) != current_tenant:
            raise HTTPException(status_code=403, detail="Access denied to this tenant")
        
        target_date = date or datetime.now().date()
        requirements = await production_service.get_production_requirements(tenant_id, target_date)
        
        logger.info("Retrieved production requirements for procurement", 
                   tenant_id=str(tenant_id), date=target_date.isoformat())
        
        return requirements
        
    except Exception as e:
        logger.error("Error getting production requirements", 
                    error=str(e), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to get production requirements")


# ================================================================
# PRODUCTION BATCH ENDPOINTS
# ================================================================

@router.post("/tenants/{tenant_id}/production/batches", response_model=ProductionBatchResponse)
async def create_production_batch(
    batch_data: ProductionBatchCreate,
    tenant_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    production_service: ProductionService = Depends(get_production_service)
):
    """Create a new production batch"""
    try:
        current_tenant = current_user.get("tenant_id")
        if str(tenant_id) != current_tenant:
            raise HTTPException(status_code=403, detail="Access denied to this tenant")
        
        batch = await production_service.create_production_batch(tenant_id, batch_data)
        
        logger.info("Created production batch", 
                   batch_id=str(batch.id), tenant_id=str(tenant_id))
        
        return ProductionBatchResponse.model_validate(batch)
        
    except ValueError as e:
        logger.warning("Invalid batch data", error=str(e), tenant_id=str(tenant_id))
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        logger.error("Error creating production batch", 
                    error=str(e), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to create production batch")


@router.get("/tenants/{tenant_id}/production/batches/active", response_model=ProductionBatchListResponse)
async def get_active_batches(
    tenant_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    db=Depends(get_db)
):
    """Get currently active production batches"""
    try:
        current_tenant = current_user.get("tenant_id")
        if str(tenant_id) != current_tenant:
            raise HTTPException(status_code=403, detail="Access denied to this tenant")
        
        from app.repositories.production_batch_repository import ProductionBatchRepository
        batch_repo = ProductionBatchRepository(db)
        
        batches = await batch_repo.get_active_batches(str(tenant_id))
        batch_responses = [ProductionBatchResponse.model_validate(batch) for batch in batches]
        
        logger.info("Retrieved active production batches", 
                   count=len(batches), tenant_id=str(tenant_id))
        
        return ProductionBatchListResponse(
            batches=batch_responses,
            total_count=len(batches),
            page=1,
            page_size=len(batches)
        )
        
    except Exception as e:
        logger.error("Error getting active batches", 
                    error=str(e), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to get active batches")


@router.get("/tenants/{tenant_id}/production/batches/{batch_id}", response_model=ProductionBatchResponse)
async def get_batch_details(
    tenant_id: UUID = Path(...),
    batch_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    db=Depends(get_db)
):
    """Get detailed information about a production batch"""
    try:
        current_tenant = current_user.get("tenant_id")
        if str(tenant_id) != current_tenant:
            raise HTTPException(status_code=403, detail="Access denied to this tenant")
        
        from app.repositories.production_batch_repository import ProductionBatchRepository
        batch_repo = ProductionBatchRepository(db)
        
        batch = await batch_repo.get(batch_id)
        if not batch or str(batch.tenant_id) != str(tenant_id):
            raise HTTPException(status_code=404, detail="Production batch not found")
        
        logger.info("Retrieved production batch details", 
                   batch_id=str(batch_id), tenant_id=str(tenant_id))
        
        return ProductionBatchResponse.model_validate(batch)
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error("Error getting batch details", 
                    error=str(e), batch_id=str(batch_id), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to get batch details")


@router.put("/tenants/{tenant_id}/production/batches/{batch_id}/status", response_model=ProductionBatchResponse)
async def update_batch_status(
    status_update: ProductionBatchStatusUpdate,
    tenant_id: UUID = Path(...),
    batch_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    production_service: ProductionService = Depends(get_production_service)
):
    """Update production batch status"""
    try:
        current_tenant = current_user.get("tenant_id")
        if str(tenant_id) != current_tenant:
            raise HTTPException(status_code=403, detail="Access denied to this tenant")
        
        batch = await production_service.update_batch_status(tenant_id, batch_id, status_update)
        
        logger.info("Updated production batch status", 
                   batch_id=str(batch_id), 
                   new_status=status_update.status.value,
                   tenant_id=str(tenant_id))
        
        return ProductionBatchResponse.model_validate(batch)
        
    except ValueError as e:
        logger.warning("Invalid status update", error=str(e), batch_id=str(batch_id))
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        logger.error("Error updating batch status", 
                    error=str(e), batch_id=str(batch_id), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to update batch status")


# ================================================================
# PRODUCTION SCHEDULE ENDPOINTS
# ================================================================

@router.get("/tenants/{tenant_id}/production/schedule", response_model=dict)
async def get_production_schedule(
    tenant_id: UUID = Path(...),
    start_date: Optional[date] = Query(None, description="Start date for schedule"),
    end_date: Optional[date] = Query(None, description="End date for schedule"),
    current_user: dict = Depends(get_current_user_dep),
    db=Depends(get_db)
):
    """Get production schedule for a date range"""
    try:
        current_tenant = current_user.get("tenant_id")
        if str(tenant_id) != current_tenant:
            raise HTTPException(status_code=403, detail="Access denied to this tenant")
        
        # Default to next 7 days if no dates provided
        if not start_date:
            start_date = datetime.now().date()
        if not end_date:
            end_date = start_date + timedelta(days=7)
        
        from app.repositories.production_schedule_repository import ProductionScheduleRepository
        schedule_repo = ProductionScheduleRepository(db)
        
        schedules = await schedule_repo.get_schedules_by_date_range(
            str(tenant_id), start_date, end_date
        )
        
        schedule_data = {
            "start_date": start_date.isoformat(),
            "end_date": end_date.isoformat(),
            "schedules": [
                {
                    "id": str(schedule.id),
                    "date": schedule.schedule_date.isoformat(),
                    "shift_start": schedule.shift_start.isoformat(),
                    "shift_end": schedule.shift_end.isoformat(),
                    "capacity_utilization": schedule.utilization_percentage,
                    "batches_planned": schedule.total_batches_planned,
                    "is_finalized": schedule.is_finalized
                }
                for schedule in schedules
            ],
            "total_schedules": len(schedules)
        }
        
        logger.info("Retrieved production schedule", 
                   tenant_id=str(tenant_id),
                   start_date=start_date.isoformat(),
                   end_date=end_date.isoformat(),
                   schedules_count=len(schedules))
        
        return schedule_data
        
    except Exception as e:
        logger.error("Error getting production schedule", 
                    error=str(e), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to get production schedule")




# ================================================================
# CAPACITY MANAGEMENT ENDPOINTS
# ================================================================

@router.get("/tenants/{tenant_id}/production/capacity/status", response_model=dict)
async def get_capacity_status(
    tenant_id: UUID = Path(...),
    date: Optional[date] = Query(None, description="Date for capacity status"),
    current_user: dict = Depends(get_current_user_dep),
    db=Depends(get_db)
):
    """Get production capacity status for a specific date"""
    try:
        current_tenant = current_user.get("tenant_id")
        if str(tenant_id) != current_tenant:
            raise HTTPException(status_code=403, detail="Access denied to this tenant")
        
        target_date = date or datetime.now().date()
        
        from app.repositories.production_capacity_repository import ProductionCapacityRepository
        capacity_repo = ProductionCapacityRepository(db)
        
        capacity_summary = await capacity_repo.get_capacity_utilization_summary(
            str(tenant_id), target_date, target_date
        )
        
        logger.info("Retrieved capacity status", 
                   tenant_id=str(tenant_id), date=target_date.isoformat())
        
        return capacity_summary
        
    except Exception as e:
        logger.error("Error getting capacity status", 
                    error=str(e), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to get capacity status")


# ================================================================
# METRICS AND ANALYTICS ENDPOINTS
# ================================================================

@router.get("/tenants/{tenant_id}/production/metrics/yield", response_model=dict)
async def get_yield_metrics(
    tenant_id: UUID = Path(...),
    start_date: date = Query(..., description="Start date for metrics"),
    end_date: date = Query(..., description="End date for metrics"),
    current_user: dict = Depends(get_current_user_dep),
    db=Depends(get_db)
):
    """Get production yield metrics for analysis"""
    try:
        current_tenant = current_user.get("tenant_id")
        if str(tenant_id) != current_tenant:
            raise HTTPException(status_code=403, detail="Access denied to this tenant")
        
        from app.repositories.production_batch_repository import ProductionBatchRepository
        batch_repo = ProductionBatchRepository(db)
        
        metrics = await batch_repo.get_production_metrics(str(tenant_id), start_date, end_date)
        
        logger.info("Retrieved yield metrics", 
                   tenant_id=str(tenant_id),
                   start_date=start_date.isoformat(),
                   end_date=end_date.isoformat())
        
        return metrics
        
    except Exception as e:
        logger.error("Error getting yield metrics", 
                    error=str(e), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to get yield metrics")