# -*- coding: utf-8 -*-
# Quasarr
# Project by https://github.com/rix1337

import json
import re
import time
from datetime import datetime, timedelta

import requests
from bs4 import BeautifulSoup

from quasarr.constants import SEARCH_CAT_SHOWS
from quasarr.providers.hostname_issues import clear_hostname_issue, mark_hostname_issue
from quasarr.providers.imdb_metadata import get_localized_title
from quasarr.providers.log import debug, error, trace, warn
from quasarr.providers.utils import (
    generate_download_link,
    get_base_search_category_id,
    is_imdb_id,
    is_valid_release,
    sanitize_string,
)

hostname = "dj"


def convert_to_rss_date(date_str):
    try:
        return datetime.fromisoformat(date_str.replace("Z", "+00:00")).strftime(
            "%a, %d %b %Y %H:%M:%S +0000"
        )
    except Exception:
        return ""


def dj_feed(shared_state, start_time, search_category):
    releases = []

    base_category = get_base_search_category_id(search_category)

    if base_category != SEARCH_CAT_SHOWS:  # Only TV supported
        debug(
            f"<d>Skipping <y>{search_category}</y> on <g>{hostname.upper()}</g> (category not supported)!</d>"
        )
        return releases

    sj_host = shared_state.values["config"]("Hostnames").get(hostname)
    password = sj_host

    headers = {"User-Agent": shared_state.values["user_agent"]}

    for days in range(4):
        url = f"https://{sj_host}/api/releases/latest/{days}"

        try:
            r = requests.get(url, headers=headers, timeout=30)
            r.raise_for_status()
            data = json.loads(r.content)
        except Exception as e:
            error(f"Feed load error: {e}")
            mark_hostname_issue(
                hostname, "feed", str(e) if "e" in dir() else "Error occurred"
            )
            return releases

        for release in data:
            try:
                title = release.get("name").rstrip(".")
                if not title:
                    continue

                published = convert_to_rss_date(release.get("createdAt"))
                if not published:
                    continue

                media = release.get("_media", {})
                slug = media.get("slug")
                if not slug:
                    continue

                series_url = f"https://{sj_host}/serie/{slug}"

                mb = 0
                size = 0
                imdb_id = None

                link = generate_download_link(
                    shared_state,
                    title,
                    series_url,
                    mb,
                    password,
                    imdb_id,
                    hostname,
                )

                releases.append(
                    {
                        "details": {
                            "title": title,
                            "hostname": hostname,
                            "imdb_id": imdb_id,
                            "link": link,
                            "size": size,
                            "date": published,
                            "source": series_url,
                        },
                        "type": "protected",
                    }
                )

            except Exception as e:
                warn(f"Feed parse error: {e}")
                continue

        if releases:
            break

    debug(f"Time taken: {time.time() - start_time:.2f}s")

    if releases:
        clear_hostname_issue(hostname)
    return releases


def dj_search(
    shared_state,
    start_time,
    search_category,
    search_string,
    season=None,
    episode=None,
):
    releases = []

    base_category = get_base_search_category_id(search_category)

    if base_category != SEARCH_CAT_SHOWS:  # Only TV supported
        debug(
            f"<d>Skipping <y>{search_category}</y> on <g>{hostname.upper()}</g> (category not supported)!</d>"
        )
        return releases

    dj_host = shared_state.values["config"]("Hostnames").get(hostname)
    password = dj_host

    imdb_id = is_imdb_id(search_string)
    if not imdb_id:
        error(f"No IMDb ID found in search string '{search_string}'")
        return releases

    localized_title = get_localized_title(shared_state, imdb_id, "de")
    if not localized_title:
        error(f"No localized title for IMDb {imdb_id}")
        return releases

    headers = {"User-Agent": shared_state.values["user_agent"]}
    search_url = f"https://{dj_host}/serie/search"
    params = {"q": localized_title}

    try:
        r = requests.get(search_url, headers=headers, params=params, timeout=10)
        soup = BeautifulSoup(r.content, "html.parser")
        results = soup.find_all("a", href=re.compile(r"^/serie/"))
    except Exception as e:
        error(f"Search load error: {e}")
        mark_hostname_issue(
            hostname, "search", str(e) if "e" in dir() else "Error occurred"
        )
        return releases

    one_hour_ago = (datetime.now() - timedelta(hours=1)).strftime("%Y-%m-%d %H:%M:%S")
    sanitized_search_string = sanitize_string(localized_title)

    for result in results:
        try:
            result_title = result.get_text(strip=True)

            sanitized_title = sanitize_string(result_title)

            if not re.search(
                rf"\b{re.escape(sanitized_search_string)}\b", sanitized_title
            ):
                trace(
                    f"Search string '{localized_title}' doesn't match '{result_title}'"
                )
                continue

            trace(
                f"Matched search string '{localized_title}' with result '{result_title}'"
            )

            series_url = f"https://{dj_host}{result['href']}"

            r = requests.get(series_url, headers=headers, timeout=10)
            media_id_match = re.search(r'data-mediaid="([^"]+)"', r.text)
            if not media_id_match:
                warn(f"No media id for {result_title}")
                continue

            media_id = media_id_match.group(1)
            api_url = f"https://{dj_host}/api/media/{media_id}/releases"

            r = requests.get(api_url, headers=headers, timeout=10)
            r.raise_for_status()
            data = json.loads(r.content)

            for season_block in data.values():
                for item in season_block.get("items", []):
                    title = item.get("name").rstrip(".")
                    if not title:
                        continue

                    if not is_valid_release(
                        title, base_category, search_string, season, episode
                    ):
                        continue

                    published = convert_to_rss_date(item.get("createdAt"))
                    if not published:
                        debug(f"No published date for {title}")
                        published = one_hour_ago

                    mb = 0
                    size = 0

                    link = generate_download_link(
                        shared_state,
                        title,
                        series_url,
                        mb,
                        password,
                        imdb_id,
                        hostname,
                    )

                    releases.append(
                        {
                            "details": {
                                "title": title,
                                "hostname": hostname,
                                "imdb_id": imdb_id,
                                "link": link,
                                "size": size,
                                "date": published,
                                "source": series_url,
                            },
                            "type": "protected",
                        }
                    )

        except Exception as e:
            warn(f"Search parse error: {e}")
            continue

    debug(f"Time taken: {time.time() - start_time:.2f}s")

    if releases:
        clear_hostname_issue(hostname)
    return releases
