import logging
from datetime import date, datetime, timedelta
from typing import List

from epg2xml.providers import EPGProgram, EPGProvider

log = logging.getLogger(__name__.rsplit(".", maxsplit=1)[-1].upper())


class SPOTV(EPGProvider):
    """EPGProvider for SPOTV

    데이터: jsonapi
    요청수: #days
    특이사항:
    - 5일치만 제공
    """

    referer = "https://www.spotvnow.co.kr/channel"
    title_regex = r"\s?(?:\[(.*?)\])?\s?(.*?)\s?(?:[\(<](.*)[\)>])?\s?(?:-(\d+))?\s?(?:<?([\d,]+)회>?)?\s?$"

    def get_svc_channels(self) -> List[dict]:
        url = "https://www.spotvnow.co.kr/api/v3/channel"
        return [
            {
                "Name": ch["name"],
                "ServiceId": ch["id"],
                "Icon_url": ch["logo"],
            }
            for ch in self.request(url)
        ]

    def __dt(self, dt: str) -> datetime:
        if not dt:
            return None
        if dt.endswith("24:00"):
            return datetime.strptime(dt.replace("24:00", "00:00"), "%Y-%m-%d %H:%M") + timedelta(days=1)
        return datetime.strptime(dt, "%Y-%m-%d %H:%M")

    def get_programs(self) -> None:
        max_ndays = 5
        if int(self.cfg["FETCH_LIMIT"]) > max_ndays:
            log.warning(
                """

***********************************************************************

%s는 당일포함 %d일치만 EPG를 제공하고 있습니다.

***********************************************************************
            """,
                self.provider_name,
                max_ndays,
            )
        data = []
        for nd in range(min(int(self.cfg["FETCH_LIMIT"]), max_ndays)):
            day = date.today() + timedelta(days=nd)
            url = "https://www.spotvnow.co.kr/api/v3/program/" + day.strftime("%Y-%m-%d")
            try:
                data.extend(self.request(url))
            except Exception:
                log.exception("데이터 가져오는 중 에러:")
                continue

        # 날짜의 경계에서 발생할 수 있는 중복 제거
        _data = []
        for _d in data:
            _d.pop("date", None)
            if _d not in _data:
                _data.append(_d)

        for idx, _ch in enumerate(self.req_channels):
            log.info("%03d/%03d %s", idx + 1, len(self.req_channels), _ch)
            try:
                _epgs = self.__epgs_of_channel(_ch.id, _data, _ch.svcid)
            except AssertionError as e:
                log.warning("%s: %s", e, _ch)
            except Exception:
                log.exception("프로그램 파싱 중 예외: %s", _ch)
            else:
                _ch.programs.extend(_epgs)

    def __epgs_of_channel(self, channelid: str, data: dict, svcid: str) -> List[EPGProgram]:
        programs = [x for x in data if x["channelId"] == svcid]
        assert programs, "EPG 정보가 없거나 없는 채널입니다"

        _epgs = []
        for p in programs:
            _epg = EPGProgram(channelid)
            _epg.title = p["title"]
            _epg.stime = self.__dt(p["startTime"])
            # 끝나는 시간이 없으면 해당일 자정으로 강제
            _epg.etime = self.__dt(p["endTime"]) or (_epg.stime.replace(hour=0, minute=0) + timedelta(days=1))
            if _epg.stime == _epg.etime:
                continue

            if m := self.title_regex.match(_epg.title):
                _epg.title = m.group(2)
                subs = []
                if prefix := m.group(1):
                    subs.append(prefix)
                if sub := m.group(3):
                    subs += [sub.replace(")(", ", ").replace(") (", ", ")]
                title_sub = ", ".join(subs)
                if num := m.group(4):
                    title_sub += f"-{num}"
                if title_sub:
                    _epg.title_sub = title_sub
                _epg.ep_num = m.group(5)
            if p["type"] == 300:
                # 100: live, 200: 본방송
                _epg.rebroadcast = True
            _epgs.append(_epg)
        return _epgs
