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


import json
from typing import Dict

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

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


def update_last_purchase_rate(doc, is_submit) -> None:
	"""updates last_purchase_rate in item table for each item"""

	this_purchase_date = 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) -> None:
	items = []
	for d in doc.get("items"):
		set_stock_levels(row=d)  # update with latest quantities
		item = validate_item_and_get_basic_data(row=d)
		validate_stock_item_warehouse(row=d, item=item)
		validate_end_of_life(d.item_code, item.end_of_life, item.disabled)

		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 set_stock_levels(row) -> None:
	projected_qty = frappe.db.get_value(
		"Bin",
		{
			"item_code": row.item_code,
			"warehouse": row.warehouse,
		},
		"projected_qty",
	)

	qty_data = {
		"projected_qty": flt(projected_qty),
		"ordered_qty": 0,
		"received_qty": 0,
	}
	if row.doctype in ("Purchase Receipt Item", "Purchase Invoice Item"):
		qty_data.pop("received_qty")

	for field in qty_data:
		if row.meta.get_field(field):
			row.set(field, qty_data[field])


def validate_item_and_get_basic_data(row) -> Dict:
	item = frappe.db.get_values(
		"Item",
		filters={"name": row.item_code},
		fieldname=["is_stock_item", "is_sub_contracted_item", "end_of_life", "disabled"],
		as_dict=1,
	)
	if not item:
		frappe.throw(_("Row #{0}: Item {1} does not exist").format(row.idx, frappe.bold(row.item_code)))

	return item[0]


def validate_stock_item_warehouse(row, item) -> None:
	if (
		item.is_stock_item == 1
		and row.qty
		and not row.warehouse
		and not row.get("delivered_by_supplier")
	):
		frappe.throw(
			_("Row #{1}: Warehouse is mandatory for stock Item {0}").format(
				frappe.bold(row.item_code), row.idx
			)
		)


def check_on_hold_or_closed_status(doctype, docname) -> None:
	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
