"""Plugin to generate unique batch numbers"""

from plugin import InvenTreePlugin

from plugin.mixins import SettingsMixin, ValidationMixin

from part.models import Part

from django.core.exceptions import ValidationError

import logging

from . import PLUGIN_VERSION

from inventree.api import InvenTreeAPI
from inventree.stock import StockItem
from inventree.part import Part as PartAPI




logger = logging.getLogger("inventree")


class SSBatchNumberGenerator(SettingsMixin, ValidationMixin, InvenTreePlugin):

    """SSBatchNumberGenerator - custom InvenTree plugin."""

    # Plugin metadata
    TITLE = "SS Batch Number Generator"
    NAME = "SSBatchNumberGenerator"
    SLUG = "ss-batch-number-generator"
    DESCRIPTION = "Plugin to generate unique batch numbers"
    VERSION = PLUGIN_VERSION

    # Additional project information
    AUTHOR = "Rob Kettridge"
    WEBSITE = "https://www.smartsentry.co.uk"
    LICENSE = "MIT"

    # Optionally specify supported InvenTree versions
    # MIN_VERSION = '0.18.0'
    # MAX_VERSION = '2.0.0'

    
    
    
    # Plugin settings (from SettingsMixin)
    # Ref: https://docs.inventree.org/en/latest/plugins/mixins/settings/
    SETTINGS = {
        # Define your plugin settings here...
        "ACTIVE": {
            "name": "Active",
            "description": "Batch number generator is active",
            "validator": bool,
            "default": True,
        },
        "PREFIX": {
            "name": "Batch Prefix",
            "description": "Prefix for autogenerated batch numbers",
            "default": "SS_",
        },
        "PADDING": {
            "name": "Padding",
            "description": "Number of digits in batch number",
            "validator": int,
            "default": 5,
        },
        "SERVER_ADDRESS": {
            "name": "Server Address",
            "description": "URL for InvenTree API",
            "default": "http://127.0.0.1:8000",
        },

        #"USERNAME": {
        #    "name": "Username",
        #    "description": "Username for InvenTree API",
        #},

        #"PASSWORD": {
        #    "name": "Password",
        #    "description": "Password for InvenTree API",

        #},

        "ACCESS_TOKEN": {
            "name": "Access Token",
            "description": "Access token for InvenTree API (alternative to username/password)",
        },

        "DUMMY_PART": {
            "name": "Dummy Part",
            "description": "Inventree part number for dummy part to use to store metadata",
            "validator": int,
            "default": 1,
        },

        "DEBUG": {
            "name": "Debug",
            "description": "Print debug information to console",
            "validator": bool,
            "default": False,
        },
    }
    
    
    

    # Custom data validation (from ValidationMixin)
    # Ref: https://docs.inventree.org/en/latest/plugins/mixins/validation/
    
    def generate_batch_code(self, **kwargs):
        """
        if self.get_setting('DEBUG'):
            print("[BATCH SCRIPT DEBUG] generate_batch_code called with kwargs: " + str(kwargs))

        if not self.get_setting("ACTIVE"):
            return False

        # init batch variable
        batch = None

        # get padding setting from settings
        padding = self.get_setting('PADDING')

        #define API connection using access token
        api = InvenTreeAPI(self.get_setting('SERVER_ADDRESS'), token=self.get_setting('ACCESS_TOKEN'))

        #create part API object for part with pk=3 (for testing, will need to be changed to work with any part)
        part = PartAPI(api, pk=self.get_setting('DUMMY_PART'))

        # Uncomment to clear out metadata for testing
        #part.setMetadata({"batch": None})

        #get metadata for dummy part
        metadata = part.getMetadata()

        #check if batch number already exists in metadata for part
        batch = metadata.get("batch")

        #if metadata exists...
        if batch is not None:
            if self.get_setting('DEBUG'):
                print("[BATCH SCRIPT DEBUG] Batch number already exists, last number was: " + batch)
                print("[BATCH SCRIPT DEBUG] Checking if current number is available...")

            stockList = StockItem.list(api, batch_regex=batch)
            if len(stockList) == 0:
                if self.get_setting('DEBUG'):
                    print("[BATCH SCRIPT DEBUG] Batch number " + str(batch) + " is available, returning batch code")
                part.setMetadata({"batch": batch})
            else:
                if self.get_setting('DEBUG'):
                    print("[BATCH SCRIPT DEBUG] Batch number " + str(batch) + " is already in use, cannot assign. Adding 1 and trying again...")
                #loop to keep adding 1 until an available batch number is found
                allowed = False
                while not allowed:
                    batch = batch.removeprefix(self.get_setting('PREFIX'))
                    batch = int(batch)+1
                    batch = (self.get_setting('PREFIX') + str(batch).rjust(padding,'0'))
                    stockList = StockItem.list(api, batch_regex=batch)
                    if len(stockList) == 0:
                        allowed = True
                        #part.setMetadata("batch", batch)
                        if self.get_setting('DEBUG'):
                            print("[BATCH SCRIPT DEBUG] Batch number " + str(batch) + " is available, returning batch code")
                        #update metadata when available batch number found
                        part.setMetadata({"batch": batch})
                    else:
                        pass
                        if self.get_setting('DEBUG'):
                            print("[BATCH SCRIPT DEBUG] Batch number " + str(batch) + " is already in use, cannot assign. Adding 1 and trying again...")
        

        #if metadata doesn't exist...
        else:
            #set batch to 1
            batch = 1
            #add prefix and padding
            batch = (self.get_setting('PREFIX') + str(batch).rjust(padding,'0'))
            #print some debug info
            if self.get_setting('DEBUG'):
                print("[BATCH SCRIPT DEBUG] No existing batch number, assigned " + batch)
                print("Checking doesn't already exist...")
            #check stock to see if batch number already used
            stockList = StockItem.list(api, batch_regex=batch)
            #if not used
            if len(stockList) == 0:
                #print debug info and update metadata for part
                if self.get_setting('DEBUG'):
                    print("[BATCH SCRIPT DEBUG] Batch number " + str(batch) + " is available, returning batch code")
                part.setMetadata({"batch": batch})
            #if already used
            else:
                if self.get_setting('DEBUG'):
                    print("[BATCH SCRIPT DEBUG] Batch number " + str(batch) + " is already in use, cannot assign. Adding 1 and trying again...")
                #loop to keep adding 1 until an available batch number is found
                allowed = False
                while not allowed:
                    batch = batch.removeprefix(self.get_setting('PREFIX'))
                    batch = int(batch)+1
                    batch = (self.get_setting('PREFIX') + str(batch).rjust(padding,'0'))
                    stockList = StockItem.list(api, batch_regex=batch)
                    if len(stockList) == 0:
                        allowed = True
                        #part.setMetadata("batch", batch)
                        if self.get_setting('DEBUG'):
                            print("[BATCH SCRIPT DEBUG] Batch number " + str(batch) + " is available, returning batch code")
                        #update metadata when available batch number found
                        part.setMetadata({"batch": batch})
                    else:
                        if self.get_setting('DEBUG'):
                            print("[BATCH SCRIPT DEBUG] Batch number " + str(batch) + " is already in use, cannot assign. Adding 1 and trying again...")
                        else:
                            pass
    """
        #define API connection using access token
        api = InvenTreeAPI(self.get_setting('SERVER_ADDRESS'), token=self.get_setting('ACCESS_TOKEN'))
        #stockList = StockItem.list(api, batch_regex="SS_00001")

        return ("Batch code generation not implemented yet")
    


    """

    def generate_batch_code(self, **kwargs):
        #Generate a new batch code.

        if not self.get_setting("ACTIVE"):
            return False

        #api = InvenTreeAPI(self.get_setting('SERVER_ADDRESS'), username=self.get_setting('USERNAME'), password=self.get_setting('PASSWORD'))
        api = InvenTreeAPI(self.get_setting('SERVER_ADDRESS'), token=self.get_setting('ACCESS_TOKEN'))
        
        batch = None

        padding = self.get_setting('PADDING')

        expression = re.compile('^' + self.get_setting('PREFIX') + "[0-9]+$")

        stockList = StockItem.list(api, parent='')

        filteredStockList = list(filter(lambda x: re.match(expression, x.batch), stockList))

        sortedFilteredStockList = sorted(filteredStockList, key=lambda x: x.batch)

        if len(sortedFilteredStockList) > 0:
            batch = sortedFilteredStockList[-1].batch
            batch = batch.removeprefix(self.get_setting('PREFIX'))
            batch = int(batch)+1
            batch = (self.get_setting('PREFIX') + str(batch).rjust(padding,'0'))

        else:
            batch = 1
            batch = (self.get_setting('PREFIX') + str(batch).rjust(padding,'0'))

        print("Generated batch code: " + batch )

        return (batch)
    """
