# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt

import json
import os
from random import randint

import frappe
from frappe import _
from frappe.utils import add_days, getdate

import erpnext
from erpnext.accounts.utils import get_fiscal_year
from erpnext.setup.setup_wizard.operations.install_fixtures import create_bank_account


def setup_demo_data():
	from frappe.utils.telemetry import capture

	capture("demo_data_creation_started", "erpnext")
	try:
		company = create_demo_company()
		process_masters()
		make_transactions(company)
		frappe.cache.delete_keys("bootinfo")
		frappe.publish_realtime("demo_data_complete")
	except Exception:
		frappe.log_error("Failed to create demo data")
		capture("demo_data_creation_failed", "erpnext", properties={"exception": frappe.get_traceback()})
		raise
	capture("demo_data_creation_completed", "erpnext")


@frappe.whitelist()
def clear_demo_data():
	frappe.only_for("System Manager")
	try:
		company = frappe.db.get_single_value("Global Defaults", "demo_company")
		create_transaction_deletion_record(company)
		clear_masters()
		delete_company(company)
		default_company = frappe.db.get_single_value("Global Defaults", "default_company")
		frappe.db.set_default("company", default_company)
	except Exception:
		frappe.db.rollback()
		frappe.log_error("Failed to erase demo data")
		frappe.throw(
			_("Failed to erase demo data, please delete the demo company manually."),
			title=_("Could Not Delete Demo Data"),
		)


def create_demo_company():
	company = frappe.db.get_all("Company")[0].name
	company_doc = frappe.get_doc("Company", company)

	# Make a dummy company
	new_company = frappe.new_doc("Company")
	new_company.company_name = company_doc.company_name + " (Demo)"
	new_company.abbr = company_doc.abbr + "D"
	new_company.enable_perpetual_inventory = 1
	new_company.default_currency = company_doc.default_currency
	new_company.country = company_doc.country
	new_company.chart_of_accounts_based_on = "Standard Template"
	new_company.chart_of_accounts = company_doc.chart_of_accounts
	new_company.insert()

	# Set Demo Company as default to
	frappe.db.set_single_value("Global Defaults", "demo_company", new_company.name)
	frappe.db.set_default("company", new_company.name)

	bank_account = create_bank_account({"company_name": new_company.name})
	frappe.db.set_value("Company", new_company.name, "default_bank_account", bank_account.name)

	return new_company.name


def process_masters():
	for doctype in frappe.get_hooks("demo_master_doctypes"):
		data = read_data_file_using_hooks(doctype)
		if data:
			for item in json.loads(data):
				create_demo_record(item)


def create_demo_record(doctype):
	frappe.get_doc(doctype).insert(ignore_permissions=True)


def make_transactions(company):
	start_date = get_fiscal_year(date=getdate())[1]
	frappe.db.set_single_value("Stock Settings", "allow_negative_stock", 1)

	for doctype in frappe.get_hooks("demo_transaction_doctypes"):
		data = read_data_file_using_hooks(doctype)
		if data:
			for item in json.loads(data):
				create_transaction(item, company, start_date)


def create_transaction(doctype, company, start_date):
	warehouse = get_warehouse(company)
	posting_date = (
		start_date if doctype.get("doctype") == "Purchase Invoice" else get_random_date(start_date)
	)
	bank_account, default_receivable_account = frappe.db.get_value(
		"Company", company, ["default_bank_account", "default_receivable_account"]
	)
	bank_field = "paid_to" if doctype.get("party_type") == "Customer" else "paid_from"

	doctype.update(
		{
			"company": company,
			"set_posting_time": 1,
			"posting_date": posting_date,
			"set_warehouse": warehouse,
			bank_field: bank_account,
			"reference_date": posting_date,
		}
	)

	income_account, expense_account = frappe.db.get_value(
		"Company", company, ["default_income_account", "default_expense_account"]
	)

	if doctype in ("Purchase Invoice", "Sales Invoice"):
		for item in doctype.get("items") or []:
			item.update(
				{
					"cost_center": erpnext.get_default_cost_center(company),
					"income_account": income_account,
					"expense_account": expense_account,
				}
			)
	elif doctype == "Journal Entry":
		pass
		# update_accounts(doctype, bank_account, default_receivable_account)

	doc = frappe.get_doc(doctype)
	doc.save(ignore_permissions=True)
	doc.submit()


# def update_accounts(doctype, company, bank_account):


def get_random_date(start_date):
	return add_days(start_date, randint(1, 365))


def create_transaction_deletion_record(company):
	transaction_deletion_record = frappe.new_doc("Transaction Deletion Record")
	transaction_deletion_record.company = company
	transaction_deletion_record.save(ignore_permissions=True)
	transaction_deletion_record.submit()


def clear_masters():
	for doctype in frappe.get_hooks("demo_master_doctypes")[::-1]:
		data = read_data_file_using_hooks(doctype)
		if data:
			for item in json.loads(data):
				clear_demo_record(item)


def clear_demo_record(document):
	doc_type = document.get("doctype")
	del document["doctype"]
	doc = frappe.get_doc(doc_type, document)
	frappe.delete_doc(doc.doctype, doc.name, ignore_permissions=True)


def delete_company(company):
	frappe.db.set_single_value("Global Defaults", "demo_company", "")
	frappe.delete_doc("Company", company, ignore_permissions=True)


def read_data_file_using_hooks(doctype):
	path = os.path.join(os.path.dirname(__file__), "demo_data")
	with open(os.path.join(path, doctype + ".json"), "r") as f:
		data = f.read()

	return data


def get_warehouse(company):
	abbr = frappe.db.get_value("Company", company, "abbr")
	warehouse = "Stores - {0}".format(abbr)

	return warehouse
