# -*- coding: utf-8 -*-
import re
import json
from typing import Optional
from lxml import etree
from urllib.parse import urljoin
from app.log import logger
from app.modules.indexer.parser import SiteSchema
from app.modules.indexer.parser import SiteParserBase
from app.utils.string import StringUtils


class NexusRabbitSiteUserInfo(SiteParserBase):
    schema = SiteSchema.NexusRabbit

    def _parse_site_page(self, html_text: str):
        html_text = self._prepare_html_text(html_text)

        user_detail = re.search(r"user.php\?id=(\d+)", html_text)

        if not (user_detail and user_detail.group().strip()):
            return

        self.userid = user_detail.group(1)
        self._user_detail_page = f"user.php?id={self.userid}"

        self._user_traffic_page = None

        self._torrent_seeding_page = "api/general"
        self._torrent_seeding_params = {
            "page": 1,
            "limit": 5000000,
            "action": "userTorrentsList",
            "data": {"type": "seeding", "id": int(self.userid)},
        }
        self._torrent_seeding_headers = {
            "Content-Type": "application/json",
            "Accept": "application/json, text/plain, */*",
            "X-Requested-With": "XMLHttpRequest",  # 必须要加上这一条，不然返回的是空数据
        }

        self._user_mail_unread_page = None
        self._sys_mail_unread_page = "api/general"
        self._mail_unread_params = {
            "page": 1,
            "limit": 5000000,
            "action": "getMessageIn",
        }
        self._mail_unread_headers = {
            "Content-Type": "application/json",
            "Accept": "application/json, text/plain, */*",
            "X-Requested-With": "XMLHttpRequest",
        }

    def _parse_user_torrent_seeding_info(
        self, html_text: str, multi_page: bool = False
    ) -> Optional[str]:
        """
        做种相关信息
        :param html_text:
        :param multi_page: 是否多页数据
        :return: 下页地址
        """

        try:
            torrents = json.loads(html_text).get("data", [])
        except Exception as e:
            logger.error(f"解析做种信息失败: {str(e)}")
            return None

        seeding_size = 0
        seeding_info = []

        for torrent in torrents:
            seeders = int(torrent.get("seeders", 0))
            size = StringUtils.num_filesize(torrent.get("size"))
            seeding_size += size
            seeding_info.append([seeders, size])

        self.seeding = len(torrents)
        self.seeding_size = seeding_size
        self.seeding_info = seeding_info

    def _parse_message_unread_links(
        self, html_text: str, msg_links: list
    ) -> str | None:
        unread_ids = []
        try:
            messages = json.loads(html_text).get("data", [])
        except Exception as e:
            logger.error(f"解析未读消息失败: {e}")
            return None
        for msg in messages:
            msg_id, msg_unread = msg.get("id"), msg.get("unread")
            if not (msg_id and msg_unread) or msg_unread == "no":
                continue
            unread_ids.append(msg_id)
            head, date, content = msg.get("subject"), msg.get("added"), msg.get("msg")
            if head and date and content:
                self.message_unread_contents.append((head, date, content))
        self.message_unread = len(unread_ids)
        if unread_ids:
            self._get_page_content(
                url=urljoin(self._base_url, "api/general?loading=true"),
                params={"action": "readMessage", "data": {"ids": unread_ids}},
                headers={
                    "Content-Type": "application/json",
                    "Accept": "application/json, text/plain, */*",
                    "X-Requested-With": "XMLHttpRequest",
                },
            )
        return None

    def _parse_user_base_info(self, html_text: str):
        """只有奶糖余额才需要在 base 中获取，其它均可以在详情页拿到"""
        html = etree.HTML(html_text)
        try:
            if not StringUtils.is_valid_html_element(html):
                return
            bonus = html.xpath(
                '//div[contains(text(), "奶糖余额")]/following-sibling::div[1]/text()'
            )
            if bonus:
                self.bonus = StringUtils.str_float(bonus[0].strip())
        finally:
            if html is not None:
                del html

    def _parse_user_detail_info(self, html_text: str):
        html = etree.HTML(html_text)
        try:
            if not StringUtils.is_valid_html_element(html):
                return
            # 缩小一下查找范围，所有的信息都在这个 div 里
            user_info = html.xpath('//div[contains(@class, "layui-hares-user-info-right")]')
            if not user_info:
                return
            user_info = user_info[0]
            # 用户名
            if username := user_info.xpath(
                './/span[contains(text(), "用户名")]/a/span/text()'
            ):
                self.username = username[0].strip()
            # 等级
            if user_level := user_info.xpath('.//span[contains(text(), "等级")]/b/text()'):
                self.user_level = user_level[0].strip()
            # 加入日期
            if join_date := user_info.xpath('.//span[contains(text(), "注册日期")]/text()'):
                join_date = join_date[0].strip().split("\r")[0].removeprefix("注册日期：")
                self.join_at = StringUtils.unify_datetime_str(join_date)
            # 上传量
            if upload := user_info.xpath('.//span[contains(text(), "上传量")]/text()'):
                self.upload = StringUtils.num_filesize(
                    upload[0].strip().removeprefix("上传量：")
                )
            # 下载量
            if download := user_info.xpath('.//span[contains(text(), "下载量")]/text()'):
                self.download = StringUtils.num_filesize(
                    download[0].strip().removeprefix("下载量：")
                )
            # 分享率
            if ratio := user_info.xpath('.//span[contains(text(), "分享率")]/em/text()'):
                self.ratio = StringUtils.str_float(ratio[0].strip())
        finally:
            if html is not None:
                del html

    def _parse_message_content(self, html_text):
        """
        解析短消息内容，已经在 _parse_message_unread_links 内实现，重载防止 abstractmethod 报错
        :param html_text:
        :return:  head: message, date: time, content: message content
        """
        pass

    def _parse_user_traffic_info(self, html_text: str):
        """
        解析用户的上传，下载，分享率等信息，已经在 _parse_user_detail_info 内实现，重载防止 abstractmethod 报错
        :param html_text:
        :return:
        """
        pass
