"""
Setup required accounts for Tax Year Closing Wizard.
Runs after migrate — checks if accounts exist and creates them if missing.
"""

import frappe
from frappe import _

def _get_accounting_method(company):
	"""Safely get accounting_method — returns '' if the custom field column doesn't exist yet."""
	if not frappe.db.has_column("Company", "accounting_method"):
		return ""
	return frappe.db.get_value("Company", company, "accounting_method") or ""


REQUIRED_ACCOUNTS = [
	{
		"account_number": "245.1",
		"account_name": "ƏDV gözləmədə (satış)",
		"parent_number": "245",
		"parent_name": "Digər qısamüddətli aktivlər",
		"root_type": "Asset",
		"account_type": "Tax",
		"description": "Kassa metodu: Satış fakturasında ƏDV burada saxlanılır, ödəniş alındıqda 521.3-ə köçürülür",
		"needed_for": "Kassa metodu",
	},
	{
		"account_number": "245.2",
		"account_name": "ƏDV gözləmədə (alış)",
		"parent_number": "245",
		"parent_name": "Digər qısamüddətli aktivlər",
		"root_type": "Asset",
		"account_type": "Tax",
		"description": "Kassa metodu: Alış fakturasında ƏDV burada saxlanılır, ödəniş edildikdə 226-ya köçürülür",
		"needed_for": "Kassa metodu",
	},
]


def check_and_create_accounts():
	"""Check required accounts for all companies and create if missing."""
	companies = frappe.get_all("Company", filters={"is_group": 0}, fields=["name", "abbr"])

	for company in companies:
		missing = []
		for acc_def in REQUIRED_ACCOUNTS:
			exists = frappe.db.exists("Account", {
				"company": company.name,
				"account_number": acc_def["account_number"],
			})
			if not exists:
				missing.append(acc_def)

		if not missing:
			continue

		# Check accounting method — only create if Kassa
		method = _get_accounting_method(company.name)
		if "Kassa" not in method:
			continue

		for acc_def in missing:
			_create_account(company.name, company.abbr, acc_def)


def _create_account(company, abbr, acc_def):
	"""Create a single account if parent exists."""
	# Ensure parent is group
	parent_acc = frappe.db.get_value("Account", {
		"company": company,
		"account_number": acc_def["parent_number"],
	}, ["name", "is_group"], as_dict=True)

	if not parent_acc:
		frappe.log_error(
			f"taxes_az: Cannot create account {acc_def['account_number']} — "
			f"parent {acc_def['parent_number']} not found for {company}",
			"Account Setup"
		)
		return

	# Convert parent to group if needed
	if not parent_acc.is_group:
		gl_count = frappe.db.count("GL Entry", {
			"account": parent_acc.name, "is_cancelled": 0
		})
		if gl_count == 0:
			frappe.db.set_value("Account", parent_acc.name, "is_group", 1)
		else:
			frappe.log_error(
				f"taxes_az: Cannot convert {parent_acc.name} to group — has GL entries",
				"Account Setup"
			)
			return

	try:
		acc = frappe.get_doc({
			"doctype": "Account",
			"account_name": acc_def["account_name"],
			"account_number": acc_def["account_number"],
			"parent_account": parent_acc.name,
			"company": company,
			"account_type": acc_def.get("account_type", ""),
			"is_group": 0,
		})
		acc.flags.ignore_permissions = True
		acc.flags.ignore_mandatory = True
		acc.insert(ignore_permissions=True)
		frappe.db.commit()
		print(f"  ✓ Created {acc_def['account_number']} — {acc_def['account_name']} for {company}")
	except Exception as e:
		frappe.log_error(
			f"taxes_az: Failed to create {acc_def['account_number']} for {company}: {e}",
			"Account Setup"
		)


