from decimal import Decimal

from psycopg import Connection
from src.__types.index import Tenant
from src.domain.entities.attention import Attention, AttentionSeverity, AttentionType, LastMonthUsageParameters
from src.infrastructure.repositories.quota_repository import QuotaRepository
from src.infrastructure.repositories.quota_usage_repository import QuotaUsageRepository
from src.infrastructure.repositories.usage_event_repository import UsageEventRepository
from src.tracer import tracer


class AttentionUseCase:
    def __init__(
        self,
        quota_repository: QuotaRepository,
        usage_event_repository: UsageEventRepository,
        quota_usage_repository: QuotaUsageRepository,
    ) -> None:
        self.quota_repository = quota_repository
        self.usage_event_repository = usage_event_repository
        self.usage_repository = quota_usage_repository

    @classmethod
    def create(cls, tenant: Tenant, connection: Connection) -> "AttentionUseCase":
        return AttentionUseCase(
            quota_repository=QuotaRepository(tenant=tenant, connection=connection),
            usage_event_repository=UsageEventRepository(
                tenant=tenant,
                connection=connection,
            ),
            quota_usage_repository=QuotaUsageRepository(tenant=tenant, connection=connection),
        )

    @tracer.capture_method
    def get(self) -> list[Attention]:
        """アテンションを取得する"""
        # クォータの超過を確認
        quota = self.quota_repository.get()
        if quota.is_exceeded:
            # クォータが超過している場合は、重大度最大のアテンションを作成
            return [
                Attention(
                    severity=AttentionSeverity.HIGH,
                    type=AttentionType.EXCEEDED,
                ),
            ]

        # 前月のクォータ使用実績を確認
        last_month_usage = self.usage_repository.get_last_month_usage()

        # 前月の使用量が0の場合はアテンションを作成しない
        if last_month_usage == Decimal(0):
            return []

        # 前月の使用量がクォータの月当たり残量を超えているか確認
        # クォータの月当たり残量が前月の使用量を下回っている場合は、より重大度を上げる
        if quota.remaining_per_remaining_month < last_month_usage:
            return [
                Attention(
                    severity=AttentionSeverity.MEDIUM,
                    type=AttentionType.LAST_MONTH_USAGE,
                    parameters=LastMonthUsageParameters(
                        last_month_usage=last_month_usage,
                    ),
                ),
            ]

        return [
            Attention(
                severity=AttentionSeverity.LOW,
                type=AttentionType.LAST_MONTH_USAGE,
                parameters=LastMonthUsageParameters(
                    last_month_usage=last_month_usage,
                ),
            ),
        ]
