# Copyright (c) 2021, JINGROW
# For license information, please see license.txt

import os
import re
from string import ascii_letters, digits

import jingrow
from jingrow.model.page import Page

LICENSES = (
	"GNU Affero General Public License",
	"GNU General Public License",
	"MIT License",
)


class Package(Page):
	# begin: auto-generated types
	# This code is auto-generated. Do not modify anything in this block.

	from typing import TYPE_CHECKING

	if TYPE_CHECKING:
		from jingrow.types import DF

		license: DF.MarkdownEditor | None
		license_type: DF.Literal[
			"", "MIT License", "GNU General Public License", "GNU Affero General Public License"
		]
		package_name: DF.Data
		readme: DF.MarkdownEditor | None

	# end: auto-generated types
	def validate(self):
		if not self.package_name:
			self.package_name = self.name.lower().replace(" ", "-")

		allowed_characters = ascii_letters + digits + "-"
		if not all(c in allowed_characters for c in self.package_name):
			jingrow.throw("Package name can only contain letters, digits and hyphens")


@jingrow.whitelist()
def get_license_text(license_type: str) -> str | None:
	if license_type in LICENSES:
		with open(os.path.join(os.path.dirname(__file__), "licenses", license_type + ".md")) as textfile:
			return textfile.read()


@jingrow.whitelist()
def uninstall_package(package_name: str) -> dict:

	try:
		if not jingrow.db.exists("Package", package_name):
			return {"status": "error", "message": f"Package '{package_name}' not found"}
		
		# 获取所有 Package Release（在外层定义，以便后续使用）
		package_releases = jingrow.get_all("Package Release", filters={"package": package_name}, pluck="name")
		
		# 删除与 package 相关的 File 记录（会自动删除物理文件）
		try:
			files_to_delete = []
			
			# 查找关联到 Package Release 的文件
			for release_name in package_releases:
				files_to_delete.extend(
					jingrow.get_all("File", filters={"attached_to_pagetype": "Package Release", "attached_to_name": release_name}, pluck="name")
				)
			
			# 查找直接关联到 Package 的文件
			files_to_delete.extend(
				jingrow.get_all("File", filters={"attached_to_pagetype": "Package", "attached_to_name": package_name}, pluck="name")
			)
			
			# 通过文件名模式查找未关联的文件
			pattern = re.compile(rf"{re.escape(package_name)}.*\.(gz|tgz)$", re.IGNORECASE)
			potential_files = jingrow.get_all("File", filters={"file_name": ["like", f"%{package_name}%"]}, pluck="name")
			
			for file_name in potential_files:
				try:
					file_doc = jingrow.get_pg("File", file_name)
					if file_doc.file_name and pattern.search(file_doc.file_name):
						if (not file_doc.attached_to_pagetype or not file_doc.attached_to_name):
							files_to_delete.append(file_name)
				except (jingrow.DoesNotExistError, Exception):
					pass
			
			# 去重并删除文件
			for file_name in set(files_to_delete):
				try:
					jingrow.delete_pg("File", file_name, force=True)
				except Exception:
					pass
		except Exception:
			pass
		
		# 获取所有模块
		modules = jingrow.get_all("Module Def", filters={"package": package_name}, pluck="name")
		
		# 获取所有 PageType
		pagetypes = []
		for module in modules:
			pts = jingrow.get_all("PageType", filters={"module": module}, pluck="name")
			pagetypes.extend(pts)
		
		# 删除所有 PageType
		for pagetype in pagetypes:
			try:
				jingrow.delete_pg("PageType", pagetype, force=True)
			except Exception:
				pass
		
		# 删除所有 Module Def
		for module in modules:
			try:
				jingrow.delete_pg("Module Def", module, force=True)
			except Exception:
				pass
		
		# 删除 Package Release
		for release_name in package_releases:
			try:
				jingrow.delete_pg("Package Release", release_name, force=True)
			except Exception:
				pass
		
		# 最后删除 Package 本身
		jingrow.delete_pg("Package", package_name, force=True)
		
		return {
			"status": "success", 
			"message": f"Package '{package_name}' uninstalled successfully"
		}
		
	except Exception as e:
		return {"status": "error", "message": f"Failed to uninstall package: {str(e)}"}


@jingrow.whitelist()
def get_package_dependencies(package_name: str) -> dict:

	try:
		if not jingrow.db.exists("Package", package_name):
			return {"status": "error", "message": f"Package '{package_name}' not found"}
		
		modules = jingrow.get_all("Module Def", filters={"package": package_name}, pluck="name")
		
		pagetypes = []
		for module in modules:
			pts = jingrow.get_all("PageType", filters={"module": module}, pluck="name")
			pagetypes.extend(pts)
		
		releases = jingrow.get_all("Package Release", filters={"package": package_name}, pluck="name")
		
		return {
			"status": "success",
			"package_name": package_name,
			"modules": modules,
			"pagetypes": pagetypes,
			"releases": releases,
			"summary": {
				"modules_count": len(modules),
				"pagetypes_count": len(pagetypes),
				"releases_count": len(releases)
			}
		}
		
	except Exception as e:
		return {"status": "error", "message": f"Failed to get package dependencies: {str(e)}"}
