from collections.abc import Generator
from functools import lru_cache
from typing import Literal

from aumiao.utils import acquire
from aumiao.utils.decorator import singleton


@singleton
class DataFetcher:
	def __init__(self) -> None:
		# 初始化 acquire 对象
		self._client = acquire.CodeMaoClient()

	# 获取随机昵称
	def fetch_random_nickname(self) -> str:
		# 发送 GET 请求, 获取随机昵称
		response = self._client.send_request(
			method="GET",
			endpoint="/api/user/random/nickname",
		)
		# 返回响应中的昵称
		return response.json()["data"]["nickname"]

	# 获取新消息数量
	def fetch_message_count(self, method: Literal["web", "nemo"]) -> dict:
		# 根据方法选择不同的 url
		if method == "web":
			url = "/web/message-record/count"
		elif method == "nemo":
			url = "/nemo/v2/user/message/count"
		else:
			msg = "不支持的方法"
			raise ValueError(msg)
		# 发送 GET 请求, 获取新消息数量
		record = self._client.send_request(
			endpoint=url,
			method="GET",
		)
		# 返回响应
		return record.json()

	# 获取回复
	def fetch_replies(
		self,
		types: Literal["LIKE_FORK", "COMMENT_REPLY", "SYSTEM"],
		limit: int = 15,
		offset: int = 0,
	) -> dict:
		# 构造参数
		params = {"query_type": types, "limit": limit, "offset": offset}
		# 获取前 * 个回复
		response = self._client.send_request(
			endpoint="/web/message-record",
			method="GET",
			params=params,
		)
		return response.json()

	def fetch_replies_gen(
		self,
		types: Literal["LIKE_FORK", "COMMENT_REPLY", "SYSTEM"],
		limit: int = 15,
	) -> Generator[dict]:
		params = {"query_type": types}
		return self._client.fetch_paginated_data(
			endpoint="/web/message-record",
			params=params,
			method="GET",
			limit=limit,
			pagination_method="offset",
			total_key="total",
			data_key="items",
		)

	# 获取 nemo 消息
	def fetch_nemo_messages(self, types: Literal["fork", "like"]) -> dict:
		extra_url = 1 if types == "like" else 3
		url = f"/nemo/v2/user/message/{extra_url}"
		response = self._client.send_request(endpoint=url, method="GET")
		return response.json()

	# 获取点个猫更新
	def fetch_pickcat_update(self) -> dict:
		response = self._client.send_request(endpoint="https://update.codemao.cn/updatev2/appsdk", method="GET")
		return response.json()

	# 获取 kitten4 更新
	def fetch_kitten4_update(self) -> dict:
		time_stamp = self.fetch_current_timestamp_10()["data"]
		params = {"TIME": time_stamp}
		response = self._client.send_request(endpoint="https://kn-cdn.codemao.cn/kitten4/application/kitten4_update_info.json", method="GET", params=params)
		return response.json()

	# 获取 kitten 更新
	def fetch_kitten_update(self) -> dict:
		time_stamp = self.fetch_current_timestamp_10()["data"]
		params = {"timeStamp": time_stamp}
		response = self._client.send_request(endpoint="https://kn-cdn.codemao.cn/application/kitten_update_info.json", method="GET", params=params)
		return response.json()

	# 获取海龟编辑器更新
	def fetch_wood_editor_update(self) -> dict:
		time_stamp = self.fetch_current_timestamp_10()["data"]
		params = {"timeStamp": time_stamp}
		response = self._client.send_request(endpoint="https://static-am.codemao.cn/wood/client/xp/prod/package.json", method="GET", params=params)
		return response.json()

	# 获取源码智造编辑器更新
	def fetch_matrix_editor_update(self) -> dict:
		time_stamp = self.fetch_current_timestamp_10()["data"]
		params = {"timeStamp": time_stamp}
		response = self._client.send_request(endpoint="https://public-static-edu.codemao.cn/matrix/publish/desktop_matrix.json", method="GET", params=params)
		return response.json()

	# 获取时间戳
	def fetch_current_timestamp_10(self) -> dict:
		response = self._client.send_request(endpoint="/coconut/clouddb/currentTime", method="GET")
		return response.json()

	def fetch_current_timestamp_13(self) -> dict:
		response = self._client.send_request(endpoint="https://time.codemao.cn/time/current", method="GET")
		return response.json()

	# 获取推荐头图
	def fetch_web_banners(
		self,
		types: (Literal["FLOAT_BANNER", "OFFICIAL", "CODE_TV", "WOKE_SHOP", "MATERIAL_NORMAL"] | None) = None,
	) -> dict:
		# 所有: 不设置 type, 首页:OFFICIAL, 工作室页:WORK_SHOP
		# 素材页:MATERIAL_NORMAL, 右下角浮动区域:FLOAT_BANNER, 编程 TV:CODE_TV
		params = {"type": types}
		response = self._client.send_request(endpoint="/web/banners/all", method="GET", params=params)
		return response.json()

	# 获取推荐头图
	def fetch_nemo_banners(self, types: Literal[1, 2, 3]) -> dict:
		# 1: 点个猫推荐页 2: 点个猫主题页 3: 点个猫课程页
		params = {"banner_type": types}
		response = self._client.send_request(endpoint="/nemo/v2/home/banners", method="GET", params=params)
		return response.json()

	# 获取举报类型
	@lru_cache  # noqa: B019
	def fetch_report_reasons(self) -> dict:
		response = self._client.send_request(endpoint="/web/reports/reasons/all", method="GET")
		return response.json()

	# 获取 nemo 配置
	# TODO@Aurzex: 待完善
	def _fetch_nemo_config(self) -> str:
		response = self._client.send_request(endpoint="https://nemo.codemao.cn/config", method="GET")
		return response.json()

	# 获取社区网络服务
	def fetch_community_config(self) -> dict:
		response = self._client.send_request(endpoint="https://c.codemao.cn/config", method="GET")
		return response.json()

	# 获取编程猫网络服务
	def fetch_client_config(self) -> dict:
		response = self._client.send_request(endpoint="https://player.codemao.cn/new/client_config.json", method="GET")
		return response.json()

	# 获取编程猫首页作品
	def fetch_recommended_works(self, types: Literal[1, 2]) -> dict:
		# 1 为点猫精选,2 为新作喵喵看
		params = {"type": types}
		response = self._client.send_request(
			endpoint="/creation-tools/v1/pc/home/recommend-work",
			method="GET",
			params=params,
		)
		return response.json()

	# 获取 nemo 端新作喵喵看作品
	def fetch_new_recommend_works(self, limit: int = 15, offset: int = 0) -> dict:
		params = {"limit": limit, "offset": offset}
		response = self._client.send_request(endpoint="/nemo/v3/new-recommend/more/list", method="GET", params=params)
		return response.json()

	# 获取编程猫 nemo 作品推荐
	def fetch_recommended_works_nemo(self) -> dict:
		response = self._client.send_request(endpoint="/nemo/v2/system/recommended/pool", method="GET")
		return response.json()

	# 获取编程猫首页推荐 channel
	def fetch_work_channels(self, types: Literal["KITTEN", "NEMO"]) -> dict:
		params = {"type": types}
		response = self._client.send_request(
			endpoint="/web/works/channels/list",
			method="GET",
			params=params,
		)
		return response.json()

	# 获取指定 channel
	def fetch_channel_works(self, channel_id: int, types: Literal["KITTEN", "NEMO"], limit: int = 5, page: int = 1) -> dict:
		params = {"type": types, "page": page, "limit": limit}
		response = self._client.send_request(
			endpoint=f"/web/works/channels/{channel_id}/works",
			method="GET",
			params=params,
		)
		return response.json()

	# 获取社区星推荐
	def fetch_recommended_users(self) -> dict:
		response = self._client.send_request(endpoint="/web/users/recommended", method="GET")
		return response.json()

	# 获取训练师小课堂
	def fetch_training_courses(self) -> dict:
		response = self._client.send_request(endpoint="https://backend.box3.fun/diversion/codemao/post", method="GET")
		return response.json()

	# 获取 KN 课程
	def fetch_kn_courses(self) -> dict:
		response = self._client.send_request(endpoint="/creation-tools/v1/home/especially/course", method="GET")
		return response.json()

	# 获取 KN 公开课
	def fetch_public_courses_gen(self, limit: int | None = 10) -> Generator[dict]:
		params = {"limit": 10, "offset": 0}
		return self._client.fetch_paginated_data(
			endpoint="https://api-creation.codemao.cn/neko/course/publish/list",
			params=params,
			limit=limit,
			total_key="total_course",
			# total_key 也可设置为 "course_page.total",
			data_key="course_page.items",
		)

	# 获取 KN 模板作品
	# subject_id 为一时返回基础指南, 为 2 时返回进阶指南
	def fetch_sample_works(self, subject_id: Literal[1, 2]) -> dict:
		params = {"subject_id": subject_id}
		response = self._client.send_request(endpoint="https://api-creation.codemao.cn/neko/sample/list", params=params, method="GET")
		return response.json()

	# 获取社区各个部分开启状态
	# TODO@Aurzex: 待完善
	def fetch_community_status(self, types: Literal["WEB_FORUM_STATUS", "WEB_FICTION_STATUS"]) -> dict:
		response = self._client.send_request(endpoint=f"/web/config/tab/on-off/status?config_type={types}", method="GET")
		return response.json()

	# 获取 kitten 编辑页面精选活动
	def fetch_kitten_activities(self) -> dict:
		response = self._client.send_request(
			endpoint="https://api-creation.codemao.cn/kitten/activity/choiceness/list",
			method="GET",
		)
		return response.json()

	# 获取 nemo 端教程合集
	def fetch_course_packages_gen(self, platform: int = 1, limit: int | None = 50) -> Generator[dict]:
		params = {"limit": 50, "offset": 0, "platform": platform}
		return self._client.fetch_paginated_data(
			endpoint="/creation-tools/v1/course/package/list",
			params=params,
			limit=limit,
		)

	# 获取 nemo 教程
	def fetch_course_details_gen(self, course_package_id: int, limit: int | None = 50) -> Generator[dict]:
		# course_package_id 由 fetch_course_packages_gen 中获取
		params = {
			"course_package_id": course_package_id,
			"limit": 50,
			"offset": 0,
		}
		return self._client.fetch_paginated_data(
			endpoint="/creation-tools/v1/course/list/search",
			params=params,
			data_key="course_page.items",
			limit=limit,
			# 参数中 total_key 也可用 total_course
		)

	# 获取教学计划
	# TODO @Aurzex: 未知
	def fetch_teaching_plans_gen(self, limit: int = 100) -> Generator[dict]:
		params = {"limit": limit, "offset": 0}
		return self._client.fetch_paginated_data(endpoint="https://api-creation.codemao.cn/neko/teaching-plan/list/team", params=params, limit=limit)

	def fetch_user_certificate_info(self, user_id: int) -> dict:
		params = {"user_id": user_id}
		response = self._client.send_request(endpoint="https://api-wechatsbp-codemaster.codemao.cn/user/info/certificate", params=params, method="GET")
		return response.json()

	# 获取未读板块消息数量
	# TODO @Aurzex: 功能待确认
	def fetch_board_unread_count(self, board_id: int) -> dict:
		response = self._client.send_request(method="GET", endpoint=f"/web/forums/boards/{board_id}/unread-count")
		return response.json()

	# 获取活动页面
	def fetch_studio_info(self, studio_id: int) -> dict:
		response = self._client.send_request(method="GET", endpoint=f"/web/studios/{studio_id}")
		return response.json()

	# 获取活动帖子
	def fetch_studio_posts_gen(self, studio_id: int, limit: int | None = 24) -> Generator[dict]:
		params = {"limit": 50, "offset": 0, "studio_id": studio_id, "sort": "-created_at"}
		return self._client.fetch_paginated_data(
			endpoint="/web/forums/posts",
			params=params,
			limit=limit,
		)

	# 获取活动教程
	def fetch_studio_courses_gen(self, studio_id: int, limit: int | None = 100) -> Generator[dict]:
		params = {"limit": 50, "offset": 0}
		return self._client.fetch_paginated_data(
			endpoint=f"/web/studios/{studio_id}/courses",
			params=params,
			limit=limit,
		)

	# 获取活动作品
	def fetch_studio_works_gen(self, studio_id: int, limit: int | None = 24) -> Generator[dict]:
		params = {"limit": 50, "offset": 0, "sort": "-n_likes"}
		return self._client.fetch_paginated_data(
			endpoint=f"/web/studios/{studio_id}/works",
			params=params,
			limit=limit,
		)

	# 获取活动参加者
	def fetch_studio_participators_gen(self, studio_id: int, limit: int | None = 24) -> Generator[dict]:
		params = {"limit": 50, "offset": 0}
		return self._client.fetch_paginated_data(
			endpoint=f"/web/studios/{studio_id}/participators",
			params=params,
			limit=limit,
		)


