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

from __future__ import unicode_literals
import webnotes
from webnotes import msgprint, _, throw
from webnotes.utils import getdate, flt, add_days, cstr
import json

@webnotes.whitelist()
def get_item_details(args):
	"""
		args = {
			"doctype": "",
			"docname": "",
			"item_code": "",
			"warehouse": None,
			"supplier": None,
			"transaction_date": None,
			"conversion_rate": 1.0,
			"buying_price_list": None,
			"price_list_currency": None,
			"plc_conversion_rate": 1.0,
			"is_subcontracted": "Yes" / "No"
		}
	"""
	if isinstance(args, basestring):
		args = json.loads(args)
		
	args = webnotes._dict(args)
	
	item_bean = webnotes.bean("Item", args.item_code)
	item = item_bean.doc
	
	_validate_item_details(args, item)
	
	out = _get_basic_details(args, item_bean)
	
	out.supplier_part_no = _get_supplier_part_no(args, item_bean)
	
	if not out.warehouse:
		out.warehouse = item_bean.doc.default_warehouse
	
	if out.warehouse:
		out.projected_qty = get_projected_qty(item.name, out.warehouse)
	
	if args.transaction_date and item.lead_time_days:
		out.schedule_date = out.lead_time_date = add_days(args.transaction_date,
			item.lead_time_days)
			
	meta = webnotes.get_doctype(args.doctype)
	
	if meta.get_field("currency"):
		out.purchase_ref_rate = out.discount_rate = out.purchase_rate = \
			out.import_ref_rate = out.import_rate = 0.0
		out.update(_get_price_list_rate(args, item_bean, meta))
	
	if args.doctype == "Material Request":
		out.min_order_qty = flt(item.min_order_qty)
	
	return out
	
def _get_basic_details(args, item_bean):
	item = item_bean.doc
	
	out = webnotes._dict({
		"description": item.description_html or item.description,
		"qty": 1.0,
		"uom": item.stock_uom,
		"conversion_factor": 1.0,
		"warehouse": args.warehouse or item.default_warehouse,
		"item_tax_rate": json.dumps(dict(([d.tax_type, d.tax_rate] for d in 
			item_bean.doclist.get({"parentfield": "item_tax"})))),
		"batch_no": None,
		"expense_head": item.purchase_account \
			or webnotes.conn.get_value("Company", args.company, "default_expense_account"),
		"cost_center": item.cost_center
	})
	
	for fieldname in ("item_name", "item_group", "brand", "stock_uom"):
		out[fieldname] = item.fields.get(fieldname)
	
	return out
	
def _get_price_list_rate(args, item_bean, meta):
	from erpnext.utilities.transaction_base import validate_currency
	item = item_bean.doc
	out = webnotes._dict()
	
	# try fetching from price list
	if args.buying_price_list and args.price_list_currency:
		price_list_rate = webnotes.conn.sql("""select ref_rate from `tabItem Price` 
			where price_list=%s and item_code=%s and buying=1""", 
			(args.buying_price_list, args.item_code), as_dict=1)
		
		if price_list_rate:
			validate_currency(args, item_bean.doc, meta)
				
			out.import_ref_rate = flt(price_list_rate[0].ref_rate) * \
				flt(args.plc_conversion_rate) / flt(args.conversion_rate)
		
	# if not found, fetch from last purchase transaction
	if not out.import_ref_rate:
		last_purchase = get_last_purchase_details(item.name, args.docname, args.conversion_rate)
		if last_purchase:
			out.update(last_purchase)
	
	if out.import_ref_rate or out.import_rate:
		validate_currency(args, item, meta)
	
	return out
	
def _get_supplier_part_no(args, item_bean):
	item_supplier = item_bean.doclist.get({"parentfield": "item_supplier_details",
		"supplier": args.supplier})
	
	return item_supplier and item_supplier[0].supplier_part_no or None

def _validate_item_details(args, item):
	from erpnext.utilities.transaction_base import validate_item_fetch
	validate_item_fetch(args, item)
	
	# validate if purchase item or subcontracted item
	if item.is_purchase_item != "Yes":
		throw(_("Item") + (" %s: " % item.name) + _("not a purchase item"))
	
	if args.is_subcontracted == "Yes" and item.is_sub_contracted_item != "Yes":
		throw(_("Item") + (" %s: " % item.name) + 
			_("not a sub-contracted item.") +
			_("Please select a sub-contracted item or do not sub-contract the transaction."))

def get_last_purchase_details(item_code, doc_name=None, conversion_rate=1.0):
	"""returns last purchase details in stock uom"""
	# get last purchase order item details
	last_purchase_order = webnotes.conn.sql("""\
		select po.name, po.transaction_date, po.conversion_rate,
			po_item.conversion_factor, po_item.purchase_ref_rate, 
			po_item.discount_rate, po_item.purchase_rate
		from `tabPurchase Order` po, `tabPurchase Order Item` po_item
		where po.docstatus = 1 and po_item.item_code = %s and po.name != %s and 
			po.name = po_item.parent
		order by po.transaction_date desc, po.name desc
		limit 1""", (item_code, cstr(doc_name)), as_dict=1)

	# get last purchase receipt item details		
	last_purchase_receipt = webnotes.conn.sql("""\
		select pr.name, pr.posting_date, pr.posting_time, pr.conversion_rate,
			pr_item.conversion_factor, pr_item.purchase_ref_rate, pr_item.discount_rate,
			pr_item.purchase_rate
		from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pr_item
		where pr.docstatus = 1 and pr_item.item_code = %s and pr.name != %s and
			pr.name = pr_item.parent
		order by pr.posting_date desc, pr.posting_time desc, pr.name desc
		limit 1""", (item_code, cstr(doc_name)), as_dict=1)

	purchase_order_date = getdate(last_purchase_order and last_purchase_order[0].transaction_date \
		or "1900-01-01")
	purchase_receipt_date = getdate(last_purchase_receipt and \
		last_purchase_receipt[0].posting_date or "1900-01-01")

	if (purchase_order_date > purchase_receipt_date) or \
			(last_purchase_order and not last_purchase_receipt):
		# use purchase order
		last_purchase = last_purchase_order[0]
		purchase_date = purchase_order_date
		
	elif (purchase_receipt_date > purchase_order_date) or \
			(last_purchase_receipt and not last_purchase_order):
		# use purchase receipt
		last_purchase = last_purchase_receipt[0]
		purchase_date = purchase_receipt_date
		
	else:
		return webnotes._dict()
	
	conversion_factor = flt(last_purchase.conversion_factor)
	out = webnotes._dict({
		"purchase_ref_rate": flt(last_purchase.purchase_ref_rate) / conversion_factor,
		"purchase_rate": flt(last_purchase.purchase_rate) / conversion_factor,
		"discount_rate": flt(last_purchase.discount_rate),
		"purchase_date": purchase_date
	})

	conversion_rate = flt(conversion_rate) or 1.0
	out.update({
		"import_ref_rate": out.purchase_ref_rate / conversion_rate,
		"import_rate": out.purchase_rate / conversion_rate,
		"rate": out.purchase_rate
	})
	
	return out
	
@webnotes.whitelist()
def get_conversion_factor(item_code, uom):
	return {"conversion_factor": webnotes.conn.get_value("UOM Conversion Detail",
		{"parent": item_code, "uom": uom}, "conversion_factor")}
		
@webnotes.whitelist()
def get_projected_qty(item_code, warehouse):
	return webnotes.conn.get_value("Bin", {"item_code": item_code, 
			"warehouse": warehouse}, "projected_qty")