# services/sales/app/api/sales_records.py
"""
Sales Records API - Atomic CRUD operations on SalesData model
"""

from fastapi import APIRouter, Depends, HTTPException, Query, Path, status
from typing import List, Optional, Dict, Any
from uuid import UUID
from datetime import datetime
import structlog

from app.schemas.sales import (
    SalesDataCreate,
    SalesDataUpdate,
    SalesDataResponse,
    SalesDataQuery
)
from app.services.sales_service import SalesService
from app.models import AuditLog
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

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

# Initialize audit logger
audit_logger = create_audit_logger("sales-service", AuditLog)


def get_sales_service():
    """Dependency injection for SalesService"""
    return SalesService()


@router.post(
    route_builder.build_base_route("sales"),
    response_model=SalesDataResponse,
    status_code=status.HTTP_201_CREATED
)
@require_user_role(['admin', 'owner', 'member'])
async def create_sales_record(
    sales_data: SalesDataCreate,
    tenant_id: UUID = Path(..., description="Tenant ID"),
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
    sales_service: SalesService = Depends(get_sales_service)
):
    """Create a new sales record"""
    try:
        logger.info(
            "Creating sales record",
            product=sales_data.product_name,
            quantity=sales_data.quantity_sold,
            tenant_id=tenant_id,
            user_id=current_user.get("user_id")
        )

        record = await sales_service.create_sales_record(
            sales_data,
            tenant_id,
            user_id=UUID(current_user["user_id"]) if current_user.get("user_id") else None
        )

        logger.info("Successfully created sales record", record_id=record.id, tenant_id=tenant_id)
        return record

    except ValueError as ve:
        logger.warning("Validation error creating sales record", error=str(ve), tenant_id=tenant_id)
        raise HTTPException(status_code=400, detail=str(ve))
    except Exception as e:
        logger.error("Failed to create sales record", error=str(e), tenant_id=tenant_id)
        raise HTTPException(status_code=500, detail=f"Failed to create sales record: {str(e)}")


@router.get(
    route_builder.build_base_route("sales"),
    response_model=List[SalesDataResponse]
)
async def get_sales_records(
    tenant_id: UUID = Path(..., description="Tenant ID"),
    start_date: Optional[datetime] = Query(None, description="Start date filter"),
    end_date: Optional[datetime] = Query(None, description="End date filter"),
    product_name: Optional[str] = Query(None, description="Product name filter"),
    product_category: Optional[str] = Query(None, description="Product category filter"),
    location_id: Optional[str] = Query(None, description="Location filter"),
    sales_channel: Optional[str] = Query(None, description="Sales channel filter"),
    source: Optional[str] = Query(None, description="Data source filter"),
    is_validated: Optional[bool] = Query(None, description="Validation status filter"),
    limit: int = Query(50, ge=1, le=1000, description="Number of records to return"),
    offset: int = Query(0, ge=0, description="Number of records to skip"),
    order_by: str = Query("date", description="Field to order by"),
    order_direction: str = Query("desc", description="Order direction (asc/desc)"),
    sales_service: SalesService = Depends(get_sales_service)
):
    """Get sales records for a tenant with filtering and pagination"""
    try:
        query_params = SalesDataQuery(
            start_date=start_date,
            end_date=end_date,
            product_name=product_name,
            product_category=product_category,
            location_id=location_id,
            sales_channel=sales_channel,
            source=source,
            is_validated=is_validated,
            limit=limit,
            offset=offset,
            order_by=order_by,
            order_direction=order_direction
        )

        records = await sales_service.get_sales_records(tenant_id, query_params)

        logger.info("Retrieved sales records", count=len(records), tenant_id=tenant_id)
        return records

    except Exception as e:
        logger.error("Failed to get sales records", error=str(e), tenant_id=tenant_id)
        raise HTTPException(status_code=500, detail=f"Failed to get sales records: {str(e)}")


