import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils import flt


class TaxPeriodClosingSettings(Document):
	def validate(self):
		self.validate_contradictions()
		if self.auto_detect_on_save and self.company:
			self.run_auto_detect()

	def validate_contradictions(self):
		"""Check for logical contradictions between settings."""

		# 1. Regime vs tax enables
		if self.default_tax_regime == "General (VAT + Profit)":
			if self.enable_simplified_tax:
				frappe.msgprint(
					_("You have selected 'General (VAT + Profit)' regime but also enabled "
					  "Simplified Tax. In the General regime, Simplified Tax is not applicable. "
					  "The wizard will ignore Simplified Tax. Consider disabling it."),
					indicator="orange", title=_("Setting Conflict"))

			if not self.enable_vat and not self.auto_detect_regime:
				frappe.msgprint(
					_("General regime typically requires VAT. VAT is disabled. "
					  "The wizard will not calculate VAT entries. Enable it if this company is a VAT payer."),
					indicator="orange", title=_("Check Required"))

			if not self.enable_profit_tax and not self.auto_detect_regime:
				frappe.msgprint(
					_("General regime typically requires Profit Tax. It is disabled. "
					  "The wizard will not calculate profit tax entries."),
					indicator="orange", title=_("Check Required"))

		elif self.default_tax_regime in ("Simplified Tax", "Special Regime"):
			if self.enable_vat:
				frappe.msgprint(
					_("Simplified/Special regime does not use VAT. VAT is enabled. "
					  "Simplified tax payers are not VAT payers per AZ Tax Code. "
					  "The wizard will skip VAT calculation. Consider disabling it."),
					indicator="orange", title=_("Setting Conflict"))

			if self.enable_profit_tax:
				frappe.msgprint(
					_("Simplified/Special regime does not use Profit Tax. It is enabled. "
					  "Simplified tax replaces profit tax per AZ Tax Code. "
					  "The wizard will skip profit tax. Consider disabling it."),
					indicator="orange", title=_("Setting Conflict"))

		# 2. Profit tax advance method consistency
		if (self.enable_profit_tax
			and self.profit_tax_advance_method == "1/4 of Previous Year Tax"
			and flt(self.profit_tax_previous_year_amount) <= 0):
			frappe.msgprint(
				_("Profit tax advance method is set to '1/4 of Previous Year Tax' "
				  "but the previous year amount is 0. The wizard will calculate 0 tax. "
				  "Please enter the previous year's total profit tax amount."),
				indicator="red", title=_("Missing Data"))

		# 3. VAT accounts must be different
		if self.enable_vat and self.vat_input_account and self.vat_output_account:
			if self.vat_input_account == self.vat_output_account:
				frappe.throw(
					_("VAT Input Account and VAT Output Account must be different. "
					  "Input (226) is an Asset account for VAT paid on purchases. "
					  "Output (521.3) is a Liability account for VAT collected from sales."))

		# 4. Period closing requires closing account
		if self.enable_period_closing and not self.closing_account:
			frappe.msgprint(
				_("Period Closing Voucher is enabled but no Closing Account is set. "
				  "You must specify an Equity or Liability account (e.g., 341) where "
				  "net profit/loss will be transferred when P&L is closed."),
				indicator="red", title=_("Missing Account"))

		# 5. Auto-submit + period closing = dangerous
		if self.auto_submit_entries and self.enable_period_closing:
			frappe.msgprint(
				_("Both 'Auto-submit' and 'Period Closing Voucher' are enabled. "
				  "This means journal entries AND the Period Closing Voucher will be "
				  "submitted immediately without manual review. This is irreversible. "
				  "Consider disabling auto-submit for safety."),
				indicator="red", title=_("High Risk Configuration"))

		# 6. Re-closing disabled but shown
		if not self.allow_reclosing and self.duplicate_check_scope:
			pass  # This is fine, duplicate_check_scope only applies when reclosing is OFF

		# 7. Declaration draft without regime match
		if self.create_declaration_draft and self.auto_fill_declaration:
			if not self.company:
				frappe.msgprint(
					_("Auto-fill declarations requires a Company to be set. "
					  "VOEN, activity code, and tax authority are read from the Company document."),
					indicator="orange", title=_("Company Required"))

		# 8. Property tax rate sanity
		if flt(self.property_tax_rate) > 5:
			frappe.msgprint(
				_("Property tax rate is set to {}%. The standard AZ rate is 1%. "
				  "Are you sure this is correct?").format(self.property_tax_rate),
				indicator="orange", title=_("Unusual Rate"))

		# 9. VAT rate sanity
		if self.enable_vat and flt(self.vat_rate) != 18 and flt(self.vat_rate) > 0:
			frappe.msgprint(
				_("VAT rate is set to {}%. The standard AZ rate is 18%. "
				  "This is unusual — change only if a new rate has been enacted.").format(
					self.vat_rate),
				indicator="orange", title=_("Non-standard Rate"))

		# 10. Profit tax rate sanity
		if self.enable_profit_tax and flt(self.profit_tax_rate) != 20 and flt(self.profit_tax_rate) > 0:
			frappe.msgprint(
				_("Profit tax rate is set to {}%. The standard AZ rate is 20%. "
				  "Change only if your company qualifies for a special rate.").format(
					self.profit_tax_rate),
				indicator="orange", title=_("Non-standard Rate"))

		# 11. Account mapping completeness
		self._validate_account_map()

	def _validate_account_map(self):
		"""Check that enabled taxes have corresponding account mappings."""
		tax_map = {row.tax_type for row in self.account_map or []}

		missing = []
		if self.enable_vat and "VAT (ƏDV)" not in tax_map:
			# VAT uses separate fields, so this is OK
			if not self.vat_input_account or not self.vat_output_account:
				missing.append("VAT (ƏDV) — set VAT Input/Output accounts above")

		if self.enable_profit_tax and "Profit Tax (Mənfəət)" not in tax_map:
			missing.append("Profit Tax (Mənfəət)")

		if self.enable_simplified_tax and "Simplified Tax (Sadələşdirilmiş)" not in tax_map:
			missing.append("Simplified Tax (Sadələşdirilmiş)")

		if self.enable_property_tax and "Property Tax (Əmlak)" not in tax_map:
			missing.append("Property Tax (Əmlak)")

		if self.enable_land_tax and "Land Tax (Torpaq)" not in tax_map:
			missing.append("Land Tax (Torpaq)")

		if missing:
			frappe.msgprint(
				_("The following enabled taxes have no account mapping. "
				  "The wizard won't know which accounts to debit/credit:<br><br>"
				  "{}").format("<br>".join(f"• {m}" for m in missing)),
				indicator="orange", title=_("Missing Account Mapping"))

	def run_auto_detect(self):
		"""Auto-detect settings from company data."""
		company = frappe.get_doc("Company", self.company)
		detected = []

		# Cost center
		if not self.default_cost_center and company.cost_center:
			self.default_cost_center = company.cost_center
			detected.append(f"Cost Center → {company.cost_center}")

		# VAT payer detection
		has_vat_cert = (hasattr(company, "vat_certificate_number")
			and company.vat_certificate_number)

		# Regime detection
		if self.auto_detect_regime:
			if has_vat_cert:
				self.default_tax_regime = "General (VAT + Profit)"
				self.enable_vat = 1
				self.enable_profit_tax = 1
				self.enable_simplified_tax = 0
				detected.append("Regime → General (VAT payer detected)")
			else:
				self.default_tax_regime = "Simplified Tax"
				self.enable_vat = 0
				self.enable_profit_tax = 0
				self.enable_simplified_tax = 1
				detected.append("Regime → Simplified (no VAT certificate)")

		# Asset detection
		asset_count = frappe.db.count("Asset", {
			"company": self.company,
			"docstatus": 1,
			"status": ["not in", ["Scrapped", "Sold"]],
		})
		if asset_count > 0:
			self.enable_property_tax = 1
			detected.append(f"Property Tax → Enabled ({asset_count} assets found)")
		else:
			self.enable_property_tax = 0
			detected.append("Property Tax → Disabled (no active assets)")

		# Employee detection
		emp_count = frappe.db.count("Employee", {
			"company": self.company,
			"status": "Active",
		})
		if emp_count > 0:
			self.enable_payroll_collection = 1
			detected.append(f"Payroll Collection → Enabled ({emp_count} active employees)")
		else:
			self.enable_payroll_collection = 0
			detected.append("Payroll Collection → Disabled (no active employees)")

		# VAT accounts auto-detect
		if self.enable_vat and (not self.vat_input_account or not self.vat_output_account):
			self._detect_vat_accounts(detected)

		# Account mapping auto-detect
		if not self.account_map or len(self.account_map) == 0:
			self._detect_account_mapping(detected)

		if detected:
			frappe.msgprint(
				_("Auto-detection results:<br><br>{}").format(
					"<br>".join(f"✓ {d}" for d in detected)),
				indicator="green", title=_("Parameters Detected"))

	def _detect_vat_accounts(self, detected):
		"""Try to find VAT accounts from Chart of Accounts."""
		# Look for account 226 (VAT input)
		vat_input = frappe.db.get_value("Account", {
			"company": self.company,
			"account_number": "226",
			"is_group": 0,
		}, "name")
		if vat_input:
			self.vat_input_account = vat_input
			detected.append(f"VAT Input Account → {vat_input}")

		# Look for account 521.3 (VAT output)
		vat_output = frappe.db.get_value("Account", {
			"company": self.company,
			"account_number": "521.3",
			"is_group": 0,
		}, "name")
		if vat_output:
			self.vat_output_account = vat_output
			detected.append(f"VAT Output Account → {vat_output}")

	def _detect_account_mapping(self, detected):
		"""Try to auto-detect account mappings from Chart of Accounts."""
		mapping_rules = [
			{
				"tax_type": "Profit Tax (Mənfəət)",
				"debit_numbers": ["901"],
				"credit_numbers": ["521.1"],
			},
			{
				"tax_type": "Simplified Tax (Sadələşdirilmiş)",
				"debit_numbers": ["731"],
				"credit_numbers": ["521.9"],
			},
			{
				"tax_type": "Property Tax (Əmlak)",
				"debit_numbers": ["731"],
				"credit_numbers": ["521.5"],
			},
			{
				"tax_type": "Land Tax (Torpaq)",
				"debit_numbers": ["731"],
				"credit_numbers": ["521.6"],
			},
			{
				"tax_type": "Excise Tax (Aksiz)",
				"debit_numbers": ["731"],
				"credit_numbers": ["521.4"],
			},
			{
				"tax_type": "Mining Tax (Mədən)",
				"debit_numbers": ["731"],
				"credit_numbers": ["521.8"],
			},
			{
				"tax_type": "Road Tax (Yol)",
				"debit_numbers": ["731"],
				"credit_numbers": ["521.7"],
			},
		]

		found_count = 0
		for rule in mapping_rules:
			debit_acc = None
			credit_acc = None

			for num in rule["debit_numbers"]:
				debit_acc = frappe.db.get_value("Account", {
					"company": self.company,
					"account_number": num,
					"is_group": 0,
				}, "name")
				if debit_acc:
					break

			for num in rule["credit_numbers"]:
				credit_acc = frappe.db.get_value("Account", {
					"company": self.company,
					"account_number": num,
					"is_group": 0,
				}, "name")
				if credit_acc:
					break

			if debit_acc and credit_acc:
				self.append("account_map", {
					"tax_type": rule["tax_type"],
					"debit_account": debit_acc,
					"credit_account": credit_acc,
				})
				found_count += 1

		if found_count:
			detected.append(f"Account Mapping → {found_count} mappings auto-detected")

	def on_update(self):
		frappe.clear_cache(doctype="Tax Period Closing Settings")


