#from django.shortcuts import render

from system_administration.serializers import UserSerializer
from system_administration.utils import get_staff_profile_data
from access_control.permissions import user_has_permission, user_can_at_branch
from warehouse_management.models import Category, PurchaseRequisitionInstance
from warehouse_management.requisition_helpers import enrich_purchase_requisition_map
from .supplier_helpers import supplier_documents_list
from .models import *
from .serializers import *
from rest_framework.permissions import IsAuthenticated
from rest_framework.authentication import TokenAuthentication
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.response import Response
from django.contrib.auth.models import User
from datetime import datetime
import json
import logging
from django.http import JsonResponse
from django.contrib.auth import authenticate, login, logout

logger = logging.getLogger(__name__)

@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def procurement_dashboard(request):
    date_format = '%d/%m/%Y, %H:%M'
    company_serial_number = request.data.get("serial_number", "")
    active_user = request.user
    payload = {}
    supplier_list = []
    supplier_map = {}
    supplied_products_list = []
    supplied_product_map = {}
    company_profile_map = {}
    company_branches_list = []
    company_branch_map = {}
    purchase_order_list = []
    purchase_order_map = {}
    stock_order_list = []
    stock_order_map = {}
    purchase_order_product_instances_list = []
    purchase_order_product_instance_map = {}
    stock_order_instances_list = []
    stock_order_instance_map = {}
    creator_map = {}
    category_map = {}
    category_list = []
    product_map = {}
    product_list = []
    try:
        if not company_serial_number:
            return Response({"message": "serial_number is required", "payload": payload}, status=400)
        try:
            company_profile = CompanyProfile.objects.get(
                company_serial_number=company_serial_number)
        except CompanyProfile.DoesNotExist:
            company_profile = CompanyProfile.objects.order_by("id").first()
            if company_profile is None:
                return Response({"message": "No company found for this serial number", "payload": payload}, status=404)
        all_suppliers = Supplier.objects.all().order_by("-id")
        all_purchase_orders = PurchaseOrder.objects.all().order_by("-id")
        #
        staff_profile = StaffProfile.objects.get(user=active_user)
        if company_profile and user_has_permission(staff_profile, "procurement.dashboard.view"):
            active_staff_profile_data = get_staff_profile_data(active_user)
            company_profile_map["company_id"] = str(company_profile.id)
            company_profile_map["company_name"] = company_profile.company_name
            company_profile_map["company_phone"] = company_profile.company_phone
            all_branches = company_profile.company_branches.all()
            all_categories = Category.objects.all().order_by("-id")
            for category in all_categories:
                if category.recycle_bin != True:
                    category_map = {}
                    product_list = []
                    category_map["category_id"] = str(category.id)
                    category_map["category_name"] = category.category_name
                    category_map["category_description"] = category.category_description
                    category_products = category.category_products.all().order_by("-id")
                    for product in category_products:
                        if product.recycle_bin != True:
                            product_map = {}
                            product_image_catalogues_list = []
                            product_map["product_id"] = str(product.id)
                            product_map["product_name"] = product.product_name
                            product_map["stock_keeping_unit"] = product.stock_keeping_unit
                            product_map["unit_of_measurement"] = product.unit_of_measurement
                            product_map["product_description"] = product.product_description
                            # product_map["product_description"] = product.product_description
                            product_image_catalogue = product.product_images.all().order_by("-id")
                            for product_image in product_image_catalogue:
                                product_image_catalogue_map = {}
                                product_image_catalogue_map["product_image_id"] = str(
                                    product_image.id)
                                product_image_catalogue_map["product_image_url"] = product_image.product_image.url
                                product_image_catalogue_map["image_attribute"] = product_image.image_attribute
                                product_image_catalogue_map["use_as_main_image"] = "true" if product_image.use_as_main_image == True else "false"
                                product_image_catalogues_list.append(
                                    product_image_catalogue_map)
                            product_map["product_image_catalogues_list"] = product_image_catalogues_list
                            product_list.append(product_map)
                    category_map["product_list"] = product_list
                    category_list.append(category_map)
            for branch in all_branches:
                if branch.recycle_bin != True:
                    company_branch_map = {}
                    stock_order_list = []
                    company_branch_map["branch_id"] = str(branch.id)
                    company_branch_map["branch_name"] = branch.branch_name
                    company_branch_map["is_main_branch"] = "true" if branch.main_branch == True else "false"
                    branch_stock_orders = branch.branch_stock_orders.all()
                    for stock_order in branch_stock_orders:
                        if stock_order.recycle_bin != True:
                            stock_order_map = {}
                            stock_order_instances_list = []
                            stock_order_map["stock_order_id"] = str(stock_order.id)
                            stock_order_map["stock_order_number"] = stock_order.stock_order_number
                            stock_order_map["stock_order_approved"] = "true" if stock_order.stock_order_approved == True else "false"
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                stock_order.created_by.id) if stock_order.created_by is not None else ""
                            creator_map["staff_name"] = f'{stock_order.created_by.first_name} {stock_order.created_by.last_name}' if stock_order.created_by is not None else ""
                            creator_map["staff_position"] = stock_order.created_by.staff_position.position_title if stock_order.created_by is not None and stock_order.created_by.staff_position is not None else ""
                            stock_order_map["created_by"] = creator_map
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                stock_order.last_updated_by.id) if stock_order.last_updated_by is not None else ""
                            creator_map["staff_name"] = f'{stock_order.last_updated_by.first_name} {stock_order.last_updated_by.last_name}' if stock_order.last_updated_by is not None else ""
                            creator_map["staff_position"] = stock_order.last_updated_by.staff_position.position_title if stock_order.last_updated_by is not None and stock_order.last_updated_by.staff_position is not None else ""
                            stock_order_map["last_updated_by"] = creator_map
                            stock_order_map["created_on"] = datetime.strftime(
                                stock_order.created_on, date_format) if stock_order.created_on is not None else ""
                            stock_order_map["last_updated_on"] = datetime.strftime(
                                stock_order.last_updated_on, date_format) if stock_order.last_updated_on is not None else ""
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                stock_order.stock_order_approved_by.id) if stock_order.stock_order_approved_by is not None else ""
                            creator_map["staff_name"] = f'{stock_order.stock_order_approved_by.first_name} {stock_order.stock_order_approved_by.last_name}' if stock_order.stock_order_approved_by is not None else ""
                            creator_map["staff_position"] = stock_order.stock_order_approved_by.staff_position.position_title if stock_order.stock_order_approved_by is not None and stock_order.stock_order_approved_by.staff_position is not None else ""
                            stock_order_map["stock_order_approved_by"] = creator_map
                            stock_order_product_instances = stock_order.stock_order_product_instances.all()
                            for stock_order_product_instance in stock_order_product_instances:
                                stock_order_instance_map = {}
                                stock_order_instance_map["stock_order_product_instance_id"] = str(
                                    stock_order_product_instance.id)
                                stock_order_instance_map["stock_requisition_instance_id"] = str(
                                    stock_order_product_instance.stock_requisition_instance.id) if stock_order_product_instance.stock_requisition_instance is not None else ""
                                stock_order_instance_map["stock_order_item_delivered"] = "true" if stock_order_product_instance.stock_order_item_delivered == True else "false"
                                stock_order_instance_map["quantity_delivered"] = stock_order_product_instance.quantity_delivered
                                stock_order_instances_list.append(
                                    stock_order_instance_map)
                            stock_order_map["stock_order_instances_list"] = stock_order_instances_list
                            stock_order_list.append(stock_order_map)
                    company_branch_map["stock_order_list"] = stock_order_list
                    company_branches_list.append(company_branch_map)
            company_profile_map["company_branches_list"] = company_branches_list
            for supplier in all_suppliers:
                if supplier.recycle_bin != True:
                    supplier_map = {}
                    supplied_products_list = []
                    supplier_map["supplier_id"] = str(supplier.id)
                    supplier_map["preferred_currency"] = company_profile.company_preferred_currency
                    supplier_map["supplier_name"] = supplier.supplier_name
                    supplier_map["supplier_phone"] = supplier.supplier_phone
                    supplier_map["supplier_email"] = supplier.supplier_email
                    supplier_map["supplier_address"] = supplier.supplier_address
                    supplier_map["supplier_description"] = supplier.supplier_description
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        supplier.created_by.id) if supplier.created_by is not None else ""
                    creator_map["staff_name"] = f'{supplier.created_by.first_name} {supplier.created_by.last_name}' if supplier.created_by is not None else ""
                    creator_map["staff_position"] = supplier.created_by.staff_position.position_title if supplier.created_by is not None and supplier.created_by.staff_position is not None else ""
                    supplier_map["created_by"] = creator_map
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        supplier.last_updated_by.id) if supplier.last_updated_by is not None else ""
                    creator_map["staff_name"] = f'{supplier.last_updated_by.first_name} {supplier.last_updated_by.last_name}' if supplier.last_updated_by is not None else ""
                    creator_map["staff_position"] = supplier.last_updated_by.staff_position.position_title if supplier.last_updated_by is not None and supplier.last_updated_by.staff_position is not None else ""
                    supplier_map["last_updated_by"] = creator_map
                    supplier_map["created_on"] = datetime.strftime(
                        supplier.created_on, date_format) if supplier.created_on is not None else ""
                    supplier_map["last_updated_on"] = datetime.strftime(
                        supplier.last_updated_on, date_format) if supplier.last_updated_on is not None else ""
                    #supplied products
                    supplied_products = supplier.supplied_products.all()
                    for supplied_product in supplied_products:
                        supplied_product_map = {}
                        supplied_product_map["product_id"] = str(supplied_product.id)
                        supplied_product_map["product_name"] = supplied_product.product_name
                        supplied_products_list.append(supplied_product_map)
                    supplier_map["supplied_products_list"] = supplied_products_list
                    #supllier payment details
                    supplier_payment_details = supplier.supplier_payment_details.all().order_by("-id")
                    supplier_payment_details_list = []
                    for supplier_payment_detail in supplier_payment_details:
                        supplier_payment_detail_map = {}
                        supplier_payment_detail_map["supplier_payment_detail_id"] = str(supplier_payment_detail.id)
                        supplier_payment_detail_map["bank_institution_name"] = supplier_payment_detail.banking_institution_name
                        supplier_payment_detail_map["bank_account_name"] = supplier_payment_detail.bank_account_name
                        supplier_payment_detail_map["bank_account_number"] = supplier_payment_detail.bank_account_number
                        supplier_payment_detail_map["bank_branch_name"] = supplier_payment_detail.bank_branch_name
                        supplier_payment_detail_map["bank_branch_code"] = supplier_payment_detail.bank_branch_code
                        supplier_payment_detail_map["bank_swift_code"] = supplier_payment_detail.bank_swift_code
                        supplier_payment_detail_map["created_on"] = datetime.strftime(
                            supplier_payment_detail.created_on, date_format) if supplier_payment_detail.created_on is not None else ""
                        supplier_payment_detail_map["last_updated_on"] = datetime.strftime(
                            supplier_payment_detail.last_updated_on, date_format) if supplier_payment_detail.last_updated_on is not None else ""
                        supplier_payment_details_list.append(supplier_payment_detail_map)
                    supplier_map["supplier_payment_details_list"] = supplier_payment_details_list
                    supplier_product_purchase_instances = supplier.supplier_product_purchase_instances.all().order_by("-id")
                    supplied_product_history_list = []
                    for supplied_product in supplier_product_purchase_instances:
                        if supplied_product.recycle_bin != True:
                            supplied_product_map = {}
                            supplied_product_map["purchase_order_number"] = supplied_product.purchase_order.purchase_order_number if supplied_product.purchase_order is not None else ""
                            try:
                                supplied_product_map["purchase_requisition_number"] = supplied_product.purchase_requisition_instance.purchase_requisition.purchase_requisition_number
                            except:
                                supplied_product_map["purchase_requisition_number"] = "Deleted"
                            supplied_product_map["quantity_delivered"] = supplied_product.quantity_delivered
                            supplied_product_map["purchase_value_per_unit"] = supplied_product.purchase_value_per_unit
                            supplied_product_map["purchase_value_overall"] = supplied_product.purchase_value_overall
                            supplied_product_map["purchase_amount_paid_to_supplier"] = supplied_product.purchase_amount_paid_to_supplier
                            supplied_product_map["supplier_payment_settled"] = "true" if supplied_product.supplier_payment_settled == True else "false"
                            supplied_product_map["product_purchase_delivered"] = "true" if supplied_product.product_purchase_delivered == True else "false"
                            try:
                                supplied_product_map["product_name"] = supplied_product.purchase_requisition_instance.product.product_name
                            except:
                                supplied_product_map["product_name"] = "Deleted product"
                            supplied_product_history_list.append(supplied_product_map)
                    supplier_map["supplied_product_history_list"] = supplied_product_history_list
                    supplier_list.append(supplier_map)
                    supplier_map["documents_list"] = supplier_documents_list(supplier, date_format)
            for purchase_order in all_purchase_orders:
                if purchase_order.recycle_bin != True:
                    purchase_order_map = {}
                    purchase_order_product_instances_list = []
                    purchase_order_map["purchase_order_id"] = str(purchase_order.id)
                    purchase_order_map["purchase_order_number"] = purchase_order.purchase_order_number
                    purchase_order_map["purchase_value_overall"] = purchase_order.purchase_value_overall
                    purchase_order_map["purchase_order_approved"] = "true" if purchase_order.purchase_order_approved == True else "false"
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        purchase_order.created_by.id) if purchase_order.created_by is not None else ""
                    creator_map["staff_name"] = f'{purchase_order.created_by.first_name} {purchase_order.created_by.last_name}' if purchase_order.created_by is not None else ""
                    creator_map["staff_position"] = purchase_order.created_by.staff_position.position_title if purchase_order.created_by is not None and purchase_order.created_by.staff_position is not None else ""
                    purchase_order_map["created_by"] = creator_map
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        purchase_order.last_updated_by.id) if purchase_order.last_updated_by is not None else ""
                    creator_map["staff_name"] = f'{purchase_order.last_updated_by.first_name} {purchase_order.last_updated_by.last_name}' if purchase_order.last_updated_by is not None else ""
                    creator_map["staff_position"] = purchase_order.last_updated_by.staff_position.position_title if purchase_order.last_updated_by is not None and purchase_order.last_updated_by.staff_position is not None else ""
                    purchase_order_map["last_updated_by"] = creator_map
                    purchase_order_map["created_on"] = datetime.strftime(
                        purchase_order.created_on, date_format) if purchase_order.created_on is not None else ""
                    purchase_order_map["last_updated_on"] = datetime.strftime(
                        purchase_order.last_updated_on, date_format) if purchase_order.last_updated_on is not None else ""
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        purchase_order.purchase_order_approved_by.id) if purchase_order.purchase_order_approved_by is not None else ""
                    creator_map["staff_name"] = f'{purchase_order.purchase_order_approved_by.first_name} {purchase_order.purchase_order_approved_by.last_name}' if purchase_order.purchase_order_approved_by is not None else ""
                    creator_map["staff_position"] = purchase_order.purchase_order_approved_by.staff_position.position_title if purchase_order.purchase_order_approved_by is not None and purchase_order.purchase_order_approved_by.staff_position is not None else ""
                    purchase_order_map["purchase_order_approved_by"] = creator_map
                    purchase_order_product_instances = purchase_order.purchase_order_product_instances.all()
                    for purchase_order_product_instance in purchase_order_product_instances:
                        if purchase_order_product_instance.recycle_bin != True:
                            purchase_order_product_instance_map = {}
                            purchase_order_product_instance_map[
                                "purchase_order_product_instance_id"] = str(purchase_order_product_instance.id)
                            # Keep the legacy key name expected by Flutter/Vue payloads.
                            requisition_instance = purchase_order_product_instance.purchase_requisition_instance
                            purchase_order_product_instance_map["purchase_requisition_instance_id"] = str(
                                requisition_instance.id) if requisition_instance is not None else ""
                            purchase_order_product_instance_map["purchase_requisition_number"] = (
                                requisition_instance.purchase_requisition.purchase_requisition_number
                                if requisition_instance is not None
                                and requisition_instance.purchase_requisition is not None else ""
                            )
                            purchase_order_product_instance_map["product_name"] = (
                                requisition_instance.product.product_name
                                if requisition_instance is not None
                                and requisition_instance.product is not None else ""
                            )
                            purchase_order_product_instance_map["supplier_id"] = str(
                                purchase_order_product_instance.supplier.id) if purchase_order_product_instance.supplier is not None else ""
                            purchase_order_product_instance_map[
                                "purchase_value_per_unit"] = purchase_order_product_instance.purchase_value_per_unit
                            purchase_order_product_instance_map["cost_currency"] = (
                                purchase_order_product_instance.cost_currency or 'kes'
                            )
                            purchase_order_product_instance_map["exchange_rate"] = (
                                purchase_order_product_instance.exchange_rate or '1.00'
                            )
                            purchase_order_product_instance_map[
                                "purchase_value_overall"] = purchase_order_product_instance.purchase_value_overall
                            purchase_order_product_instance_map[
                                "purchase_amount_paid_to_supplier"] = purchase_order_product_instance.purchase_amount_paid_to_supplier
                            purchase_order_product_instance_map[
                                "supplier_payment_settled"] = "true" if purchase_order_product_instance.supplier_payment_settled == True else "false"
                            purchase_order_product_instance_map[
                                "product_purchase_delivered"] = "true" if purchase_order_product_instance.product_purchase_delivered == True else "false"
                            purchase_order_product_instance_map[
                                "quantity_delivered"] = purchase_order_product_instance.quantity_delivered
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                purchase_order_product_instance.created_by.id) if purchase_order_product_instance.created_by is not None else ""
                            creator_map["staff_name"] = f'{purchase_order_product_instance.created_by.first_name} {purchase_order_product_instance.created_by.last_name}' if purchase_order_product_instance.created_by is not None else ""
                            creator_map["staff_position"] = purchase_order_product_instance.created_by.staff_position.position_title if purchase_order_product_instance.created_by is not None and purchase_order_product_instance.created_by.staff_position is not None else ""
                            purchase_order_product_instance_map["created_by"] = creator_map
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                purchase_order_product_instance.last_updated_by.id) if purchase_order_product_instance.last_updated_by is not None else ""
                            creator_map["staff_name"] = f'{purchase_order_product_instance.last_updated_by.first_name} {purchase_order_product_instance.last_updated_by.last_name}' if purchase_order_product_instance.last_updated_by is not None else ""
                            creator_map["staff_position"] = purchase_order_product_instance.last_updated_by.staff_position.position_title if purchase_order_product_instance.last_updated_by is not None and purchase_order_product_instance.last_updated_by.staff_position is not None else ""
                            purchase_order_product_instance_map["last_updated_by"] = creator_map
                            purchase_order_product_instance_map["created_on"] = datetime.strftime(
                                purchase_order_product_instance.created_on, date_format) if purchase_order_product_instance.created_on is not None else ""
                            purchase_order_product_instance_map["last_updated_on"] = datetime.strftime(
                                purchase_order_product_instance.last_updated_on, date_format) if purchase_order_product_instance.last_updated_on is not None else ""
                            purchase_order_product_instances_list.append(
                                purchase_order_product_instance_map)
                    purchase_order_map["purchase_order_product_instances_list"] = purchase_order_product_instances_list
                    purchase_order_list.append(purchase_order_map)
            payload["purchase_order_list"] = purchase_order_list
            payload["supplier_list"] = supplier_list
            payload["company_profile"] = company_profile_map
            payload["active_staff_profile_data"] = active_staff_profile_data
            payload["category_list"] = category_list
            return Response({"message": "true", "payload": payload}, status=200)
        else:
            return Response({"message": "false", "payload": payload}, status=401)
    except StaffProfile.DoesNotExist:
        return Response({"message": "Staff profile not found for active user", "payload": payload}, status=404)
    except Exception as e:
        logger.exception("procurement_dashboard failed")
        return Response({"message": "false", "payload": payload}, status=500)

