# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
# License: GNU General Public License v3. See license.txt

from __future__ import unicode_literals
import webnotes
from webnotes import msgprint, _
import webnotes.defaults
from webnotes.utils import flt, get_fullname, fmt_money, cstr

class WebsitePriceListMissingError(webnotes.ValidationError): pass

def set_cart_count(quotation=None):
	if not quotation:
		quotation = _get_cart_quotation()
	cart_count = cstr(len(quotation.doclist.get({"parentfield": "quotation_details"})))
	webnotes._response.set_cookie("cart_count", cart_count)

@webnotes.whitelist()
def get_cart_quotation(doclist=None):
	party = get_lead_or_customer()
	
	if not doclist:
		quotation = _get_cart_quotation(party)
		doclist = quotation.doclist
		set_cart_count(quotation)
	
	return {
		"doclist": decorate_quotation_doclist(doclist),
		"addresses": [{"name": address.name, "display": address.display} 
			for address in get_address_docs(party)],
		"shipping_rules": get_applicable_shipping_rules(party)
	}
	
@webnotes.whitelist()
def place_order():
	quotation = _get_cart_quotation()
	controller = quotation.make_controller()
	for fieldname in ["customer_address", "shipping_address_name"]:
		if not quotation.doc.fields.get(fieldname):
			msgprint(_("Please select a") + " " + _(controller.meta.get_label(fieldname)), raise_exception=True)
	
	quotation.ignore_permissions = True
	quotation.submit()
	
	from selling.doctype.quotation.quotation import _make_sales_order
	sales_order = webnotes.bean(_make_sales_order(quotation.doc.name, ignore_permissions=True))
	sales_order.ignore_permissions = True
	sales_order.insert()
	sales_order.submit()
	webnotes._response.set_cookie("cart_count", "")
	
	return sales_order.doc.name

@webnotes.whitelist()
def update_cart(item_code, qty, with_doclist=0):
	quotation = _get_cart_quotation()
	
	qty = flt(qty)
	if qty == 0:
		quotation.set_doclist(quotation.doclist.get({"item_code": ["!=", item_code]}))
		if not quotation.doclist.get({"parentfield": "quotation_details"}) and \
			not quotation.doc.fields.get("__islocal"):
				quotation.__delete = True
			
	else:
		quotation_items = quotation.doclist.get({"item_code": item_code})
		if not quotation_items:
			quotation.doclist.append({
				"doctype": "Quotation Item",
				"parentfield": "quotation_details",
				"item_code": item_code,
				"qty": qty
			})
		else:
			quotation_items[0].qty = qty
	
	apply_cart_settings(quotation=quotation)

	if hasattr(quotation, "__delete"):
		webnotes.delete_doc("Quotation", quotation.doc.name, ignore_permissions=True)
		quotation = _get_cart_quotation()
	else:
		quotation.ignore_permissions = True
		quotation.save()
	
	set_cart_count(quotation)
	
	if with_doclist:
		return get_cart_quotation(quotation.doclist)
	else:
		return quotation.doc.name
		
@webnotes.whitelist()
def update_cart_address(address_fieldname, address_name):
	from utilities.transaction_base import get_address_display
	
	quotation = _get_cart_quotation()
	address_display = get_address_display(webnotes.doc("Address", address_name).fields)
	
	if address_fieldname == "shipping_address_name":
		quotation.doc.shipping_address_name = address_name
		quotation.doc.shipping_address = address_display
		
		if not quotation.doc.customer_address:
			address_fieldname == "customer_address"
	
	if address_fieldname == "customer_address":
		quotation.doc.customer_address = address_name
		quotation.doc.address_display = address_display
		
	
	apply_cart_settings(quotation=quotation)
	
	quotation.ignore_permissions = True
	quotation.save()
		
	return get_cart_quotation(quotation.doclist)

@webnotes.whitelist()
def get_addresses():
	return [d.fields for d in get_address_docs()]
	
