from django.db import models
from django.core.validators import MaxValueValidator, MinValueValidator
from polymorphic.models import PolymorphicModel
from .engineeringmodel import EngineeringModel
import random


# Event und erbende Klassen (specialOrder)
class Event(PolymorphicModel):
    name = models.CharField(default="random Event", max_length=40)
    description = models.CharField(default="Event description here", max_length=200)

    @classmethod
    def createEmpty(cls):
        emptyEvent = cls(
            name="Your E-Mails are empty",
            description="You do not have E-Mails this round.",
        )
        emptyEvent.save()
        return emptyEvent

    @classmethod
    def createOrderFailed(cls, ordername):
        name = ordername + " canceled."
        description = (
            "Your order "
            + ordername
            + " ran out of rounds! The order was canceled and your customerSatisfaction decreased."
        )
        event = cls(
            name=name,
            description=description,
        )
        event.save()
        return event

    @classmethod
    def createOrderFinished(cls, ordername, profit):
        name = ordername + " finished."
        description = (
            "Your order "
            + ordername
            + " was completed! The profit of "
            + profit
            + " was added to your companys money."
        )
        event = cls(
            name=name,
            description=description,
        )
        event.save()
        return event

    @classmethod
    def createWorkerQuit(cls, threshhold, workername, workerhappyness):
        name = workername + " quit his job."
        description = (
            "Your worker "
            + workername
            + " quit his job due to his happyness falling to "
            + str(workerhappyness)
            + "! Falling below "
            + str(threshhold)
            + " will result in increasing chance for your worker to quit!"
        )
        event = cls(
            name=name,
            description=description,
        )
        event.save()
        return event

    @classmethod
    def createSpecialOrderPenalty(cls, order):
        name = "You ignored the Special Order for " + order.name
        description = (
            "You ignored the Special Order for the order "
            + order.name
            + ". Penalties have been applied! [-20 Customer Satisfaction; -20% Profit]"
        )
        event = cls(
            name=name,
            description=description,
        )
        event.save()
        return event

    @classmethod
    def createSpecialOrderBonus(cls, order):
        name = "You handled the Special Order for " + order.name
        description = (
            "You handled the Special Order for the order "
            + order.name
            + " in a flexible model. You received a bonus on your order!"
            + " [+10 Customer Satisfaction; +10 Worker Satisfaction; +20% Profit ; +10 happyness all Workers]"
        )
        event = cls(
            name=name,
            description=description,
        )
        event.save()
        return event

    @classmethod
    def createSpecialOrderWrongModel(cls, order):
        name = "You handled the Special Order for " + order.name
        description = (
            "You handled the Special Order for the order "
            + order.name
            + ", but you are working with an unflexible model! You let your workers work overtime to complete the customers wish."
            + " [+30 Workload on all Skills; -20 happyness all Workers; -10 Worker Satsifaction]"
        )
        event = cls(
            name=name,
            description=description,
        )
        event.save()
        return event


class EventOfferAccepted(Event):
    order = models.ForeignKey("Order", default=1, on_delete=models.CASCADE)
    modelset = models.BooleanField(default=False)

    def setModel(self, model):
        self.order.setEngineeringmodel(model)
        self.modelset = True
        self.save()


