from __future__ import annotations

from typing import TYPE_CHECKING, Any, Dict, List, Optional

from cardog.types.market import (
    DemandMatrixResponse,
    LocalMarketResponse,
    MarketAnalysis,
    MarketBreakdown,
    MarketGeography,
    MarketOdometer,
    MarketOverview,
    MarketPosition,
    MarketPricing,
    MarketPulse,
    MarketTrends,
)

if TYPE_CHECKING:
    from cardog._base_client import AsyncAPIClient, SyncAPIClient


class SyncMarketResource:
    """Market analysis and pricing intelligence."""

    def __init__(self, client: SyncAPIClient) -> None:
        self._client = client

    def overview(self, make: str, model: str, year: int) -> MarketOverview:
        """Get market overview for a make/model/year cohort.

        Args:
            make: Vehicle make (e.g., "Honda").
            model: Vehicle model (e.g., "Civic").
            year: Model year (e.g., 2022).
        """
        return self._client._get(
            f"/market/{make}/{model}/{year}/overview", model=MarketOverview
        )

    def pricing(self, make: str, model: str, year: int) -> MarketPricing:
        """Get price distribution histogram for a cohort.

        Args:
            make: Vehicle make.
            model: Vehicle model.
            year: Model year.
        """
        return self._client._get(
            f"/market/{make}/{model}/{year}/pricing", model=MarketPricing
        )

    def breakdown(self, make: str, model: str, year: int) -> MarketBreakdown:
        """Get trim-level price breakdown for a cohort.

        Args:
            make: Vehicle make.
            model: Vehicle model.
            year: Model year.
        """
        return self._client._get(
            f"/market/{make}/{model}/{year}/breakdown", model=MarketBreakdown
        )

    def odometer(self, make: str, model: str, year: int) -> MarketOdometer:
        """Get odometer vs price correlation analysis.

        Args:
            make: Vehicle make.
            model: Vehicle model.
            year: Model year.
        """
        return self._client._get(
            f"/market/{make}/{model}/{year}/odometer", model=MarketOdometer
        )

    def geography(self, make: str, model: str, year: int) -> MarketGeography:
        """Get geographic market breakdown by region.

        Args:
            make: Vehicle make.
            model: Vehicle model.
            year: Model year.
        """
        return self._client._get(
            f"/market/{make}/{model}/{year}/geography", model=MarketGeography
        )

    def trends(
        self,
        make: str,
        model: str,
        year: int,
        *,
        period: Optional[str] = None,
    ) -> MarketTrends:
        """Get market trends over time.

        Args:
            make: Vehicle make.
            model: Vehicle model.
            year: Model year.
            period: Time granularity ("week" or "month").
        """
        return self._client._get(
            f"/market/{make}/{model}/{year}/trends",
            params={"period": period},
            model=MarketTrends,
        )

    def analysis(self, vin: str) -> MarketAnalysis:
        """Get comprehensive market analysis for a specific VIN.

        Args:
            vin: A 17-character VIN.
        """
        return self._client._get(f"/market/analysis/vin/{vin}", model=MarketAnalysis)

    def position(self, listing_id: str) -> MarketPosition:
        """Get a listing's market position relative to similar vehicles.

        Args:
            listing_id: The listing ID.
        """
        return self._client._get(
            f"/market/listings/{listing_id}/position", model=MarketPosition
        )

    def similar(
        self, listing_id: str, *, limit: int = 20
    ) -> List[MarketPosition]:
        """Find similar listings for comparison.

        Args:
            listing_id: The listing ID.
            limit: Maximum number of results (max 50).
        """
        return self._client._get(
            f"/market/listings/{listing_id}/similar", params={"limit": limit}
        )

    def pulse(
        self,
        *,
        active_only: Optional[bool] = None,
        days_cutoff: Optional[int] = None,
        max_top_makes: Optional[int] = None,
        max_top_models: Optional[int] = None,
        price_range_min: Optional[float] = None,
        price_range_max: Optional[float] = None,
        price_range_increment: Optional[float] = None,
    ) -> MarketPulse:
        """Get overall market pulse/overview with distributions.

        Args:
            active_only: Only include active listings.
            days_cutoff: Number of days to look back.
            max_top_makes: Limit number of top makes returned.
            max_top_models: Limit number of top models returned.
            price_range_min: Minimum price for distribution.
            price_range_max: Maximum price for distribution.
            price_range_increment: Price bucket size.
        """
        return self._client._get(
            "/market/overview",
            params={
                "activeOnly": active_only,
                "daysCutoff": days_cutoff,
                "maxTopMakes": max_top_makes,
                "maxTopModels": max_top_models,
                "priceRangeMin": price_range_min,
                "priceRangeMax": price_range_max,
                "priceRangeIncrement": price_range_increment,
            },
            model=MarketPulse,
        )

    def treemap(self, make: Optional[str] = None) -> Any:
        """Get market treemap visualization data.

        Args:
            make: Optional make to get model-level treemap.
        """
        path = f"/market/treemap/{make}" if make else "/market/treemap"
        return self._client._get(path)

    def local(
        self,
        make: str,
        model: str,
        year: int,
        *,
        lat: float,
        lng: float,
        radius: Optional[float] = None,
    ) -> LocalMarketResponse:
        """Get local market data scoped to a geographic area.

        Args:
            make: Vehicle make.
            model: Vehicle model.
            year: Model year.
            lat: Latitude of search center.
            lng: Longitude of search center.
            radius: Search radius in km (default 75).
        """
        return self._client._get(
            f"/market/{make}/{model}/{year}/local",
            params={"lat": lat, "lng": lng, "radius": radius},
            model=LocalMarketResponse,
        )

    def demand(self, make: str, model: str, year: int) -> DemandMatrixResponse:
        """Get demand matrix (price vs turn rate distribution).

        Args:
            make: Vehicle make.
            model: Vehicle model.
            year: Model year.
        """
        return self._client._get(
            f"/market/{make}/{model}/{year}/demand", model=DemandMatrixResponse
        )