@webnotes.whitelist()
def save_address(fields, address_fieldname=None):
	party = get_lead_or_customer()
	fields = webnotes.load_json(fields)
	
	if fields.get("name"):
		bean = webnotes.bean("Address", fields.get("name"))
	else:
		bean = webnotes.bean({"doctype": "Address", "__islocal": 1})
	
	bean.doc.fields.update(fields)
	
	party_fieldname = party.doctype.lower()
	bean.doc.fields.update({
		party_fieldname: party.name,
		(party_fieldname + "_name"): party.fields[party_fieldname + "_name"]
	})
	bean.ignore_permissions = True
	bean.save()
	
	if address_fieldname:
		update_cart_address(address_fieldname, bean.doc.name)
	
	return bean.doc.name
	
def get_address_docs(party=None):
	from webnotes.model.doclist import objectify
	from utilities.transaction_base import get_address_display
	
	if not party:
		party = get_lead_or_customer()
		
	address_docs = objectify(webnotes.conn.sql("""select * from `tabAddress`
		where `%s`=%s order by name""" % (party.doctype.lower(), "%s"), party.name, 
		as_dict=True, update={"doctype": "Address"}))
	
	for address in address_docs:
		address.display = get_address_display(address.fields)
		address.display = (address.display).replace("\n", "<br>\n")
		
	return address_docs
	
def get_lead_or_customer():
	customer = webnotes.conn.get_value("Contact", {"email_id": webnotes.session.user}, "customer")
	if customer:
		return webnotes.doc("Customer", customer)
	
	lead = webnotes.conn.get_value("Lead", {"email_id": webnotes.session.user})
	if lead:
		return webnotes.doc("Lead", lead)
	else:
		lead_bean = webnotes.bean({
			"doctype": "Lead",
			"email_id": webnotes.session.user,
			"lead_name": get_fullname(webnotes.session.user),
			"territory": guess_territory(),
			"status": "Open" # TODO: set something better???
		})
		
		if webnotes.session.user != "Guest":
			lead_bean.ignore_permissions = True
			lead_bean.insert()
			
		return lead_bean.doc
		
def guess_territory():
	territory = None
	geoip_country = webnotes.session.get("session_country")
	if geoip_country:
		territory = webnotes.conn.get_value("Territory", geoip_country)
	
	return territory or \
		webnotes.conn.get_value("Shopping Cart Settings", None, "territory") or \
		"All Territories"

def decorate_quotation_doclist(doclist):
	for d in doclist:
		if d.item_code:
			d.fields.update(webnotes.conn.get_value("Item", d.item_code, 
				["website_image", "description", "page_name"], as_dict=True))
			d.formatted_rate = fmt_money(d.export_rate, currency=doclist[0].currency)
			d.formatted_amount = fmt_money(d.export_amount, currency=doclist[0].currency)
		elif d.charge_type:
			d.formatted_tax_amount = fmt_money(d.tax_amount / doclist[0].conversion_rate,
				currency=doclist[0].currency)

	doclist[0].formatted_grand_total_export = fmt_money(doclist[0].grand_total_export,
		currency=doclist[0].currency)
	
	return [d.fields for d in doclist]

def _get_cart_quotation(party=None):
	if not party:
		party = get_lead_or_customer()
		
	quotation = webnotes.conn.get_value("Quotation", 
		{party.doctype.lower(): party.name, "order_type": "Shopping Cart", "docstatus": 0})
	
	if quotation:
		qbean = webnotes.bean("Quotation", quotation)
	else:
		qbean = webnotes.bean({
			"doctype": "Quotation",
			"naming_series": webnotes.defaults.get_user_default("shopping_cart_quotation_series") or "QTN-CART-",
			"quotation_to": party.doctype,
			"company": webnotes.defaults.get_user_default("company"),
			"order_type": "Shopping Cart",
			"status": "Draft",
			"docstatus": 0,
			"__islocal": 1,
			(party.doctype.lower()): party.name
		})
		
		if party.doctype == "Customer":
			qbean.doc.contact_person = webnotes.conn.get_value("Contact", {"email_id": webnotes.session.user,
				"customer": party.name})
			qbean.run_method("set_contact_fields")
		
		qbean.run_method("onload_post_render")
		apply_cart_settings(party, qbean)
	
	return qbean