def update_tax_templates_for_method(company):
	"""Switch Sales/Purchase Tax Templates based on accounting method."""
	method = _get_accounting_method(company)
	abbr = frappe.db.get_value("Company", company, "abbr")

	if "Kassa" in method:
		# Kassa: 521.3 → 245.1 (sales), 226 → 245.2 (purchase)
		sales_from = f"521.3 - ƏDV - {abbr}"
		sales_to = frappe.db.get_value("Account", {"company": company, "account_number": "245.1"}, "name")
		purchase_from = f"226 - ƏDV sub-uçot hesabı - {abbr}"
		purchase_to = frappe.db.get_value("Account", {"company": company, "account_number": "245.2"}, "name")
	else:
		# Hesablama: 245.1 → 521.3 (sales), 245.2 → 226 (purchase)
		sales_from = frappe.db.get_value("Account", {"company": company, "account_number": "245.1"}, "name")
		sales_to = f"521.3 - ƏDV - {abbr}"
		purchase_from = frappe.db.get_value("Account", {"company": company, "account_number": "245.2"}, "name")
		purchase_to = f"226 - ƏDV sub-uçot hesabı - {abbr}"

	if not sales_to or not sales_from:
		return

	# Update Sales Templates
	updated = 0
	for t_name in frappe.get_all("Sales Taxes and Charges Template",
		filters={"company": company}, pluck="name"):
		doc = frappe.get_doc("Sales Taxes and Charges Template", t_name)
		changed = False
		for tax in doc.taxes:
			if tax.account_head == sales_from:
				tax.account_head = sales_to
				changed = True
		if changed:
			doc.save(ignore_permissions=True)
			updated += 1

	# Update Purchase Templates
	if purchase_from and purchase_to:
		for t_name in frappe.get_all("Purchase Taxes and Charges Template",
			filters={"company": company}, pluck="name"):
			doc = frappe.get_doc("Purchase Taxes and Charges Template", t_name)
			changed = False
			for tax in doc.taxes:
				if tax.account_head == purchase_from:
					tax.account_head = purchase_to
					changed = True
			if changed:
				doc.save(ignore_permissions=True)
				updated += 1

	if updated:
		frappe.db.commit()


def on_company_update(doc, method):
	"""Hook: when Company is saved, update templates if accounting method changed."""
	if not frappe.db.has_column("Company", "accounting_method"):
		return
	old_method = doc.get_db_value("accounting_method") if not doc.is_new() else ""
	new_method = doc.accounting_method or ""

	if old_method != new_method and new_method:
		# Create accounts if switching to Kassa
		if "Kassa" in new_method:
			check_and_create_accounts()
		# Update templates
		update_tax_templates_for_method(doc.name)


@frappe.whitelist()
def check_required_accounts(company):
	"""API: Check which accounts are missing for a company."""
	if not company:
		return {"accounts": [], "missing": []}

	abbr = frappe.db.get_value("Company", company, "abbr")
	method = _get_accounting_method(company)

	accounts = []
	missing = []

	for acc_def in REQUIRED_ACCOUNTS:
		acc = frappe.db.get_value("Account", {
			"company": company,
			"account_number": acc_def["account_number"],
		}, ["name", "account_name"], as_dict=True)

		status = {
			"number": acc_def["account_number"],
			"name": acc_def["account_name"],
			"description": acc_def["description"],
			"needed_for": acc_def["needed_for"],
			"exists": bool(acc),
			"account": acc.name if acc else None,
		}
		accounts.append(status)
		if not acc:
			missing.append(status)

	return {
		"accounts": accounts,
		"missing": missing,
		"method": method,
		"needs_kassa_accounts": "Kassa" in method,
	}


@frappe.whitelist()
def create_missing_accounts(company):
	"""API: Create all missing required accounts for a company."""
	if not company:
		return {"created": []}

	abbr = frappe.db.get_value("Company", company, "abbr")
	created = []

	for acc_def in REQUIRED_ACCOUNTS:
		exists = frappe.db.exists("Account", {
			"company": company,
			"account_number": acc_def["account_number"],
		})
		if exists:
			continue

		_create_account(company, abbr, acc_def)
		created.append(acc_def["account_number"])

	return {"created": created}
