# -*- coding: utf-8 -*-

# Copyright 2025 Mike Fährmann
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.

"""Extractors for https://comick.io/"""

from .common import ChapterExtractor, MangaExtractor, Message
from .. import text
from ..cache import memcache

BASE_PATTERN = r"(?:https?://)?(?:www\.)?comick\.io"


class ComickBase():
    """Base class for comick.io extractors"""
    category = "comick"
    root = "https://comick.io"

    @memcache(keyarg=1)
    def _manga_info(self, slug):
        url = f"{self.root}/comic/{slug}"
        page = self.request(url).text
        data = self._extract_nextdata(page)
        props = data["props"]["pageProps"]
        comic = props["comic"]

        genre = []
        theme = []
        format = ""
        for item in comic["md_comic_md_genres"]:
            item = item["md_genres"]
            group = item["group"]
            if group == "Genre":
                genre.append(item["name"])
            elif group == "Theme":
                theme.append(item["name"])
            else:
                format = item["name"]

        if mu := comic["mu_comics"]:
            tags = [c["mu_categories"]["title"]
                    for c in mu["mu_comic_categories"]]
            publisher = [p["mu_publishers"]["title"]
                         for p in mu["mu_comic_publishers"]]
        else:
            tags = publisher = ()

        return {
            "manga": comic["title"],
            "manga_id": comic["id"],
            "manga_hid": comic["hid"],
            "manga_slug": slug,
            "manga_titles": [t["title"] for t in comic["md_titles"]],
            "artist": [a["name"] for a in props["artists"]],
            "author": [a["name"] for a in props["authors"]],
            "genre" : genre,
            "theme" : theme,
            "format": format,
            "tags"  : tags,
            "publisher": publisher,
            "published": text.parse_int(comic["year"]),
            "description": comic["desc"],
            "demographic": props["demographic"],
            "origin": comic["iso639_1"],
            "mature": props["matureContent"],
            "rating": comic["content_rating"],
            "rank"  : comic["follow_rank"],
            "score" : text.parse_float(comic["bayesian_rating"]),
            "status": "Complete" if comic["status"] == 2 else "Ongoing",
            "links" : comic["links"],
            "_build_id": data["buildId"],
        }

    def _chapter_info(self, manga, chstr):
        slug = manga['manga_slug']
        url = (f"{self.root}/_next/data/{manga['_build_id']}"
               f"/comic/{slug}/{chstr}.json")
        params = {"slug": slug, "chapter": chstr}
        return self.request_json(url, params=params)["pageProps"]


class ComickChapterExtractor(ComickBase, ChapterExtractor):
    """Extractor for comick.io manga chapters"""
    archive_fmt = "{chapter_hid}_{page}"
    pattern = BASE_PATTERN + r"/comic/([\w-]+)/(\w+-chapter-[^/?#]+)"
    example = "https://comick.io/comic/MANGA/ID-chapter-123-en"

    def metadata(self, page):
        slug, chstr = self.groups
        manga = self._manga_info(slug)
        props = self._chapter_info(manga, chstr)

        ch = props["chapter"]
        self._images = ch["md_images"]
        chapter, sep, minor = ch["chap"].partition(".")

        return {
            **manga,
            "title"   : props["chapTitle"],
            "volume"  : text.parse_int(ch["vol"]),
            "chapter" : text.parse_int(chapter),
            "chapter_minor" : sep + minor,
            "chapter_id"    : ch["id"],
            "chapter_hid"   : ch["hid"],
            "chapter_string": chstr,
            "group"   : ch["group_name"],
            "date"    : text.parse_datetime(
                ch["created_at"][:19], "%Y-%m-%dT%H:%M:%S"),
            "date_updated"  : text.parse_datetime(
                ch["updated_at"][:19], "%Y-%m-%dT%H:%M:%S"),
            "lang"    : ch["lang"],
        }

    def images(self, page):
        return [
            ("https://meo.comick.pictures/" + img["b2key"], {
                "width"    : img["w"],
                "height"   : img["h"],
                "size"     : img["s"],
                "optimized": img["optimized"],
            })
            for img in self._images
        ]


class ComickMangaExtractor(ComickBase, MangaExtractor):
    """Extractor for comick.io manga"""
    pattern = BASE_PATTERN + r"/comic/([\w-]+)/?(?:\?([^#]+))?"
    example = "https://comick.io/comic/MANGA"

    def items(self):
        slug = self.groups[0]
        manga = self._manga_info(slug)

        for ch in self.chapters(manga):
            url = (f"{self.root}/comic/{slug}"
                   f"/{ch['hid']}-chapter-{ch['chap']}-{ch['lang']}")

            ch.update(manga)
            chapter, sep, minor = ch["chap"].partition(".")
            ch["chapter"] = text.parse_int(chapter)
            ch["chapter_minor"] = sep + minor
            ch["_extractor"] = ComickChapterExtractor

            yield Message.Queue, url, ch

    def chapters(self, manga):
        info = True
        slug, query = self.groups

        url = f"https://api.comick.io/comic/{manga['manga_hid']}/chapters"
        headers = {
            "Origin": "https://comick.io",
            "Sec-Fetch-Dest": "empty",
            "Sec-Fetch-Mode": "cors",
            "Sec-Fetch-Site": "same-site",
        }

        query = text.parse_query(query)
        params = {"lang": query.get("lang") or None}
        params["page"] = page = text.parse_int(query.get("page"), 1)

        if date_order := query.get("date-order"):
            params["date-order"] = date_order
        elif chap_order := query.get("chap-order"):
            params["chap-order"] = chap_order
        else:
            params["chap-order"] = \
                "0" if self.config("chapter-reverse", False) else "1"

        group = query.get("group", None)
        if group == "0":
            group = None

        while True:
            data = self.request_json(url, params=params, headers=headers)
            limit = data["limit"]

            if info:
                info = False
                total = data["total"] - limit * page
                if total > limit:
                    self.log.info("Collecting %s chapters", total)

            if group is None:
                yield from data["chapters"]
            else:
                for ch in data["chapters"]:
                    if group in ch["group_name"]:
                        yield ch

            if data["total"] <= limit * page:
                return
            params["page"] = page = page + 1