def update_party(fullname, company_name=None, mobile_no=None, phone=None):
	party = get_lead_or_customer()

	if party.doctype == "Lead":
		party.company_name = company_name
		party.lead_name = fullname
		party.mobile_no = mobile_no
		party.phone = phone
	else:
		party.customer_name = company_name or fullname
		party.customer_type == "Company" if company_name else "Individual"
		
		contact_name = webnotes.conn.get_value("Contact", {"email_id": webnotes.session.user,
			"customer": party.name})
		contact = webnotes.bean("Contact", contact_name)
		contact.doc.first_name = fullname
		contact.doc.last_name = None
		contact.doc.customer_name = party.customer_name
		contact.doc.mobile_no = mobile_no
		contact.doc.phone = phone
		contact.ignore_permissions = True
		contact.save()
	
	party_bean = webnotes.bean(party.fields)
	party_bean.ignore_permissions = True
	party_bean.save()
	
	qbean = _get_cart_quotation(party)
	if not qbean.doc.fields.get("__islocal"):
		qbean.doc.customer_name = company_name or fullname
		qbean.run_method("set_contact_fields")
		qbean.ignore_permissions = True
		qbean.save()

def apply_cart_settings(party=None, quotation=None):
	if not party:
		party = get_lead_or_customer()
	if not quotation:
		quotation = _get_cart_quotation(party)
	
	cart_settings = webnotes.get_obj("Shopping Cart Settings")
	
	billing_territory = get_address_territory(quotation.doc.customer_address) or \
		party.territory or "All Territories"
		
	set_price_list_and_rate(quotation, cart_settings, billing_territory)
	
	quotation.run_method("calculate_taxes_and_totals")
	
	set_taxes(quotation, cart_settings, billing_territory)
	
	_apply_shipping_rule(party, quotation, cart_settings)
	
def set_price_list_and_rate(quotation, cart_settings, billing_territory):
	"""set price list based on billing territory"""
	quotation.doc.selling_price_list = cart_settings.get_price_list(billing_territory)
	
	# reset values
	quotation.doc.price_list_currency = quotation.doc.currency = \
		quotation.doc.plc_conversion_rate = quotation.doc.conversion_rate = None
	for item in quotation.doclist.get({"parentfield": "quotation_details"}):
		item.ref_rate = item.adj_rate = item.export_rate = item.export_amount = None
	
	# refetch values
	quotation.run_method("set_price_list_and_item_details")
	
	# set it in cookies for using in product page
	webnotes.cookies[b"selling_price_list"] = quotation.doc.selling_price_list
	
def set_taxes(quotation, cart_settings, billing_territory):
	"""set taxes based on billing territory"""
	quotation.doc.charge = cart_settings.get_tax_master(billing_territory)

	# clear table
	quotation.set_doclist(quotation.doclist.get({"parentfield": ["!=", "other_charges"]}))
	
	# append taxes
	controller = quotation.make_controller()
	controller.append_taxes_from_master("other_charges", "charge")
	quotation.set_doclist(controller.doclist)

@webnotes.whitelist()
def apply_shipping_rule(shipping_rule):
	quotation = _get_cart_quotation()
	
	quotation.doc.shipping_rule = shipping_rule
	
	apply_cart_settings(quotation=quotation)
	
	quotation.ignore_permissions = True
	quotation.save()
	
	return get_cart_quotation(quotation.doclist)
	
def _apply_shipping_rule(party=None, quotation=None, cart_settings=None):
	shipping_rules = get_shipping_rules(party, quotation, cart_settings)
	
	if not shipping_rules:
		return
		
	elif quotation.doc.shipping_rule not in shipping_rules:
		quotation.doc.shipping_rule = shipping_rules[0]
	
	quotation.run_method("apply_shipping_rule")
	quotation.run_method("calculate_taxes_and_totals")
	
