"""Capdata Yield Curve Model."""

# pylint: disable=unused-argument

from datetime import datetime
from typing import Any, Literal
from typing import Optional

from capinvest_capdata.utils.data_path import bond_yield_curve_url, \
    ir_yield_curve_url
from capinvest_capdata.utils.helpers import post_by_token
from capinvest_core.provider.abstract.fetcher import Fetcher
from capinvest_core.provider.standard_models.yield_curve import (
    YieldCurveData,
    YieldCurveQueryParams,
)
from capinvest_core.provider.utils.errors import EmptyDataError
from pydantic import Field

from capinvest_capdata.utils.helpers import get_capdata_token


class CapdataYieldCurveQueryParams(YieldCurveQueryParams):
    """Capdata Yield Curve Query Params."""
    __json_schema_extra__ = {"date": {"multiple_items_allowed": False}}
    curve_code: str = Field(
        default="CN_TREAS_STD",
        description="curve code",
    )
    yield_curve_type: Literal["BOND", "IR"] = (
        Field(
            default="BOND",
            description="The yield curve type.",
        )
    )


class CapdataYieldCurveData(YieldCurveData):
    """Capdata Yield Curve Data."""


class CapdataYieldCurveFetcher(
    Fetcher[
        CapdataYieldCurveQueryParams,
        list[CapdataYieldCurveData],
    ]
):
    """Capdata Yield Curve Fetcher."""

    @staticmethod
    def transform_query(params: dict[str, Any]) -> CapdataYieldCurveQueryParams:
        """Transform query."""
        transformed_params = params
        if params.get("date") is None:
            transformed_params["date"] = datetime.now().date()
        return CapdataYieldCurveQueryParams(**transformed_params)

    @staticmethod
    async def aextract_data(
            query: CapdataYieldCurveQueryParams,
            credentials: Optional[dict[str, str]],
            **kwargs: Any,
    ) -> list[dict]:
        """Extract data."""
        # pylint: disable=import-outside-toplevel
        params = {
            "curve": query.curve_code,
            "start": query.date,
            "end": query.date,
            "freq": "d",
            "parseProto": True
        }
        if query.yield_curve_type == "BOND":
            results = post_by_token(bond_yield_curve_url, params, credentials)
        else:
            results = post_by_token(ir_yield_curve_url, params, credentials)
        if not results:
            raise EmptyDataError(
                f"{query.curve_code} No data found"
            )
        return results

    @staticmethod
    def transform_data(
            query: CapdataYieldCurveQueryParams,
            data: list[dict],
            **kwargs: Any,
    ) -> list[CapdataYieldCurveData]:
        """Transform data."""
        # pylint: disable=import-outside-toplevel
        if not data:
            raise EmptyDataError("The request was returned empty.")
        curve_data = data[0]['curve']['curve']
        date_list = curve_data['pillarDate']
        maturity_list = curve_data['pillarName']
        pillar_values = curve_data['pillarValues']['data']
        records = []
        for i in range(len(date_list)):
            records.append({
                "date": date_list[i],
                "maturity": maturity_list[i],
                "value": pillar_values[i]
            })
        return [CapdataYieldCurveData.model_validate(d) for d in records]
