"""
Mediaset EPG Scraper — fetches schedule data from Mediaset Infinity API.

Endpoint: https://api-ott-prod-fe.mediaset.net/PROD/play/feed/allListingFeedEpg/v2.0
Params: byListingTime={epoch_start}~{epoch_end}&byCallSign={channel_id}
Returns entries with listings containing: epgTitle, startTime, endTime (epoch ms),
program.thumbnails, description
"""
import logging
from datetime import date, datetime
from typing import List
from zoneinfo import ZoneInfo

from models import EPGEntry
import config
from scrapers.base_scraper import BaseScraper

logger = logging.getLogger(__name__)

ROME_TZ = ZoneInfo("Europe/Rome")


class MediasetScraper(BaseScraper):

    def get_provider_name(self) -> str:
        return "mediaset"

    def get_channels(self) -> dict:
        return config.MEDIASET_CHANNELS

    def fetch_channel_schedule(self, channel_id: str, channel_name: str,
                                target_date: date) -> List[EPGEntry]:
        # Start 4 hours before midnight of target date to catch overlapping programs
        from datetime import timedelta
        start_dt = datetime(
            target_date.year, target_date.month, target_date.day,
            0, 0, 0, tzinfo=ROME_TZ
        ) - timedelta(hours=4)
        
        # Get 32 hours to cover the full day plus late-night programs
        end_dt = start_dt + timedelta(hours=32)

        epoch_start = int(start_dt.timestamp() * 1000)
        epoch_end = int(end_dt.timestamp() * 1000)

        url = config.MEDIASET_BASE_URL.format(
            epoch_start=epoch_start,
            epoch_end=epoch_end,
            channel_id=channel_id,
        )

        data = self._make_request(url)

        # Navigate the response structure
        response = data.get("response", {})
        entries_list = response.get("entries", [])
        if not entries_list:
            return []

        listings = entries_list[0].get("listings", [])
        entries = []

        for listing in listings:
            try:
                entry = self._parse_listing(listing, channel_name)
                if entry:
                    entries.append(entry)
            except Exception as e:
                logger.debug(
                    f"[mediaset] Errore parsing listing "
                    f"'{listing.get('mediasetlisting$epgTitle', '?')}': {e}"
                )
                continue

        return entries

    def _parse_listing(self, listing: dict, channel_name: str) -> EPGEntry | None:
        title = listing.get("mediasetlisting$epgTitle", "")
        if not title:
            title = listing.get("description", "")
        if not title:
            return None

        # Times (epoch ms)
        start_ms = listing.get("startTime")
        end_ms = listing.get("endTime")
        if not start_ms:
            return None

        start_iso = EPGEntry.epoch_ms_to_iso(start_ms)
        end_iso = EPGEntry.epoch_ms_to_iso(end_ms) if end_ms else ""

        # Image from program thumbnails
        image = ""
        program = listing.get("program", {})
        thumbnails = program.get("thumbnails", {})

        # Prefer horizontal cover, fallback to keyframe poster
        for prefix in ["image_horizontal_cover", "image_keyframe_poster", "image_header_poster", "image_vertical", "img_s_master_boxart"]:
            for key, thumb in thumbnails.items():
                if key.startswith(prefix) and thumb.get("url"):
                    image = thumb["url"]
                    break
            if image:
                break

        # Description
        description = listing.get("description", "").strip()
        if not description:
            description = program.get("description", "").strip()

        # Category from program tags
        category = ""
        if program:
            genres = program.get("mediasetprogram$genres", [])
            if genres:
                category = genres[0]
            else:
                tags = program.get("tags", [])
                for tag in tags:
                    if tag.get("scheme") == "primaryGenre":
                        category = tag.get("title", "")
                        break
                if not category:
                    for tag in tags:
                        if tag.get("scheme") == "category":
                            category = tag.get("title", "")
                            break

        return EPGEntry(
            title=title,
            image=image,
            channel=channel_name,
            start=start_iso,
            end=end_iso,
            description=description,
            category=category,
        )