def get_settings():
	return frappe.get_single("Tax Period Closing Settings")


def get_tax_rate(tax_type):
	settings = get_settings()
	for row in settings.tax_rates or []:
		if row.tax_type == tax_type:
			return row.rate
	return 0


def get_account_map(tax_type):
	settings = get_settings()
	for row in settings.account_map or []:
		if row.tax_type == tax_type:
			return {"debit": row.debit_account, "credit": row.credit_account}
	return None


@frappe.whitelist()
def auto_detect_accounts(company):
	"""API endpoint to detect accounts for a specific company."""
	if not company:
		return {"accounts": []}

	results = {}

	account_search = {
		"226": "VAT Input (ƏDV sub-uçot)",
		"521.3": "VAT Output (ƏDV)",
		"521.1": "Profit Tax Liability",
		"521.5": "Property Tax Liability",
		"521.6": "Land Tax Liability",
		"521.9": "Simplified Tax Liability",
		"901": "Profit Tax Expense",
		"731": "Other Operating Expenses",
		"341": "Period Net Profit (Closing)",
	}

	for acc_num, label in account_search.items():
		acc = frappe.db.get_value("Account", {
			"company": company,
			"account_number": acc_num,
			"is_group": 0,
		}, ["name", "account_name"], as_dict=True)
		if acc:
			results[acc_num] = {
				"name": acc.name,
				"account_name": acc.account_name,
				"label": label,
			}

	return {"accounts": results}
