import datetime
import json
import logging
from typing import Any

from bs4 import BeautifulSoup
from fastapi import HTTPException, status

from gallery.sketch.source import ApiSource
from gallery.sketch.weather.api import WeatherApi
from gallery.sketch.weather.model import Location, WeatherResponse, WeatherValue

from . import datehelp
from .parser import DAYS_PARSER, LOCATION_PARSER, ONE_DAY_PARSER, ROW_PARSERS

logger = logging.getLogger("gismeteo")


class GismeteoApi(WeatherApi):
    PROVIDER = "gismeteo"
    SOURCE = ApiSource(
        "https://www.gismeteo.ru",
        cookies={
            "cf_clearance": (
                "zPj8qeaYZWp5BUZsWIRD7kd32s59IDWWaVvD7GGf6b4-1724254262-1.2.1.1-"
                "R1PaHoqlm4OEgHfrOg6oAJmVmFJ7053JI_QDjIFlCAmbNY0oyw1J4QtgmEkAkTWF4C99X5hpXmZB2en."
                "9Ey3NL0kzaE10UGBHPli5OLxHNKC3wQ34xmxTxg6GcKouXOPRgqo92lVRpQP7ghvDmvvT_"
                "S6YXDbRonkamptWhZiAsIhsnIQg2Mt7Lk1fxSEVbaey_RXVQBvaR2ofiFgIavcbQPRFSvJ."
                "Ct_FujmymTAZWh1XHTptK32kur81NXyPuARThetOKQm8AklaMa855Oom6Bms1a4F9b0yEHSd2inA4j3FR7uauu8hhwO0Z2goa3."
                "ktpXXAQLz6dm.fBEWIHD7wooda15X57tCcDOely4hxhO4LK2lIH6TbOr."
                "rZQAiRRhltHiCizP1Ou2SiF_81lb1umoDh739tQD1cnw_USnL."
                "JwTHvkB00ZnaHRMi4FCBrsKIE0NxJO6kiv1QANqumzf5.8_pSIGRo2cKeO8xCydduDNFbStdOmLR6FU7ZKqVu"
            )
        },
    )

    def _parse_oneday(self, date: datetime.date, data: str) -> WeatherResponse:
        result: list[dict[str, Any]] = []
        soup = BeautifulSoup(data, features="html.parser")
        location = LOCATION_PARSER.parse_location(data)
        widget = ONE_DAY_PARSER.parse_widget(soup)
        for parser in ROW_PARSERS:
            for index, value in enumerate(parser.parse_row(widget)):
                while len(result) < index + 1:
                    result.append({})
                result[index][parser.KEY] = value
        values = [WeatherValue(**item) for item in result]
        return WeatherResponse(
            location=location or "n/a",
            date=date,
            period="day",
            values=values,
        )

    def _parse_manydays(self, data: str) -> WeatherResponse:
        result: list[dict[str, Any]] = []
        soup = BeautifulSoup(data, features="html.parser")
        location = LOCATION_PARSER.parse_location(data)
        widget = DAYS_PARSER.parse_widget(soup)
        for parser in ROW_PARSERS:
            for index, value in enumerate(parser.parse_row(widget)):
                while len(result) < index + 1:
                    result.append({})
                result[index][parser.KEY] = value
        values = [WeatherValue(**item) for item in result]
        return WeatherResponse(
            location=location or "n/a",
            date=datetime.date.today(),
            period="days",
            values=values,
        )

    async def find_locations(self, query: str) -> list[Location]:
        geo = "ru"
        latitude = 52.968498
        longitude = 36.0695
        data = json.loads(
            await self.SOURCE.request(
                f"mq/city/q/?q={query}&geo={geo}&latitude={latitude}&longitude={longitude}&limit=10"
            )
        )
        result = []
        for item in data["data"]:
            result.append(
                Location(
                    id=f"{item['slug']}-{item['id']}",
                    name=item["translations"]["kk"]["city"]["name"],
                    provider=self.provider,
                    lat=item["coordinates"]["latitude"],
                    lon=item["coordinates"]["longitude"],
                    country=item["translations"]["kk"]["country"]["name"],
                    country_code=item["country"]["code"].lower(),
                    district=(
                        item["translations"]["kk"]["district"]["name"] if item["translations"]["kk"]["district"] else ""
                    ),
                    subdistrict=(
                        item["translations"]["kk"]["subdistrict"]["name"]
                        if "subdistrict" in item["translations"]["kk"]
                        else ""
                    ),
                )
            )
        return result

    async def get_day(self, location_id: str, date: datetime.date) -> WeatherResponse:
        max_date = datetime.date.today() + datetime.timedelta(days=9)
        if date > max_date:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST, detail={"max_date": max_date.strftime("%Y-%m-%d")}
            )
        data = await self.SOURCE.request(f"weather-{location_id}/{datehelp.dump(date)}")
        return self._parse_oneday(date, data)

    async def get_days(self, location_id: str, days: int) -> WeatherResponse:
        data = await self.SOURCE.request(f"weather-{location_id}/{days}-days")
        return self._parse_manydays(data)