@singleton
class UserAction:
	def __init__(self) -> None:
		# 初始化 CodeMaoClient 对象
		self._client = acquire.CodeMaoClient()

	# 签订友好协议
	def execute_sign_agreement(self) -> bool:
		response = self._client.send_request(endpoint="/nemo/v3/user/level/signature", method="POST")
		return response.status_code == acquire.HTTPStatus.OK.value

	# 获取用户协议
	def fetch_agreements(self) -> dict:
		response = self._client.send_request(endpoint="/tiger/v3/web/accounts/agreements", method="GET")
		return response.json()

	# 注册
	def create_account(
		self,
		identity: str,
		password: str,
		captcha: str,
		pid: str = "65edCTyg",
		agreement_ids: list = [186, 13],
	) -> dict:
		data = {
			"identity": identity,
			"password": password,
			"captcha": captcha,
			"pid": pid,
			"agreement_ids": agreement_ids,
		}
		response = self._client.send_request(
			endpoint="/tiger/v3/web/accounts/register/phone/with-agreement",
			method="POST",
			payload=data,
		)
		return response.json()

	# 删除消息
	def delete_message(self, message_id: int) -> bool:
		response = self._client.send_request(
			endpoint=f"/web/message-record/{message_id}",
			method="DELETE",
		)
		return response.status_code == acquire.HTTPStatus.NO_CONTENT.value

	# 获取广播消息
	def fetch_broadcast_messages_gen(self, limit: int | None = 10, read_status: Literal["READ", "UNREAD"] = "UNREAD") -> Generator[dict]:
		params = {"limit": 1, "offset": 0, "read_status": read_status, "sort": "-created_at"}
		return self._client.fetch_paginated_data(
			endpoint="/web/message-record/broadcast",
			params=params,
			limit=limit,
		)
