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

from __future__ import unicode_literals
import frappe
from frappe.utils import flt, cstr, cint
from frappe import _
import json

from erpnext.stock.doctype.item.item import get_last_purchase_details
from erpnext.stock.doctype.item.item import validate_end_of_life

def update_last_purchase_rate(doc, is_submit):
	"""updates last_purchase_rate in item table for each item"""
	import frappe.utils
	this_purchase_date = frappe.utils.getdate(doc.get('posting_date') or doc.get('transaction_date'))

	for d in doc.get("items"):
		# get last purchase details
		last_purchase_details = get_last_purchase_details(d.item_code, doc.name)

		# compare last purchase date and this transaction's date
		last_purchase_rate = None
		if last_purchase_details and \
				(doc.get('docstatus') == 2 or last_purchase_details.purchase_date > this_purchase_date):
			last_purchase_rate = last_purchase_details['base_net_rate']
		elif is_submit == 1:
			# even if this transaction is the latest one, it should be submitted
			# for it to be considered for latest purchase rate
			if flt(d.conversion_factor):
				last_purchase_rate = flt(d.base_net_rate) / flt(d.conversion_factor)
			# Check if item code is present
			# Conversion factor should not be mandatory for non itemized items
			elif d.item_code:
				frappe.throw(_("UOM Conversion factor is required in row {0}").format(d.idx))

		# update last purchsae rate
		if last_purchase_rate:
			frappe.db.sql("""update `tabItem` set last_purchase_rate = %s where name = %s""",
				(flt(last_purchase_rate), d.item_code))

def validate_for_items(doc):
	items = []
	for d in doc.get("items"):
		if not d.qty:
			if doc.doctype == "Purchase Receipt" and d.rejected_qty:
				continue
			frappe.throw(_("Please enter quantity for Item {0}").format(d.item_code))

		# update with latest quantities
		bin = frappe.db.sql("""select projected_qty from `tabBin` where
			item_code = %s and warehouse = %s""", (d.item_code, d.warehouse), as_dict=1)

		f_lst ={'projected_qty': bin and flt(bin[0]['projected_qty']) or 0, 'ordered_qty': 0, 'received_qty' : 0}
		if d.doctype in ('Purchase Receipt Item', 'Purchase Invoice Item'):
			f_lst.pop('received_qty')
		for x in f_lst :
			if d.meta.get_field(x):
				d.set(x, f_lst[x])

		item = frappe.db.sql("""select is_stock_item,
			is_sub_contracted_item, end_of_life, disabled from `tabItem` where name=%s""",
			d.item_code, as_dict=1)[0]

		validate_end_of_life(d.item_code, item.end_of_life, item.disabled)

		# validate stock item
		if item.is_stock_item==1 and d.qty and not d.warehouse and not d.get("delivered_by_supplier"):
			frappe.throw(_("Warehouse is mandatory for stock Item {0} in row {1}").format(d.item_code, d.idx))

		items.append(cstr(d.item_code))

	if items and len(items) != len(set(items)) and \
		not cint(frappe.db.get_single_value("Buying Settings", "allow_multiple_items") or 0):
		frappe.throw(_("Same item cannot be entered multiple times."))

def check_on_hold_or_closed_status(doctype, docname):
	status = frappe.db.get_value(doctype, docname, "status")

	if status in ("Closed", "On Hold"):
		frappe.throw(_("{0} {1} status is {2}").format(doctype, docname, status), frappe.InvalidStatusError)

@frappe.whitelist()
def get_linked_material_requests(items):
	items = json.loads(items)
	mr_list = []
	for item in items:
		material_request = frappe.db.sql("""SELECT distinct mr.name AS mr_name,
				(mr_item.qty - mr_item.ordered_qty) AS qty,
				mr_item.item_code AS item_code,
				mr_item.name AS mr_item
			FROM `tabMaterial Request` mr, `tabMaterial Request Item` mr_item
			WHERE mr.name = mr_item.parent
				AND mr_item.item_code = %(item)s
				AND mr.material_request_type = 'Purchase'
				AND mr.per_ordered < 99.99
				AND mr.docstatus = 1
				AND mr.status != 'Stopped'
                        ORDER BY mr_item.item_code ASC""",{"item": item}, as_dict=1)
		if material_request:
			mr_list.append(material_request)

	return mr_list