def get_applicable_shipping_rules(party=None, quotation=None):
	shipping_rules = get_shipping_rules(party, quotation)
	
	if shipping_rules:
		rule_label_map = webnotes.conn.get_values("Shipping Rule", shipping_rules, "label")
		# we need this in sorted order as per the position of the rule in the settings page
		return [[rule, rule_label_map.get(rule)] for rule in shipping_rules]
		
def get_shipping_rules(party=None, quotation=None, cart_settings=None):
	if not party:
		party = get_lead_or_customer()
	if not quotation:
		quotation = _get_cart_quotation()
	if not cart_settings:
		cart_settings = webnotes.get_obj("Shopping Cart Settings")
		
	# set shipping rule based on shipping territory	
	shipping_territory = get_address_territory(quotation.doc.shipping_address_name) or \
		party.territory
	
	shipping_rules = cart_settings.get_shipping_rules(shipping_territory)
	
	return shipping_rules
	
def get_address_territory(address_name):
	"""Tries to match city, state and country of address to existing territory"""
	territory = None

	if address_name:
		address_fields = webnotes.conn.get_value("Address", address_name, 
			["city", "state", "country"])
		for value in address_fields:
			territory = webnotes.conn.get_value("Territory", value)
			if territory:
				break
	
	return territory
	
import unittest
test_dependencies = ["Item", "Price List", "Contact", "Shopping Cart Settings"]

class TestCart(unittest.TestCase):
	def tearDown(self):
		return
		
		cart_settings = webnotes.bean("Shopping Cart Settings")
		cart_settings.ignore_permissions = True
		cart_settings.doc.enabled = 0
		cart_settings.save()
	
	def enable_shopping_cart(self):
		return
		if not webnotes.conn.get_value("Shopping Cart Settings", None, "enabled"):
			cart_settings = webnotes.bean("Shopping Cart Settings")
			cart_settings.ignore_permissions = True
			cart_settings.doc.enabled = 1
			cart_settings.save()
			
	def test_get_lead_or_customer(self):
		webnotes.session.user = "test@example.com"
		party1 = get_lead_or_customer()
		party2 = get_lead_or_customer()
		self.assertEquals(party1.name, party2.name)
		self.assertEquals(party1.doctype, "Lead")
		
		webnotes.session.user = "test_contact_customer@example.com"
		party = get_lead_or_customer()
		self.assertEquals(party.name, "_Test Customer")
		
	def test_add_to_cart(self):
		self.enable_shopping_cart()
		webnotes.session.user = "test@example.com"
		
		update_cart("_Test Item", 1)
		
		quotation = _get_cart_quotation()
		quotation_items = quotation.doclist.get({"parentfield": "quotation_details", "item_code": "_Test Item"})
		self.assertTrue(quotation_items)
		self.assertEquals(quotation_items[0].qty, 1)
		
		return quotation
		
	def test_update_cart(self):
		self.test_add_to_cart()

		update_cart("_Test Item", 5)
		
		quotation = _get_cart_quotation()
		quotation_items = quotation.doclist.get({"parentfield": "quotation_details", "item_code": "_Test Item"})
		self.assertTrue(quotation_items)
		self.assertEquals(quotation_items[0].qty, 5)
		
		return quotation
		
	def test_remove_from_cart(self):
		quotation0 = self.test_add_to_cart()
		
		update_cart("_Test Item", 0)
		
		quotation = _get_cart_quotation()
		self.assertEquals(quotation0.doc.name, quotation.doc.name)
		
		quotation_items = quotation.doclist.get({"parentfield": "quotation_details", "item_code": "_Test Item"})
		self.assertEquals(quotation_items, [])
		
	def test_place_order(self):
		quotation = self.test_update_cart()
		sales_order_name = place_order()
		sales_order = webnotes.bean("Sales Order", sales_order_name)
		self.assertEquals(sales_order.doclist.getone({"item_code": "_Test Item"}).prevdoc_docname, quotation.doc.name)
		