# app/modules/tenancy/services/tenancy_metrics.py
"""
Metrics provider for the tenancy module.

Provides metrics for:
- Store counts and status
- User counts and activation
- Team members (store users)
- Custom domains
"""

import logging
from typing import TYPE_CHECKING

from sqlalchemy import func
from sqlalchemy.orm import Session

from app.modules.contracts.metrics import (
    MetricsContext,
    MetricValue,
)

if TYPE_CHECKING:
    pass

logger = logging.getLogger(__name__)


class TenancyMetricsProvider:
    """
    Metrics provider for tenancy module.

    Provides store, user, and organizational metrics.
    """

    @property
    def metrics_category(self) -> str:
        return "tenancy"

    def get_store_metrics(
        self,
        db: Session,
        store_id: int,
        context: MetricsContext | None = None,
    ) -> list[MetricValue]:
        """
        Get metrics for a specific store.

        For stores, this provides:
        - Team member count
        - Custom domains count
        """
        from app.modules.tenancy.models import StoreDomain, StoreUser

        try:
            # Team members count
            team_count = (
                db.query(StoreUser)
                .filter(StoreUser.store_id == store_id, StoreUser.is_active == True)
                .count()
            )

            # Custom domains count
            domains_count = (
                db.query(StoreDomain)
                .filter(StoreDomain.store_id == store_id)
                .count()
            )

            # Verified domains count
            verified_domains_count = (
                db.query(StoreDomain)
                .filter(
                    StoreDomain.store_id == store_id,
                    StoreDomain.is_verified == True,
                )
                .count()
            )

            return [
                MetricValue(
                    key="tenancy.team_members",
                    value=team_count,
                    label="Team Members",
                    category="tenancy",
                    icon="users",
                    description="Active team members with access to this store",
                ),
                MetricValue(
                    key="tenancy.domains",
                    value=domains_count,
                    label="Custom Domains",
                    category="tenancy",
                    icon="globe",
                    description="Custom domains configured for this store",
                ),
                MetricValue(
                    key="tenancy.verified_domains",
                    value=verified_domains_count,
                    label="Verified Domains",
                    category="tenancy",
                    icon="check-circle",
                    description="Custom domains that have been verified",
                ),
            ]
        except Exception as e:
            logger.warning(f"Failed to get tenancy store metrics: {e}")
            return []

    def get_platform_metrics(
        self,
        db: Session,
        platform_id: int,
        context: MetricsContext | None = None,
    ) -> list[MetricValue]:
        """
        Get metrics aggregated for a platform.

        For platforms, this provides:
        - Total stores
        - Active stores
        - Verified stores
        - Total users
        - Active users
        """
        from app.modules.tenancy.models import (
            AdminPlatform,
            Merchant,
            Store,
            StorePlatform,
            StoreUser,
            User,
        )

        try:
            # Store metrics - using StorePlatform junction table
            # Get store IDs that are on this platform
            platform_store_ids = (
                db.query(StorePlatform.store_id)
                .filter(StorePlatform.platform_id == platform_id)
                .subquery()
            )

            total_stores = (
                db.query(Store)
                .filter(Store.id.in_(platform_store_ids))
                .count()
            )

            # Active stores on this platform (store active AND membership active)
            active_store_ids = (
                db.query(StorePlatform.store_id)
                .filter(
                    StorePlatform.platform_id == platform_id,
                    StorePlatform.is_active == True,
                )
                .subquery()
            )
            active_stores = (
                db.query(Store)
                .filter(
                    Store.id.in_(active_store_ids),
                    Store.is_active == True,
                )
                .count()
            )

            verified_stores = (
                db.query(Store)
                .filter(
                    Store.id.in_(platform_store_ids),
                    Store.is_verified == True,
                )
                .count()
            )

            pending_stores = (
                db.query(Store)
                .filter(
                    Store.id.in_(active_store_ids),
                    Store.is_active == True,
                    Store.is_verified == False,
                )
                .count()
            )

            inactive_stores = total_stores - active_stores

            # User metrics - using AdminPlatform junction table
            # Get user IDs that have access to this platform
            platform_user_ids = (
                db.query(AdminPlatform.user_id)
                .filter(
                    AdminPlatform.platform_id == platform_id,
                    AdminPlatform.is_active == True,
                )
                .subquery()
            )

            total_users = (
                db.query(User)
                .filter(User.id.in_(platform_user_ids))
                .count()
            )

            active_users = (
                db.query(User)
                .filter(
                    User.id.in_(platform_user_ids),
                    User.is_active == True,
                )
                .count()
            )

            admin_users = (
                db.query(User)
                .filter(
                    User.id.in_(platform_user_ids),
                    User.role.in_(["super_admin", "platform_admin"]),
                )
                .count()
            )

            inactive_users = total_users - active_users

            # Merchant user metrics
            # Owners: distinct users who own a merchant
            merchant_owners = (
                db.query(func.count(func.distinct(Merchant.owner_user_id))).scalar() or 0
            )

            # Team members: distinct StoreUser users who are NOT merchant owners
            team_members = (
                db.query(func.count(func.distinct(StoreUser.user_id)))
                .filter(
                    ~StoreUser.user_id.in_(db.query(Merchant.owner_user_id)),
                )
                .scalar() or 0
            )

            # Total: union of both sets (deduplicated)
            owner_ids = db.query(Merchant.owner_user_id).distinct()
            team_ids = db.query(StoreUser.user_id).distinct()
            merchant_users_total = (
                db.query(func.count(func.distinct(User.id)))
                .filter(User.id.in_(owner_ids.union(team_ids)))
                .scalar() or 0
            )
            merchant_users_active = (
                db.query(func.count(func.distinct(User.id)))
                .filter(
                    User.id.in_(owner_ids.union(team_ids)),
                    User.is_active == True,
                )
                .scalar() or 0
            )

            # Calculate rates
            verification_rate = (
                (verified_stores / total_stores * 100) if total_stores > 0 else 0
            )
            user_activation_rate = (
                (active_users / total_users * 100) if total_users > 0 else 0
            )

            return [
                # Store metrics
                MetricValue(
                    key="tenancy.total_stores",
                    value=total_stores,
                    label="Total Stores",
                    category="tenancy",
                    icon="store",
                    description="Total number of stores on this platform",
                ),
                MetricValue(
                    key="tenancy.active_stores",
                    value=active_stores,
                    label="Active Stores",
                    category="tenancy",
                    icon="check-circle",
                    description="Stores that are currently active",
                ),
                MetricValue(
                    key="tenancy.verified_stores",
                    value=verified_stores,
                    label="Verified Stores",
                    category="tenancy",
                    icon="badge-check",
                    description="Stores that have been verified",
                ),
                MetricValue(
                    key="tenancy.pending_stores",
                    value=pending_stores,
                    label="Pending Stores",
                    category="tenancy",
                    icon="clock",
                    description="Active stores pending verification",
                ),
                MetricValue(
                    key="tenancy.inactive_stores",
                    value=inactive_stores,
                    label="Inactive Stores",
                    category="tenancy",
                    icon="pause-circle",
                    description="Stores that are not currently active",
                ),
                MetricValue(
                    key="tenancy.store_verification_rate",
                    value=round(verification_rate, 1),
                    label="Verification Rate",
                    category="tenancy",
                    icon="percent",
                    unit="%",
                    description="Percentage of stores that are verified",
                ),
                # User metrics
                MetricValue(
                    key="tenancy.total_users",
                    value=total_users,
                    label="Total Users",
                    category="tenancy",
                    icon="users",
                    description="Total number of users on this platform",
                ),
                MetricValue(
                    key="tenancy.active_users",
                    value=active_users,
                    label="Active Users",
                    category="tenancy",
                    icon="user-check",
                    description="Users that are currently active",
                ),
                MetricValue(
                    key="tenancy.admin_users",
                    value=admin_users,
                    label="Admin Users",
                    category="tenancy",
                    icon="shield",
                    description="Users with admin role",
                ),
                MetricValue(
                    key="tenancy.inactive_users",
                    value=inactive_users,
                    label="Inactive Users",
                    category="tenancy",
                    icon="user-x",
                    description="Users that are not currently active",
                ),
                MetricValue(
                    key="tenancy.user_activation_rate",
                    value=round(user_activation_rate, 1),
                    label="User Activation Rate",
                    category="tenancy",
                    icon="percent",
                    unit="%",
                    description="Percentage of users that are active",
                ),
                # Merchant user metrics
                MetricValue(
                    key="tenancy.merchant_users_total",
                    value=merchant_users_total,
                    label="Total Merchant Users",
                    category="tenancy",
                    icon="users",
                    description="Total merchant-related users (owners and team members)",
                ),
                MetricValue(
                    key="tenancy.merchant_users_active",
                    value=merchant_users_active,
                    label="Active Merchant Users",
                    category="tenancy",
                    icon="user-check",
                    description="Active merchant users",
                ),
                MetricValue(
                    key="tenancy.merchant_owners",
                    value=merchant_owners,
                    label="Merchant Owners",
                    category="tenancy",
                    icon="office-building",
                    description="Distinct merchant owners",
                ),
                MetricValue(
                    key="tenancy.merchant_team_members",
                    value=team_members,
                    label="Team Members",
                    category="tenancy",
                    icon="user-group",
                    description="Distinct store team members",
                ),
            ]
        except Exception as e:
            logger.warning(f"Failed to get tenancy platform metrics: {e}")
            return []

    def get_merchant_metrics(
        self,
        db: Session,
        merchant_id: int,
        context: MetricsContext | None = None,
    ) -> list[MetricValue]:
        """
        Get metrics scoped to a specific merchant.

        Provides:
        - Total stores owned by this merchant
        - Active stores
        - Distinct active team members across all merchant stores
        """
        from app.modules.tenancy.models import Store, StoreUser

        try:
            total_stores = (
                db.query(Store)
                .filter(Store.merchant_id == merchant_id)
                .count()
            )

            active_stores = (
                db.query(Store)
                .filter(
                    Store.merchant_id == merchant_id,
                    Store.is_active == True,
                )
                .count()
            )

            # Distinct active team members across all merchant stores
            merchant_store_ids = (
                db.query(Store.id)
                .filter(Store.merchant_id == merchant_id)
                .subquery()
            )
            team_members = (
                db.query(func.count(func.distinct(StoreUser.user_id)))
                .filter(
                    StoreUser.store_id.in_(merchant_store_ids),
                    StoreUser.is_active == True,
                )
                .scalar()
                or 0
            )

            return [
                MetricValue(
                    key="tenancy.total_stores",
                    value=total_stores,
                    label="Total Stores",
                    category="tenancy",
                    icon="shopping-bag",
                    description="Total stores owned by this merchant",
                ),
                MetricValue(
                    key="tenancy.active_stores",
                    value=active_stores,
                    label="Active Stores",
                    category="tenancy",
                    icon="check-circle",
                    description="Active stores owned by this merchant",
                ),
                MetricValue(
                    key="tenancy.team_members",
                    value=team_members,
                    label="Team Members",
                    category="tenancy",
                    icon="users",
                    description="Distinct active team members across all stores",
                ),
            ]
        except Exception as e:
            logger.warning(f"Failed to get tenancy merchant metrics: {e}")
            return []


# Singleton instance
tenancy_metrics_provider = TenancyMetricsProvider()

__all__ = ["TenancyMetricsProvider", "tenancy_metrics_provider"]
