# app/modules/customers/services/admin_customer_service.py
"""
Admin customer management service.

Handles customer operations for admin users across all vendors.
"""

import logging
from typing import Any

from sqlalchemy import func
from sqlalchemy.orm import Session

from app.modules.customers.exceptions import CustomerNotFoundException
from app.modules.customers.models import Customer
from app.modules.tenancy.models import Vendor

logger = logging.getLogger(__name__)


class AdminCustomerService:
    """Service for admin-level customer management across vendors."""

    def list_customers(
        self,
        db: Session,
        vendor_id: int | None = None,
        search: str | None = None,
        is_active: bool | None = None,
        skip: int = 0,
        limit: int = 20,
    ) -> tuple[list[dict[str, Any]], int]:
        """
        Get paginated list of customers across all vendors.

        Args:
            db: Database session
            vendor_id: Optional vendor ID filter
            search: Search by email, name, or customer number
            is_active: Filter by active status
            skip: Number of records to skip
            limit: Maximum records to return

        Returns:
            Tuple of (customers list, total count)
        """
        # Build query
        query = db.query(Customer).join(Vendor, Customer.vendor_id == Vendor.id)

        # Apply filters
        if vendor_id:
            query = query.filter(Customer.vendor_id == vendor_id)

        if search:
            search_term = f"%{search}%"
            query = query.filter(
                (Customer.email.ilike(search_term))
                | (Customer.first_name.ilike(search_term))
                | (Customer.last_name.ilike(search_term))
                | (Customer.customer_number.ilike(search_term))
            )

        if is_active is not None:
            query = query.filter(Customer.is_active == is_active)

        # Get total count
        total = query.count()

        # Get paginated results with vendor info
        customers = (
            query.add_columns(Vendor.name.label("vendor_name"), Vendor.vendor_code)
            .order_by(Customer.created_at.desc())
            .offset(skip)
            .limit(limit)
            .all()
        )

        # Format response
        result = []
        for row in customers:
            customer = row[0]
            vendor_name = row[1]
            vendor_code = row[2]

            customer_dict = {
                "id": customer.id,
                "vendor_id": customer.vendor_id,
                "email": customer.email,
                "first_name": customer.first_name,
                "last_name": customer.last_name,
                "phone": customer.phone,
                "customer_number": customer.customer_number,
                "marketing_consent": customer.marketing_consent,
                "preferred_language": customer.preferred_language,
                "last_order_date": customer.last_order_date,
                "total_orders": customer.total_orders,
                "total_spent": float(customer.total_spent) if customer.total_spent else 0,
                "is_active": customer.is_active,
                "created_at": customer.created_at,
                "updated_at": customer.updated_at,
                "vendor_name": vendor_name,
                "vendor_code": vendor_code,
            }
            result.append(customer_dict)

        return result, total

    def get_customer_stats(
        self,
        db: Session,
        vendor_id: int | None = None,
    ) -> dict[str, Any]:
        """
        Get customer statistics.

        Args:
            db: Database session
            vendor_id: Optional vendor ID filter

        Returns:
            Dict with customer statistics
        """
        query = db.query(Customer)

        if vendor_id:
            query = query.filter(Customer.vendor_id == vendor_id)

        total = query.count()
        active = query.filter(Customer.is_active == True).count()  # noqa: E712
        inactive = query.filter(Customer.is_active == False).count()  # noqa: E712
        with_orders = query.filter(Customer.total_orders > 0).count()

        # Total spent across all customers
        total_spent_result = query.with_entities(func.sum(Customer.total_spent)).scalar()
        total_spent = float(total_spent_result) if total_spent_result else 0

        # Average order value
        total_orders_result = query.with_entities(func.sum(Customer.total_orders)).scalar()
        total_orders = int(total_orders_result) if total_orders_result else 0
        avg_order_value = total_spent / total_orders if total_orders > 0 else 0

        return {
            "total": total,
            "active": active,
            "inactive": inactive,
            "with_orders": with_orders,
            "total_spent": total_spent,
            "total_orders": total_orders,
            "avg_order_value": round(avg_order_value, 2),
        }

    def get_customer(
        self,
        db: Session,
        customer_id: int,
    ) -> dict[str, Any]:
        """
        Get customer details by ID.

        Args:
            db: Database session
            customer_id: Customer ID

        Returns:
            Customer dict with vendor info

        Raises:
            CustomerNotFoundException: If customer not found
        """
        result = (
            db.query(Customer)
            .join(Vendor, Customer.vendor_id == Vendor.id)
            .add_columns(Vendor.name.label("vendor_name"), Vendor.vendor_code)
            .filter(Customer.id == customer_id)
            .first()
        )

        if not result:
            raise CustomerNotFoundException(str(customer_id))

        customer = result[0]
        return {
            "id": customer.id,
            "vendor_id": customer.vendor_id,
            "email": customer.email,
            "first_name": customer.first_name,
            "last_name": customer.last_name,
            "phone": customer.phone,
            "customer_number": customer.customer_number,
            "marketing_consent": customer.marketing_consent,
            "preferred_language": customer.preferred_language,
            "last_order_date": customer.last_order_date,
            "total_orders": customer.total_orders,
            "total_spent": float(customer.total_spent) if customer.total_spent else 0,
            "is_active": customer.is_active,
            "created_at": customer.created_at,
            "updated_at": customer.updated_at,
            "vendor_name": result[1],
            "vendor_code": result[2],
        }

    def toggle_customer_status(
        self,
        db: Session,
        customer_id: int,
        admin_email: str,
    ) -> dict[str, Any]:
        """
        Toggle customer active status.

        Args:
            db: Database session
            customer_id: Customer ID
            admin_email: Admin user email for logging

        Returns:
            Dict with customer ID, new status, and message

        Raises:
            CustomerNotFoundException: If customer not found
        """
        customer = db.query(Customer).filter(Customer.id == customer_id).first()

        if not customer:
            raise CustomerNotFoundException(str(customer_id))

        customer.is_active = not customer.is_active
        db.flush()
        db.refresh(customer)

        status = "activated" if customer.is_active else "deactivated"
        logger.info(f"Customer {customer.email} {status} by admin {admin_email}")

        return {
            "id": customer.id,
            "is_active": customer.is_active,
            "message": f"Customer {status} successfully",
        }


# Singleton instance
admin_customer_service = AdminCustomerService()
