import sys

import frappe
import frappe.utils

import erpnext
from erpnext.demo.setup import education, manufacture, retail, setup_data
from erpnext.demo.user import accounts
from erpnext.demo.user import education as edu
from erpnext.demo.user import fixed_asset, hr, manufacturing, projects, purchase, sales, stock

"""
Make a demo

1. Start with a fresh account

bench --site demo.erpnext.dev reinstall

2. Install Demo

bench --site demo.erpnext.dev execute erpnext.demo.demo.make

3. If Demo breaks, to continue

bench --site demo.erpnext.dev execute erpnext.demo.demo.simulate

"""

def make(domain='Manufacturing', days=100):
	frappe.flags.domain = domain
	frappe.flags.mute_emails = True
	setup_data.setup(domain)
	if domain== 'Manufacturing':
		manufacture.setup_data()
	elif domain == "Retail":
		retail.setup_data()
	elif domain== 'Education':
		education.setup_data()

	site = frappe.local.site
	frappe.destroy()
	frappe.init(site)
	frappe.connect()

	simulate(domain, days)

def simulate(domain='Manufacturing', days=100):
	runs_for = frappe.flags.runs_for or days
	frappe.flags.company = erpnext.get_default_company()
	frappe.flags.mute_emails = True

	if not frappe.flags.start_date:
		# start date = 100 days back
		frappe.flags.start_date = frappe.utils.add_days(frappe.utils.nowdate(),
			-1 * runs_for)

	current_date = frappe.utils.getdate(frappe.flags.start_date)

	# continue?
	demo_last_date = frappe.db.get_global('demo_last_date')
	if demo_last_date:
		current_date = frappe.utils.add_days(frappe.utils.getdate(demo_last_date), 1)

	# run till today
	if not runs_for:
		runs_for = frappe.utils.date_diff(frappe.utils.nowdate(), current_date)
		# runs_for = 100

	fixed_asset.work()
	for i in range(runs_for):
		sys.stdout.write("\rSimulating {0}: Day {1}".format(
			current_date.strftime("%Y-%m-%d"), i))
		sys.stdout.flush()
		frappe.flags.current_date = current_date
		if current_date.weekday() in (5, 6):
			current_date = frappe.utils.add_days(current_date, 1)
			continue
		try:
			hr.work()
			purchase.work()
			stock.work()
			accounts.work()
			projects.run_projects(current_date)
			sales.work(domain)
			# run_messages()

			if domain=='Manufacturing':
				manufacturing.work()
			elif domain=='Education':
				edu.work()

		except Exception:
			frappe.db.set_global('demo_last_date', current_date)
			raise
		finally:
			current_date = frappe.utils.add_days(current_date, 1)
			frappe.db.commit()