@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_supplier(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    supplier_name = request.data["supplier_name"]
    supplier_phone = request.data["supplier_phone"]
    supplier_email = request.data["supplier_email"]
    supplier_address = request.data["supplier_address"]
    supplied_products_id_list = request.data.get('supplied_products_id_list', [])
    supplied_products_id_list = json.loads(supplied_products_id_list)
    supplier_description = request.data["supplier_description"]
    supplier_category = request.data.get("supplier_category", "secondary").lower()
    product_ids_list = []
    try:
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = StaffProfile.objects.get(user=active_user)
        if user_can_at_branch(staff_profile, "procurement.supplier.add", require_main_branch=True):
            serializers = UserSerializer(
                data={'username': supplier_email, 'password': supplier_phone})
            if serializers.is_valid():
                user = serializers.save()
                new_user = authenticate(
                    username=supplier_email, password=supplier_phone)
                for product_id in supplied_products_id_list:
                    product_ids_list.append(int(product_id))
                supplier_serializer = SupplierSerializer(
                    data={'user': new_user.id, 'company_profile': company_profile.id, 'supplier_name': supplier_name, 'supplier_phone': supplier_phone, 'supplier_email': supplier_email, 'supplier_address': supplier_address, 'supplier_description': supplier_description, 'supplier_category': supplier_category, 'supplied_products': product_ids_list, 'created_by': staff_profile.id,'last_updated_by':staff_profile.id})
                if supplier_serializer.is_valid():
                    new_supplier = supplier_serializer.save()
                    #create supplier payment details
                    SupplierPaymentDetails.objects.create(supplier=new_supplier)
                    return Response({"message": "Supplier account created successfully",}, status=200)
                else:
                    #print(supplier_serializer.errors)
                    return Response({"message": "Unable to create supplier account", }, status=406)
            else:
                #print(serializers.errors)
                error_messages = [str(value[0])
                                  for value in serializers.errors.values()]
                return Response({"message": error_messages[0], }, status=406)
        else:
            return Response({"message": "You are unauthorised to perform this action",}, status=401)
    except:# Exception as e:
        #print(e)
        return Response({"message": "Error creating supplier account",}, status=500)
    
@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_purchase_order(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    purchase_value_overall = 0.00
    purchase_order_instance_list = request.data.get(
        'purchase_order_instance_list', [])
    purchase_order_instance_list = json.loads(purchase_order_instance_list)
    try:
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = StaffProfile.objects.get(user=active_user)
        if user_can_at_branch(staff_profile, "procurement.purchase_order.add", require_main_branch=True):
            purchase_order_serializer = purchaseOrderSerializer(
                data={'company_profile': company_profile.id, 'purchase_value_overall': str(purchase_value_overall), 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
            if purchase_order_serializer.is_valid():
                new_purchase_order = purchase_order_serializer.save()
                #processing purchase order instance list
                for purchase_order_instance in purchase_order_instance_list:
                    purchase_requisition_instance_id = int(purchase_order_instance[
                        "purchase_requisition_instance_id"])
                    supplier_id = purchase_order_instance["supplier_id"]
                    purchase_requisition_instance = PurchaseRequisitionInstance.objects.get(
                        id=purchase_requisition_instance_id)
                    purchase_product_id = (
                        purchase_requisition_instance.product.id
                        if purchase_requisition_instance.product is not None else None
                    )
                    purchase_value_per_unit = purchase_order_instance["purchase_value_per_unit"]
                    purchase_instance_value_overall = purchase_order_instance["purchase_value_overall"]
                    purchase_amount_paid_to_supplier = purchase_order_instance[
                        "purchase_amount_paid_to_supplier"]
                    supplier_payment_settled = True if purchase_order_instance["supplier_payment_settled"] == "true" else False
                    product_purchase_delivered = True if purchase_order_instance["product_purchase_delivered"] == "true" else False
                    quantity_delivered = purchase_order_instance["quantity_delivered"]
                    quantity_purchased = purchase_order_instance["quantity_purchased"]
                    cost_currency = purchase_order_instance.get("cost_currency", "kes")
                    exchange_rate = purchase_order_instance.get("exchange_rate", "1.00")
                    purchase_order_instance_serializer = productPurchaseInstanceSerializer(data={
                        'purchase_order': new_purchase_order.id, 'purchase_requisition_instance': purchase_requisition_instance_id, 'purchase_product': purchase_product_id, 'supplier': supplier_id, 'purchase_value_per_unit': purchase_value_per_unit, 'purchase_value_overall': purchase_instance_value_overall, 'purchase_amount_paid_to_supplier': purchase_amount_paid_to_supplier, 'supplier_payment_settled': supplier_payment_settled, 'product_purchase_delivered': product_purchase_delivered, 'quantity_delivered': quantity_delivered, 'quantity_purchased': quantity_purchased, 'cost_currency': cost_currency, 'exchange_rate': exchange_rate, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
                    if purchase_order_instance_serializer.is_valid():
                        purchase_order_instance_serializer.save()
                        purchase_requisition_instance.purchase_requisition_items_purchased = True
                        purchase_requisition_instance.last_updated_by = staff_profile
                        purchase_requisition_instance.save()
                        purchase_value_overall += float(purchase_instance_value_overall)
                new_purchase_order.purchase_value_overall = str(purchase_value_overall)
                new_purchase_order.save()
                return Response({"message": "Purchase order created successfully", }, status=200)
            else:
                error_messages = [str(value[0])
                                  for value in purchase_order_serializer.errors.values()]
                return Response({"message": error_messages[0], }, status=406)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except:
        return Response({"message": "Error creating purchase order", }, status=500)
    
@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_stock_order(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    stock_order_instance_list = request.data.get(
        'stock_order_instance_list', [])
    stock_order_instance_list = json.loads(stock_order_instance_list)
    company_branch_id = int(request.data["company_branch_id"])
    try:
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = StaffProfile.objects.get(user=active_user)
        if user_can_at_branch(staff_profile, "procurement.stock_order.add", require_main_branch=False):
            stock_order_serializer = stockOrderSerializer(data={
                'company_branch': company_branch_id,
                'created_by':staff_profile.id,
                'last_updated_by': staff_profile.id,
            })
            if stock_order_serializer.is_valid():
                new_stock_order = stock_order_serializer.save()
                for stock_order_instance in stock_order_instance_list:
                    stock_requisition_instance_id = int(
                        stock_order_instance["stock_requisition_instance"])
                    stock_order_item_delivered = True if stock_order_instance[
                        "stock_order_item_delivered"] == "true" else False
                    quantity_ordered = stock_order_instance["quantity_ordered"]
                    quantity_delivered = stock_order_instance["quantity_delivered"]
                    stock_order_instance_serializer = stockOrderInstanceSerializer(
                        data={'stock_order': new_stock_order.id, 'stock_requisition_instance': stock_requisition_instance_id, 'stock_order_item_delivered': stock_order_item_delivered, 'quantity_ordered': quantity_ordered, 'quantity_delivered': quantity_delivered, 'created_by': staff_profile.id,
                              'last_updated_by': staff_profile.id,})
                    if stock_order_instance_serializer.is_valid():
                        stock_order_instance_serializer.save()
                return Response({"message": "Stock order created successfully", }, status=200)
            else:
                error_messages = [str(value[0])
                                  for value in stock_order_serializer.errors.values()]
                return Response({"message": error_messages[0], }, status=406)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except:
        return Response({"message": "Error creating stock order", }, status=500)
    

@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def delete_supplier(request):
    active_user = request.user
    supplier_id_to_edit = request.data["supplier_id_to_edit"]
    company_serial_number = request.data["serial_number"]
    try:
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = StaffProfile.objects.get(user=active_user)
        if user_has_permission(staff_profile, "procurement.supplier.delete"):
            supplier_instance = Supplier.objects.get(id=int(supplier_id_to_edit))
            supplier_instance.user.delete()
            return Response({"message": "You have permanently deleted supplier successfully", }, status=200)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except:  # Exception as e:
        # print(e)
        return Response({"message": "Error deleting supplier", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def edit_supplier(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    supplier_id_to_edit = request.data["supplier_id_to_edit"]
    supplier_name = request.data["supplier_name"]
    supplier_phone = request.data["supplier_phone"]
    supplier_email = request.data["supplier_email"]
    supplier_address = request.data["supplier_address"]
    supplied_products_id_list = request.data.get(
        'supplied_products_id_list', [])
    supplied_products_id_list = json.loads(supplied_products_id_list)
    supplier_description = request.data["supplier_description"]
    supplier_category = request.data.get("supplier_category", "secondary").lower()
    product_ids_list = []
    try:
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = StaffProfile.objects.get(user=active_user)
        if user_can_at_branch(staff_profile, "procurement.supplier.edit", require_main_branch=True):
            supplier_instance = Supplier.objects.get(id=int(supplier_id_to_edit))
            supplier_instance.supplied_products.clear()
            supplier_instance.save()
            new_instance = Supplier.objects.get(id=int(supplier_id_to_edit))
            for product_id in supplied_products_id_list:
                product_ids_list.append(int(product_id))
            supplier_serializer = SupplierSerializer(instance=new_instance,
                data={'supplier_name': supplier_name, 'supplier_phone': supplier_phone, 'supplier_email': supplier_email, 'supplier_address': supplier_address, 'supplier_description': supplier_description, 'supplier_category': supplier_category, 'supplied_products': product_ids_list,'last_updated_by': staff_profile.id})
            if supplier_serializer.is_valid():
                supplier_serializer.save()
                return Response({"message": "Supplier details updated successfully", }, status=200)
            else:
                error_messages = [str(value[0])
                                  for value in supplier_serializer.errors.values()]
                return Response({"message": error_messages[0], }, status=406)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except:# Exception as e:
        #print(e)
        return Response({"message": "Error updating supplier details", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def edit_supplier_payment(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    supplier_payment_detail_id = request.data["supplier_payment_detail_id"]
    banking_institution_name = request.data["banking_institution_name"]
    bank_account_name = request.data["bank_account_name"]
    bank_account_number = request.data["bank_account_number"]
    bank_branch_name = request.data["bank_branch_name"]
    bank_swift_code = request.data["bank_swift_code"]
    bank_branch_code = request.data["bank_branch_code"]
    try:
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = StaffProfile.objects.get(user=active_user)
        if user_can_at_branch(staff_profile, "procurement.supplier_payment.edit", require_main_branch=True):
            supplier_payment_detail = SupplierPaymentDetails.objects.get(
                id=int(supplier_payment_detail_id))
            supplier_payment_detail_serializer = SupplierPaymentDetailsSerializer(
                instance=supplier_payment_detail, data={'banking_institution_name': banking_institution_name, 'bank_account_name': bank_account_name, 'bank_account_number': bank_account_number, 'bank_branch_name': bank_branch_name, 'bank_swift_code': bank_swift_code, 'bank_branch_code': bank_branch_code})
            if supplier_payment_detail_serializer.is_valid():
                supplier_payment_detail_serializer.save()
                return Response({"message": "Supplier bank details updated successfully", }, status=200)
            else:
                error_messages = [str(value[0])
                                  for value in supplier_payment_detail_serializer.errors.values()]
                return Response({"message": error_messages[0], }, status=406)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except:  # Exception as e:
        # print(e)
        return Response({"message": "Error updating supplier bank details", }, status=500)

    

def _can_manage_supplier_documents(staff_profile, codename):
    # Supplier documents piggy-back on the supplier feature's permissions.
    return user_has_permission(staff_profile, codename)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def add_supplier_document(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    supplier_id = request.data["supplier_id"]
    document_name = request.data.get("document_name", "")
    document_type = request.data.get("document_type", "other")
    content_type = request.data.get("content_type", "application/octet-stream")
    file_data_base64 = request.data.get("file_data_base64", "")
    try:
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = StaffProfile.objects.get(user=active_user)
        if _can_manage_supplier_documents(staff_profile, "procurement.supplier.edit"):
            supplier = Supplier.objects.get(id=int(supplier_id), recycle_bin=False)
            SupplierDocument.objects.create(
                supplier=supplier,
                document_name=document_name,
                document_type=document_type,
                content_type=content_type,
                file_data_base64=file_data_base64,
                uploaded_by=staff_profile,
            )
            return Response({"message": "Supplier document uploaded successfully", }, status=200)
        return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except Supplier.DoesNotExist:
        return Response({"message": "Supplier not found", }, status=404)
    except:
        return Response({"message": "Error uploading supplier document", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def delete_supplier_document(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    document_id = request.data["document_id"]
    try:
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = StaffProfile.objects.get(user=active_user)
        if _can_manage_supplier_documents(staff_profile, "procurement.supplier.delete"):
            document = SupplierDocument.objects.get(id=int(document_id), recycle_bin=False)
            document.recycle_bin = True
            document.save()
            return Response({"message": "Supplier document deleted successfully", }, status=200)
        return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except SupplierDocument.DoesNotExist:
        return Response({"message": "Document not found", }, status=404)
    except:
        return Response({"message": "Error deleting supplier document", }, status=500)