# ================================================================
# services/orders/app/api/customers.py
# ================================================================
"""
Customers API endpoints - ATOMIC CRUD operations
"""

from typing import List
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, Path, Query, status
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.orders_service import OrdersService
from app.models import AuditLog
from app.schemas.order_schemas import (
    CustomerCreate,
    CustomerUpdate,
    CustomerResponse
)

logger = structlog.get_logger()
audit_logger = create_audit_logger("orders-service", AuditLog)

# Create route builder for consistent URL structure
route_builder = RouteBuilder('orders')

router = APIRouter()


# ===== Dependency Injection =====

async def get_orders_service(db = Depends(get_db)) -> OrdersService:
    """Get orders service with dependencies"""
    from app.repositories.order_repository import (
        OrderRepository,
        CustomerRepository,
        OrderItemRepository,
        OrderStatusHistoryRepository
    )
    from shared.clients import (
        get_inventory_client,
        get_production_client,
        get_sales_client
    )

    return OrdersService(
        order_repo=OrderRepository(),
        customer_repo=CustomerRepository(),
        order_item_repo=OrderItemRepository(),
        status_history_repo=OrderStatusHistoryRepository(),
        inventory_client=get_inventory_client(),
        production_client=get_production_client(),
        sales_client=get_sales_client()
    )


# ===== Customer CRUD Endpoints =====

@router.post(
    route_builder.build_base_route("customers"),
    response_model=CustomerResponse,
    status_code=status.HTTP_201_CREATED
)
@require_user_role(['admin', 'owner', 'member'])
async def create_customer(
    customer_data: CustomerCreate,
    tenant_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    orders_service: OrdersService = Depends(get_orders_service),
    db = Depends(get_db)
):
    """Create a new customer"""
    try:
        # Check if customer code already exists
        existing_customer = await orders_service.customer_repo.get_by_customer_code(
            db, customer_data.customer_code, tenant_id
        )
        if existing_customer:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Customer code already exists"
            )

        # Extract user ID safely
        user_id = current_user.get("user_id")
        if not user_id:
            logger.error("User ID not found in current_user context", current_user_keys=list(current_user.keys()))
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="User authentication error"
            )
        
        customer = await orders_service.customer_repo.create(
            db,
            obj_in=customer_data,
            created_by=UUID(user_id),
            tenant_id=tenant_id
        )

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

        logger.info("Customer created successfully",
                   customer_id=str(customer.id),
                   customer_code=customer.customer_code)

        return CustomerResponse.from_orm(customer)

    except HTTPException:
        raise
    except Exception as e:
        logger.error("Error creating customer", error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to create customer"
        )


@router.get(
    route_builder.build_base_route("customers"),
    response_model=List[CustomerResponse]
)
async def get_customers(
    tenant_id: UUID = Path(...),
    active_only: bool = Query(True, description="Filter for active customers only"),
    skip: int = Query(0, ge=0, description="Number of customers to skip"),
    limit: int = Query(100, ge=1, le=1000, description="Number of customers to return"),
    current_user: dict = Depends(get_current_user_dep),
    orders_service: OrdersService = Depends(get_orders_service),
    db = Depends(get_db)
):
    """Get customers with filtering and pagination"""
    try:
        if active_only:
            customers = await orders_service.customer_repo.get_active_customers(
                db, tenant_id, skip, limit
            )
        else:
            customers = await orders_service.customer_repo.get_multi(
                db, tenant_id, skip, limit, order_by="name"
            )

        return [CustomerResponse.from_orm(customer) for customer in customers]

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


@router.get(
    route_builder.build_resource_detail_route("customers", "customer_id"),
    response_model=CustomerResponse
)
async def get_customer(
    tenant_id: UUID = Path(...),
    customer_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    orders_service: OrdersService = Depends(get_orders_service),
    db = Depends(get_db)
):
    """Get customer details by ID"""
    try:
        customer = await orders_service.customer_repo.get(db, customer_id, tenant_id)
        if not customer:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Customer not found"
            )

        return CustomerResponse.from_orm(customer)

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


@router.put(
    route_builder.build_resource_detail_route("customers", "customer_id"),
    response_model=CustomerResponse
)
@require_user_role(['admin', 'owner', 'member'])
async def update_customer(
    customer_data: CustomerUpdate,
    tenant_id: UUID = Path(...),
    customer_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    orders_service: OrdersService = Depends(get_orders_service),
    db = Depends(get_db)
):
    """Update customer information"""
    try:
        # Get existing customer
        customer = await orders_service.customer_repo.get(db, customer_id, tenant_id)
        if not customer:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Customer not found"
            )

        # Update customer
        # Extract user ID safely for update
        user_id = current_user.get("user_id")
        if not user_id:
            logger.error("User ID not found in current_user context for update", current_user_keys=list(current_user.keys()))
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="User authentication error"
            )

        updated_customer = await orders_service.customer_repo.update(
            db,
            db_obj=customer,
            obj_in=customer_data.dict(exclude_unset=True),
            updated_by=UUID(user_id)
        )

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

        logger.info("Customer updated successfully",
                   customer_id=str(customer_id))

        return CustomerResponse.from_orm(updated_customer)

    except HTTPException:
        raise
    except Exception as e:
        logger.error("Error updating customer",
                    customer_id=str(customer_id),
                    error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to update customer"
        )


@router.delete(
    route_builder.build_resource_detail_route("customers", "customer_id"),
    status_code=status.HTTP_204_NO_CONTENT
)
@require_user_role(['admin', 'owner'])
async def delete_customer(
    tenant_id: UUID = Path(...),
    customer_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    orders_service: OrdersService = Depends(get_orders_service),
    db = Depends(get_db)
):
    """
    Delete a customer (Admin+ only, GDPR-compliant soft delete)
    Removes PII while maintaining referential integrity
    """
    try:
        customer = await orders_service.customer_repo.get(db, customer_id, tenant_id)
        if not customer:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Customer not found"
            )

        # Capture customer data before deletion (for audit trail)
        # Note: This is anonymized after retention period in compliance with GDPR
        customer_data = {
            "customer_code": customer.customer_code,
            "customer_name": customer.customer_name,
            "email": customer.email,
            "phone": customer.phone,
            "business_type": customer.business_type if hasattr(customer, 'business_type') else None
        }

        await orders_service.customer_repo.delete(db, customer_id, tenant_id)

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

        # Log HIGH severity audit event for customer deletion (GDPR compliance)
        try:
            await audit_logger.log_deletion(
                db_session=db,
                tenant_id=str(tenant_id),
                user_id=current_user["user_id"],
                resource_type="customer",
                resource_id=str(customer_id),
                resource_data=customer_data,
                description=f"Admin {current_user.get('email', 'unknown')} deleted customer {customer_data['customer_code']} (GDPR-compliant soft delete)",
                endpoint=f"/customers/{customer_id}",
                method="DELETE",
                severity=AuditSeverity.HIGH.value
            )
        except Exception as audit_error:
            logger.warning("Failed to log audit event", error=str(audit_error))

        logger.info("Customer deleted successfully (GDPR-compliant)",
                   customer_id=str(customer_id),
                   tenant_id=str(tenant_id),
                   user_id=current_user["user_id"])

    except HTTPException:
        raise
    except Exception as e:
        logger.error("Error deleting customer",
                    customer_id=str(customer_id),
                    error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to delete customer"
        )
