from __future__ import annotations

from decimal import Decimal, ROUND_HALF_UP
from typing import Any

from market_api.db.sql import qualify_table, quote_identifier
from market_api.tender.common import (
    TenderAggregate,
    build_scope_filter,
    format_growth,
    format_yi_yuan,
    normalize_month,
)


GOVERNMENT_CATEGORY = "政府"
ENTERPRISE_CATEGORY = "企业"
VALID_CATEGORIES = {GOVERNMENT_CATEGORY, ENTERPRISE_CATEGORY}


class TenderClassRepository:
    def __init__(self, conn: Any, schema: str):
        self.conn = conn
        self.schema = schema

    def aggregate(
        self,
        year: int,
        months: list[int],
        scope_filter: tuple[str, str] | None,
        category: str | None,
    ) -> TenderAggregate:
        if not months:
            raise ValueError("统计月份不能为空")
        if category is not None and category not in VALID_CATEGORIES:
            raise ValueError("分类必须是 政府 或 企业")

        month_placeholders = ", ".join(["%s"] * len(months))
        where_parts = [
            f"{quote_identifier('年份')} = %s",
            f"{quote_identifier('月份')} IN ({month_placeholders})",
        ]
        params: list[object] = [year, *[f"{month}月" for month in months]]

        if scope_filter is not None:
            column_name, scope_value = scope_filter
            where_parts.append(f"{quote_identifier(column_name)} = %s")
            params.append(scope_value)

        if category is not None:
            where_parts.append(f"{quote_identifier('分类')} = %s")
            params.append(category)

        sql = (
            "SELECT COUNT(*) AS tender_count, "
            f"COALESCE(SUM({quote_identifier('预算金额_万元')}), 0) AS amount_wan "
            f"FROM {qualify_table(self.schema, '公开市场招标数据')} "
            f"WHERE {' AND '.join(where_parts)}"
        )

        with self.conn.cursor() as cursor:
            cursor.execute(sql, params)
            row = cursor.fetchone()

        if row is None:
            return TenderAggregate(0, Decimal("0"))
        count, amount_wan = row
        return TenderAggregate(int(count or 0), Decimal(str(amount_wan or 0)))


def _share(value: Decimal | int, total: Decimal | int) -> Decimal | None:
    total_value = Decimal(str(total))
    if total_value == 0:
        return None
    return Decimal(str(value)) / total_value * Decimal("100")


def _format_share(value: Decimal | None) -> str:
    if value is None:
        return "/"
    rounded = value.quantize(Decimal("0.1"), rounding=ROUND_HALF_UP)
    return f"{rounded:.1f}%"


def _category_report_row(
    current: TenderAggregate,
    total: TenderAggregate,
    previous: TenderAggregate | None,
) -> dict[str, object]:
    if previous is None:
        count_growth = "/"
        amount_growth = "/"
    else:
        count_growth = format_growth(current.count, previous.count)
        amount_growth = format_growth(current.amount_wan, previous.amount_wan)

    return {
        "招标次数": current.count,
        "招标次数环比增幅": count_growth,
        "招标预算金额（亿元）": format_yi_yuan(current.amount_wan),
        "招标预算金额环比增幅": amount_growth,
        "招标次数占比": _format_share(_share(current.count, total.count)),
        "招标金额占比": _format_share(_share(current.amount_wan, total.amount_wan)),
    }


def build_tender_class_summary(
    repository: object,
    year: int,
    month: str | int,
    scope: str,
    scope_value: str | None,
) -> dict[str, object]:
    month_number = normalize_month(month)
    normalized_scope_value = scope_value.strip() if scope_value is not None else None
    scope_filter = build_scope_filter(scope, normalized_scope_value)
    cumulative_months = list(range(1, month_number + 1))

    total = repository.aggregate(year, cumulative_months, scope_filter, None)
    government = repository.aggregate(year, cumulative_months, scope_filter, GOVERNMENT_CATEGORY)
    enterprise = repository.aggregate(year, cumulative_months, scope_filter, ENTERPRISE_CATEGORY)
    if month_number == 1:
        previous_government = None
        previous_enterprise = None
    else:
        previous_cumulative_months = list(range(1, month_number))
        previous_government = repository.aggregate(
            year,
            previous_cumulative_months,
            scope_filter,
            GOVERNMENT_CATEGORY,
        )
        previous_enterprise = repository.aggregate(
            year,
            previous_cumulative_months,
            scope_filter,
            ENTERPRISE_CATEGORY,
        )

    return {
        "统计年份": year,
        "统计月份": f"{month_number}月",
        "统计方式": scope,
        "统计参数": normalized_scope_value if scope != "上海" else None,
        "政府侧累计数据": _category_report_row(government, total, previous_government),
        "企业侧累计数据": _category_report_row(enterprise, total, previous_enterprise),
    }