@router.get(
    route_builder.build_resource_detail_route("sales", "record_id"),
    response_model=SalesDataResponse
)
async def get_sales_record(
    tenant_id: UUID = Path(..., description="Tenant ID"),
    record_id: UUID = Path(..., description="Sales record ID"),
    sales_service: SalesService = Depends(get_sales_service)
):
    """Get a specific sales record"""
    try:
        record = await sales_service.get_sales_record(record_id, tenant_id)

        if not record:
            raise HTTPException(status_code=404, detail="Sales record not found")

        return record

    except HTTPException:
        raise
    except Exception as e:
        logger.error("Failed to get sales record", error=str(e), record_id=record_id, tenant_id=tenant_id)
        raise HTTPException(status_code=500, detail=f"Failed to get sales record: {str(e)}")


@router.put(
    route_builder.build_resource_detail_route("sales", "record_id"),
    response_model=SalesDataResponse
)
async def update_sales_record(
    update_data: SalesDataUpdate,
    tenant_id: UUID = Path(..., description="Tenant ID"),
    record_id: UUID = Path(..., description="Sales record ID"),
    sales_service: SalesService = Depends(get_sales_service)
):
    """Update a sales record"""
    try:
        updated_record = await sales_service.update_sales_record(record_id, update_data, tenant_id)

        logger.info("Updated sales record", record_id=record_id, tenant_id=tenant_id)
        return updated_record

    except ValueError as ve:
        logger.warning("Validation error updating sales record", error=str(ve), record_id=record_id)
        raise HTTPException(status_code=400, detail=str(ve))
    except Exception as e:
        logger.error("Failed to update sales record", error=str(e), record_id=record_id, tenant_id=tenant_id)
        raise HTTPException(status_code=500, detail=f"Failed to update sales record: {str(e)}")


@router.delete(
    route_builder.build_resource_detail_route("sales", "record_id")
)
@require_user_role(['admin', 'owner'])
async def delete_sales_record(
    tenant_id: UUID = Path(..., description="Tenant ID"),
    record_id: UUID = Path(..., description="Sales record ID"),
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
    sales_service: SalesService = Depends(get_sales_service)
):
    """Delete a sales record (Admin+ only)"""
    try:
        # Get record details before deletion for audit log
        record = await sales_service.get_sales_record(record_id, tenant_id)

        success = await sales_service.delete_sales_record(record_id, tenant_id)

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

        # Log audit event for sales record deletion
        try:
            from app.core.database import get_db
            db = next(get_db())
            await audit_logger.log_deletion(
                db_session=db,
                tenant_id=str(tenant_id),
                user_id=current_user["user_id"],
                resource_type="sales_record",
                resource_id=str(record_id),
                resource_data={
                    "product_name": record.product_name if record else None,
                    "quantity_sold": record.quantity_sold if record else None,
                    "sale_date": record.date.isoformat() if record and record.date else None
                } if record else None,
                description=f"Deleted sales record for {record.product_name if record else 'unknown product'}",
                endpoint=f"/sales/{record_id}",
                method="DELETE"
            )
        except Exception as audit_error:
            logger.warning("Failed to log audit event", error=str(audit_error))

        logger.info("Deleted sales record", record_id=record_id, tenant_id=tenant_id)
        return {"message": "Sales record deleted successfully"}

    except ValueError as ve:
        logger.warning("Error deleting sales record", error=str(ve), record_id=record_id)
        raise HTTPException(status_code=400, detail=str(ve))
    except HTTPException:
        raise
    except Exception as e:
        logger.error("Failed to delete sales record", error=str(e), record_id=record_id, tenant_id=tenant_id)
        raise HTTPException(status_code=500, detail=f"Failed to delete sales record: {str(e)}")


@router.get(
    route_builder.build_base_route("categories"),
    response_model=List[str]
)
async def get_product_categories(
    tenant_id: UUID = Path(..., description="Tenant ID"),
    sales_service: SalesService = Depends(get_sales_service)
):
    """Get distinct product categories from sales data"""
    try:
        categories = await sales_service.get_product_categories(tenant_id)
        return categories

    except Exception as e:
        logger.error("Failed to get product categories", error=str(e), tenant_id=tenant_id)
        raise HTTPException(status_code=500, detail=f"Failed to get product categories: {str(e)}")