class AsyncMarketResource:
    """Market analysis and pricing intelligence (async)."""

    def __init__(self, client: AsyncAPIClient) -> None:
        self._client = client

    async def overview(self, make: str, model: str, year: int) -> MarketOverview:
        """Get market overview for a make/model/year cohort."""
        return await self._client._get(
            f"/market/{make}/{model}/{year}/overview", model=MarketOverview
        )

    async def pricing(self, make: str, model: str, year: int) -> MarketPricing:
        """Get price distribution histogram for a cohort."""
        return await self._client._get(
            f"/market/{make}/{model}/{year}/pricing", model=MarketPricing
        )

    async def breakdown(self, make: str, model: str, year: int) -> MarketBreakdown:
        """Get trim-level price breakdown for a cohort."""
        return await self._client._get(
            f"/market/{make}/{model}/{year}/breakdown", model=MarketBreakdown
        )

    async def odometer(self, make: str, model: str, year: int) -> MarketOdometer:
        """Get odometer vs price correlation analysis."""
        return await self._client._get(
            f"/market/{make}/{model}/{year}/odometer", model=MarketOdometer
        )

    async def geography(self, make: str, model: str, year: int) -> MarketGeography:
        """Get geographic market breakdown by region."""
        return await self._client._get(
            f"/market/{make}/{model}/{year}/geography", model=MarketGeography
        )

    async def trends(
        self, make: str, model: str, year: int, *, period: Optional[str] = None
    ) -> MarketTrends:
        """Get market trends over time."""
        return await self._client._get(
            f"/market/{make}/{model}/{year}/trends",
            params={"period": period},
            model=MarketTrends,
        )

    async def analysis(self, vin: str) -> MarketAnalysis:
        """Get comprehensive market analysis for a specific VIN."""
        return await self._client._get(f"/market/analysis/vin/{vin}", model=MarketAnalysis)

    async def position(self, listing_id: str) -> MarketPosition:
        """Get a listing's market position relative to similar vehicles."""
        return await self._client._get(
            f"/market/listings/{listing_id}/position", model=MarketPosition
        )

    async def similar(self, listing_id: str, *, limit: int = 20) -> List[MarketPosition]:
        """Find similar listings for comparison."""
        return await self._client._get(
            f"/market/listings/{listing_id}/similar", params={"limit": limit}
        )

    async def pulse(
        self,
        *,
        active_only: Optional[bool] = None,
        days_cutoff: Optional[int] = None,
        max_top_makes: Optional[int] = None,
        max_top_models: Optional[int] = None,
        price_range_min: Optional[float] = None,
        price_range_max: Optional[float] = None,
        price_range_increment: Optional[float] = None,
    ) -> MarketPulse:
        """Get overall market pulse/overview with distributions."""
        return await self._client._get(
            "/market/overview",
            params={
                "activeOnly": active_only,
                "daysCutoff": days_cutoff,
                "maxTopMakes": max_top_makes,
                "maxTopModels": max_top_models,
                "priceRangeMin": price_range_min,
                "priceRangeMax": price_range_max,
                "priceRangeIncrement": price_range_increment,
            },
            model=MarketPulse,
        )

    async def treemap(self, make: Optional[str] = None) -> Any:
        """Get market treemap visualization data."""
        path = f"/market/treemap/{make}" if make else "/market/treemap"
        return await self._client._get(path)

    async def local(
        self,
        make: str,
        model: str,
        year: int,
        *,
        lat: float,
        lng: float,
        radius: Optional[float] = None,
    ) -> LocalMarketResponse:
        """Get local market data scoped to a geographic area."""
        return await self._client._get(
            f"/market/{make}/{model}/{year}/local",
            params={"lat": lat, "lng": lng, "radius": radius},
            model=LocalMarketResponse,
        )

    async def demand(self, make: str, model: str, year: int) -> DemandMatrixResponse:
        """Get demand matrix (price vs turn rate distribution)."""
        return await self._client._get(
            f"/market/{make}/{model}/{year}/demand", model=DemandMatrixResponse
        )