class SpecialOrder(Event):
    occuranceProbability = models.IntegerField(
        default=100, validators=[MinValueValidator(0), MaxValueValidator(100)]
    )

    validModels = models.ManyToManyField(EngineeringModel, blank=True)
    occured = models.BooleanField(default=False)
    hint = models.CharField(default="no hint", max_length=100)

    def getValidModels(self):
        vmodels = []
        for model in self.validModels.all():
            vmodels.append(model.name)
        return vmodels

    def setDefaultValidModels(self):
        self.validModels.add(EngineeringModel.objects.get(name="ModelScrum"))
        self.validModels.add(EngineeringModel.objects.get(name="ModelSpiral"))
        self.validModels.add(EngineeringModel.objects.get(name="ModelHeyJoe"))

    def createHint(occuranceProbability):
        if occuranceProbability <= 10:
            hintlist = [
                "The project is discussed completely from the beginning, and clear agreements are made regarding the requirements and scope of the project.",
                "The customer is known to wish little interaction with its project partners and just wants to get the job done.",
                "A tight budget and strict time management allows little changes within the project.",
                "The company has emphasized the importance of precise planning and scope definition, indicating their intention to avoid unnecessary changes.",
                "The client's primary focus is on efficiency and timely completion, suggesting they are unlikely to introduce substantial changes mid-project.",
                "With a fixed project scope and well-defined milestones, the company seems committed to maintaining project stability.",
                "Previous collaborations with the company reveal a preference for minimal modifications during the project execution phase.",
            ]
        else:
            hintlist = [
                "Previous project collaborations with the firm have involved multiple change requests and additional features added throughout the development process.",
                "The client has expressed a strong desire for flexibility and creativity in the project execution.",
                "Given the dynamic nature of the industry they work in, it is likely that the company will request modifications to adapt to emerging trends.",
                "The client has not yet finalized their longterm strategy, which means changes and updates to the project might be needed.",
                "The company regularely takes user feedback, which might demand project alteration and updating.",
                "The client has expressed an interest in prototyping certain features to explore different possibilities, which may result in the addition of new requirements.",
                "The customer wishes for an agile project execution to have the option to get involved in the projects development.",
            ]
        hint = random.choice(hintlist)
        return hint

    def calculateOccurance(self):
        randnum = random.randint(1, 100)
        if (self.occuranceProbability >= randnum) and not self.occured:
            return True
        else:
            return False

    def createOccuranceProbability():
        # 50% chance dass es relativ wahrscheinlich/unwahrscheinlich ist das SO auftritt
        randnum = random.randint(1, 2)
        if randnum == 1:
            # niedrige OP
            occuranceProbability = random.randint(1, 5)
        else:
            # hohe OP
            occuranceProbability = random.randint(30, 40)
        return occuranceProbability

    def occure(self, company):
        if self.calculateOccurance():
            company.events.add(self)
            self.occured = True
            self.save()

    def handle(self, order, company, handle):
        if order.engineeringModel.name in self.getValidModels():
            self.bonus(order, company)
            event = Event.createSpecialOrderBonus(order)
        elif handle == True:
            self.invest(order, company)
            event = Event.createSpecialOrderWrongModel(order)
        else:
            self.penalty(order, company)
            event = Event.createSpecialOrderPenalty(order)

        company.events.remove(self)
        company.events.add(event)
        return event

    def bonus(self, order, company):
        company.calculateCustomerSatisfaction(20)
        company.calculateWorkerSatisfaction(10)

        order.profit *= 1.2
        for worker in company.workers.all():
            worker.calculateHappyness(10)

        order.save()
        company.save()

    def penalty(self, order, company):
        company.calculateCustomerSatisfaction(-20)
        order.profit *= 0.8

        order.save()
        company.save()

    def invest(self, order, company):
        order.addWorkload(30)
        for worker in company.workers.all():
            worker.calculateHappyness(-20)
        company.calculateWorkerSatisfaction(-10)
        order.save()
        company.save()


class SOPrototyp(SpecialOrder):
    @classmethod
    def createRandom(cls, ordername):
        name = "Specialorder prototyp request from " + ordername
        description = (
            "Your customer for the order "
            + ordername
            + " wants you to produce a prototyp for them to review."
        )
        # hier random low <5% per round oder high < 40% per round
        occuranceProbability = cls.createOccuranceProbability()
        hint = cls.createHint(occuranceProbability=occuranceProbability)
        specialorder = cls(
            name=name,
            description=description,
            occuranceProbability=occuranceProbability,
            hint=hint,
        )
        specialorder.save()
        specialorder.setDefaultValidModels()
        specialorder.save()
        return specialorder


class SORegularIncrementUpdates(SpecialOrder):
    @classmethod
    def createRandom(cls, ordername):
        name = "Specialorder regular incremental updates request from " + ordername
        description = (
            "Your customer for the order "
            + ordername
            + " wants to get regular updates on the increments of the project!"
        )
        # hier random low <5% per round oder high < 40% per round
        occuranceProbability = cls.createOccuranceProbability()
        hint = cls.createHint(occuranceProbability=occuranceProbability)
        specialorder = cls(
            name=name,
            description=description,
            occuranceProbability=occuranceProbability,
            hint=hint,
        )
        specialorder.save()
        specialorder.setDefaultValidModels()
        specialorder.save()
        return specialorder


class SOChangeRequirement(SpecialOrder):
    @classmethod
    def createRandom(cls, ordername):
        name = "Specialorder change requirement request from " + ordername
        description = (
            "Your customer for the order "
            + ordername
            + " wants to change some requirements on your order. "
        )
        # hier random low <5% per round oder high < 40% per round
        occuranceProbability = cls.createOccuranceProbability()
        hint = cls.createHint(occuranceProbability=occuranceProbability)
        specialorder = cls(
            name=name,
            description=description,
            occuranceProbability=occuranceProbability,
            hint=hint,
        )
        specialorder.save()
        specialorder.setDefaultValidModels()
        specialorder.save()
        return specialorder
