"""Models for Autarco."""

from __future__ import annotations

from dataclasses import dataclass, field
from datetime import date, datetime
from typing import Any

from mashumaro import DataClassDictMixin, field_options
from mashumaro.config import BaseConfig
from mashumaro.mixins.orjson import DataClassORJSONMixin
from mashumaro.types import SerializationStrategy


class DateStrategy(SerializationStrategy):
    """Date serialization strategy to handle the date format."""

    def serialize(self, value: date) -> str:
        """Serialize date to string."""
        return value.strftime("%Y-%m-%d")

    def deserialize(self, value: str) -> date:
        """Deserialize string to date."""
        return date.fromisoformat(value)


@dataclass
class PowerResponse(DataClassORJSONMixin):
    """Object representing an Power Response model from the API."""

    inverters: dict[str, Inverter]
    stats: Stats


@dataclass
class EnergyResponse(DataClassORJSONMixin):
    """Object representing an Energy Response model response from the API."""

    stats: Stats


@dataclass
class AccountResponse(DataClassORJSONMixin):
    """Object representing an Account Response model from the API."""

    sites: list[AccountSite] = field(metadata=field_options(alias="data"))


@dataclass
class AccountSite(DataClassORJSONMixin):
    """Object representing an Account Site model response from the API."""

    site_id: int
    public_key: str
    system_name: str = field(metadata=field_options(alias="name"))
    retailer: str = field(metadata=field_options(alias="name_retailer"))
    health: str


@dataclass
class Inverter(DataClassORJSONMixin):
    """Object representing an Inverter model response from the API."""

    serial_number: str = field(metadata=field_options(alias="sn"))
    out_ac_power: int
    out_ac_energy_total: int
    grid_turned_off: bool
    health: str


@dataclass
class Solar(DataClassDictMixin):
    """Object representing a Solar model response from the API."""

    power_production: int = field(metadata=field_options(alias="pv_now"))
    energy_production_today: int = field(metadata=field_options(alias="pv_today"))
    energy_production_month: int = field(metadata=field_options(alias="pv_month"))
    energy_production_total: int = field(metadata=field_options(alias="pv_to_date"))


@dataclass
class Battery(DataClassDictMixin):
    """Object representing a Battery model response from the API."""

    # Power - Flow
    flow_now: int = field(metadata=field_options(alias="battery_now"))
    net_charged_now: int = field(
        metadata=field_options(alias="battery_net_charged_now")
    )
    state_of_charge: int = field(metadata=field_options(alias="battery_soc"))

    # Energy - Discharged
    discharged_today: int = field(
        metadata=field_options(alias="battery_discharged_today")
    )
    discharged_month: int = field(
        metadata=field_options(alias="battery_discharged_month")
    )
    discharged_total: int = field(
        metadata=field_options(alias="battery_discharged_to_date")
    )

    # Energy - Charged
    charged_today: int = field(metadata=field_options(alias="battery_charged_today"))
    charged_month: int = field(metadata=field_options(alias="battery_charged_month"))
    charged_total: int = field(metadata=field_options(alias="battery_charged_to_date"))


@dataclass
class Graphs(DataClassORJSONMixin):
    """Object representing Graphs model from the API."""

    pv_power: dict[str, dict[datetime, int | None]] | None = None
    pv_energy: dict[str, dict[date, int | None]] | None = None


@dataclass
class Stats(DataClassORJSONMixin):
    """Object representing the Stats model from the API."""

    graphs: Graphs
    kpis: dict[str, Any]

    @property
    def generate_power_stats_inverter(self) -> dict[str, list[dict[str, Any]]] | None:
        """Generate power statistics by inverter."""
        if self.graphs.pv_power:
            power_stats_by_inverter = {}
            for inverter_id, power_data in self.graphs.pv_power.items():
                stats_list = [
                    {"timestamp": timestamp, "power": power}
                    for timestamp, power in power_data.items()
                ]
                power_stats_by_inverter[inverter_id] = stats_list
            return power_stats_by_inverter
        return None

    @property
    def generate_energy_stats_inverter(self) -> dict[str, list[dict[str, Any]]] | None:
        """Generate energy statistics by inverter."""
        if self.graphs.pv_energy:
            energy_stats_by_inverter = {}
            for inverter_id, energy_data in self.graphs.pv_energy.items():
                stats_list = [
                    {"timestamp": date, "energy": energy}
                    for date, energy in energy_data.items()
                ]
                energy_stats_by_inverter[inverter_id] = stats_list
            return energy_stats_by_inverter
        return None


@dataclass
class Site(DataClassORJSONMixin):
    """Object representing an Site model response from the API."""

    # pylint: disable-next=too-few-public-methods
    class Config(BaseConfig):
        """Mashumaro configuration."""

        serialization_strategy = {date: DateStrategy()}  # noqa: RUF012
        serialize_by_alias = True

    public_key: str
    name: str
    address: Address

    # CO2 compensations
    co2_today: int
    co2_month: int
    co2_total: int = field(metadata=field_options(alias="co2_to_date"))

    # Energy consumption
    consumption_today: int
    consumption_month: int
    consumption_total: int = field(metadata=field_options(alias="consumption_to_date"))

    has_consumption_meter: bool
    has_battery: bool
    timezone: str
    created_at: date | None = field(
        metadata=field_options(alias="dt_created"), default=None
    )


@dataclass
class Address(DataClassORJSONMixin):
    """Object representing an Address model response from the API."""

    street: str | None = field(
        metadata=field_options(alias="address_line_1"), default=None
    )
    zip_code: str | None = field(metadata=field_options(alias="postcode"), default=None)
    city: str | None = field(default=None)
    country: str | None = field(default=None)
