"""Etherscan data provider for Ethereum on-chain data."""

from typing import Any

from .base import Provider, ProviderData


class EtherscanData(ProviderData):
    """Etherscan specific data."""

    provider: str = "etherscan"
    # Gas metrics
    gas_price_gwei: float | None = None
    gas_price_fast: float | None = None
    gas_price_slow: float | None = None

    # Network stats
    total_transactions_24h: int | None = None
    avg_block_time: float | None = None

    # ETH price (from Etherscan)
    eth_price_usd: float | None = None
    eth_price_btc: float | None = None

    # Supply
    eth_supply: float | None = None
    eth2_staking: float | None = None


class EtherscanProvider(Provider):
    """Etherscan API provider for Ethereum on-chain data."""

    name = "etherscan"
    base_url = "https://api.etherscan.io/api"
    requires_auth = True

    async def fetch_data(self, symbol: str) -> EtherscanData:
        """Fetch Ethereum network data."""
        if symbol.upper() not in ["ETH", "ETHEREUM"]:
            return EtherscanData(
                symbol=symbol.upper(),
                raw_data={"error": "Only ETH supported"},
            )

        try:
            # Gas oracle
            gas_data = await self._get_gas_oracle()

            # ETH price
            price_data = await self._get_eth_price()

            # ETH supply
            supply_data = await self._get_eth_supply()

            return EtherscanData(
                symbol="ETH",
                gas_price_gwei=gas_data.get("ProposeGasPrice"),
                gas_price_fast=gas_data.get("FastGasPrice"),
                gas_price_slow=gas_data.get("SafeGasPrice"),
                eth_price_usd=price_data.get("ethusd"),
                eth_price_btc=price_data.get("ethbtc"),
                eth_supply=supply_data.get("supply"),
                raw_data={
                    "gas": gas_data,
                    "price": price_data,
                    "supply": supply_data,
                },
            )

        except Exception:
            return EtherscanData(symbol="ETH", raw_data={})

    async def _get_gas_oracle(self) -> dict[str, Any]:
        """Get current gas prices."""
        data = await self.get(
            "",
            params={
                "module": "gastracker",
                "action": "gasoracle",
                "apikey": self.api_key,
            },
        )
        result = data.get("result", {})
        if isinstance(result, dict):
            return {
                "SafeGasPrice": float(result.get("SafeGasPrice", 0)),
                "ProposeGasPrice": float(result.get("ProposeGasPrice", 0)),
                "FastGasPrice": float(result.get("FastGasPrice", 0)),
            }
        return {}

    async def _get_eth_price(self) -> dict[str, Any]:
        """Get ETH price."""
        data = await self.get(
            "",
            params={
                "module": "stats",
                "action": "ethprice",
                "apikey": self.api_key,
            },
        )
        result = data.get("result", {})
        if isinstance(result, dict):
            return {
                "ethusd": float(result.get("ethusd", 0)),
                "ethbtc": float(result.get("ethbtc", 0)),
            }
        return {}

    async def _get_eth_supply(self) -> dict[str, Any]:
        """Get ETH supply."""
        data = await self.get(
            "",
            params={
                "module": "stats",
                "action": "ethsupply",
                "apikey": self.api_key,
            },
        )
        result = data.get("result", "0")
        try:
            # Convert from Wei to ETH
            supply = float(result) / 1e18
            return {"supply": supply}
        except (ValueError, TypeError):
            return {}

    async def get_token_balance(
        self, address: str, contract_address: str
    ) -> float | None:
        """Get token balance for an address."""
        data = await self.get(
            "",
            params={
                "module": "account",
                "action": "tokenbalance",
                "contractaddress": contract_address,
                "address": address,
                "tag": "latest",
                "apikey": self.api_key,
            },
        )
        result = data.get("result", "0")
        try:
            return float(result)
        except (ValueError, TypeError):
            return None

    async def get_transactions(
        self, address: str, start_block: int = 0, end_block: int = 99999999
    ) -> list[dict]:
        """Get transactions for an address."""
        data = await self.get(
            "",
            params={
                "module": "account",
                "action": "txlist",
                "address": address,
                "startblock": start_block,
                "endblock": end_block,
                "sort": "desc",
                "apikey": self.api_key,
            },
        )
        return data.get("result", [])
