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


import json

import frappe
from frappe import _
from frappe.utils import cint, cstr, flt

from erpnext.stock.doctype.item.item import get_last_purchase_details, 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
		frappe.db.set_value("Item", d.item_code, "last_purchase_rate", flt(last_purchase_rate))


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
