from __future__ import annotations

from dataclasses import dataclass
from decimal import Decimal
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_yi_yuan,
    normalize_month,
)


CUSTOMER_139_VALUE = "是"
KEY_PROJECT_LIMIT = 10


@dataclass(frozen=True)
class Customer139KeyProject:
    unit: str | None
    title: str | None
    amount_wan: Decimal


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

    def aggregate_monthly(
        self,
        year: int,
        month: int,
        scope_filter: tuple[str, str] | None,
    ) -> TenderAggregate:
        where_parts = [
            f"{quote_identifier('年份')} = %s",
            f"{quote_identifier('月份')} = %s",
            f"{quote_identifier('是否139客户')} = %s",
        ]
        params: list[object] = [year, f"{month}月", CUSTOMER_139_VALUE]

        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)

        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 top_key_projects(
        self,
        year: int,
        month: int,
        scope_filter: tuple[str, str] | None,
        limit: int = KEY_PROJECT_LIMIT,
    ) -> list[Customer139KeyProject]:
        if limit <= 0:
            raise ValueError("重点项目数量必须大于 0")

        unit_column = quote_identifier("招标单位")
        title_column = quote_identifier("标题")
        amount_column = quote_identifier("预算金额_万元")
        where_parts = [
            f"{quote_identifier('年份')} = %s",
            f"{quote_identifier('月份')} = %s",
            f"{quote_identifier('是否139客户')} = %s",
        ]
        params: list[object] = [year, f"{month}月", CUSTOMER_139_VALUE]

        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)

        sql = (
            f"SELECT {unit_column}, {title_column}, "
            f"COALESCE({amount_column}, 0) AS amount_wan "
            f"FROM {qualify_table(self.schema, '公开市场招标数据')} "
            f"WHERE {' AND '.join(where_parts)} "
            f"ORDER BY amount_wan DESC, {title_column} ASC, {unit_column} ASC "
            f"LIMIT {limit}"
        )

        with self.conn.cursor() as cursor:
            cursor.execute(sql, params)
            rows = cursor.fetchall()

        return [
            Customer139KeyProject(
                None if unit is None else str(unit),
                None if title is None else str(title),
                Decimal(str(amount_wan or 0)),
            )
            for unit, title, amount_wan in rows
        ]


def format_wan_amount(amount: Decimal | int | float | None) -> str:
    value = Decimal("0") if amount is None else Decimal(str(amount))
    return format(value.normalize(), "f")


def _project_rows(projects: list[Customer139KeyProject]) -> list[dict[str, object]]:
    return [
        {
            "招标单位": project.unit,
            "项目名称": project.title,
            "招标预算金额（万元）": format_wan_amount(project.amount_wan),
        }
        for project in projects
    ]


def build_customer_139_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)
    aggregate = repository.aggregate_monthly(year, month_number, scope_filter)

    return {
        "统计年份": year,
        "统计月份": f"{month_number}月",
        "统计方式": scope,
        "统计参数": normalized_scope_value if scope != "上海" else None,
        "月度数据": {
            "招标次数": aggregate.count,
            "招标预算金额（亿元）": format_yi_yuan(aggregate.amount_wan),
        },
    }


def build_customer_139_key_projects_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)
    projects = repository.top_key_projects(year, month_number, scope_filter)

    return {
        "统计年份": year,
        "统计月份": f"{month_number}月",
        "统计方式": scope,
        "统计参数": normalized_scope_value if scope != "上海" else None,
        "重点项目": _project_rows(projects),
    }
