from dataclasses import dataclass, field
import random
import string

@dataclass
class Person:
    first_name: str
    last_name: str
    age: int = field(default=20)
    full_name: str = field(init=False)

    def __post_init__(self):
        self.full_name = f'{self.first_name} {self.last_name}'
        self.is_programmer = True
        

def test_1():
    artem = Person('Artem', 'Egorov')
    print(artem)

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# Сортировка
@dataclass(order=True)
class PersonSort:
    sort_index: int = field(init=False, repr=False)
    name: str
    age: int
    weight: int = 190

    def __post_init__(self):
        self.sort_index = (self.weight, self.age)


def test_2():
    persons = [
        PersonSort('Иван', 25, 200),
        PersonSort('Петр', 30, 150),
        PersonSort('Кирилл', 35, 150),
        PersonSort('Борис', 20, 200),
        PersonSort('Алексей', 15, 200),
        PersonSort('Дмитрий', 11, 175),
    ]

    print(*sorted(persons), sep='\n')

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Наследование dataclass
# Если родительский класс имеет поле или несколько полей по умолчанию, то
# все поля в дочернем классе должны иметь значения по умолчанию.

@dataclass
class Person:
    first_name: str
    last_name: str
    age: int = field(default=20)

'''
@dataclass
class Student(Person):
    course: int = 1
    stipend: int = 1000
'''

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Задание на сортировку

@dataclass(order=True)
class Athlet:
    sort_index : float = field(init=False, repr=False)
    name: str
    coefficient: float = field(repr=False)
    scores: list = field(default_factory=list, repr=False)
    
    def __post_init__(self):
        self.sort_index = self.coefficient * sum(self.scores)/len(self.scores)
        print(self.sort_index)

def test_3():
    sportsmans = [
    Athlet('Иван', 1.5, [9.0, 8.0, 7.0]),
    Athlet('Петр', 1.0, [10.0, 9.0, 8.0]),
    Athlet('Алексей', 1.2, [8.0, 7.0, 6.0])
    ]

    print(f"Победитель соревнований: {max(sportsmans)}")

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

alphabet = string.ascii_uppercase + string.digits

def generate_guid():
    guid = ''.join(random.choices(alphabet, k=15))
    return guid

@dataclass(order=True)
class Student:
    sort_index : int = field(init=False, repr=False)
    first_name: str
    last_name: str
    tuition: int = field(default=0, repr=False)
    guid: str = field(init=False, repr=False)
    email: str = field(init=False)

    def __post_init__(self):
        self.sort_index = (self.tuition, self.last_name, self.first_name)
        self.guid = generate_guid()
        self.email = self.first_name.lower() + '.' + self.last_name.lower() + '@uni.edu'

def test_4():
    jane = Student('Jane', 'Lee')
    julia = Student('Julia', 'Doe')
    jake = Student('Jake', 'Langdon')
    joy = Student('Joy', 'Smith')
    print(*sorted([jane, julia, jake, joy]), sep='\n')

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


@dataclass
class Promo:
    code : str
    discount : int = field(default=0)
    goods : list = field(default_factory=list)

@dataclass
class Product:
    name: str
    price: float = field(repr=False)

book = Product('Книга', 100.0)
usb = Product('Флешка', 50.0)
pen = Product('Ручка', 10.0)

ACTIVE_PROMO = [
    Promo('new', 20, [pen]),
    Promo('all_goods', 30),
    Promo('sale', 50, [book, usb]),
]

@dataclass
class Cart:
    products: list = field(default_factory=list)
    discount: int = field(default=0, init=False, repr=False)
    discount_type: str = field(default='', init=False, repr=False)
    # product_promo: str = field(default='', init=False, repr=False)
    products_promo: list = field(default_factory=list, init=False, repr=False)

    def add_product(self, product, quantity=1):
        for i in range(quantity):
            self.products.append(product)

    def get_total(self):

        '''
        if self.product_promo != '':
            s = sum([x.price if x.name != self.product_promo else 
            x.price*(1 - self.discount/100) for x in self.products])
            return s
        '''

        if self.products_promo != []:
            s = sum([x.price if x.name not in self.products_promo else 
            x.price*(1 - self.discount/100) for x in self.products])
            return s

        s = sum([x.price for x in self.products])

        if self.discount == 0:
            return s
        else:
            return s - s/100*self.discount

    def apply_discount(self, value):
        if value < 1 or value > 100:
            raise ValueError('Неправильное значение скидки')
        self.discount = value
        self.discount_type = 'disc'

    def apply_promo(self, code):
        data = {x.code:x.discount for x in ACTIVE_PROMO}
        foo = {x.code:x.goods for x in ACTIVE_PROMO}
        if code not in data.keys():
            print(f'Промокода {code} не существует')
        else:
            print(f'Промокод {code} успешно применился')
            self.discount = data[code]
            if (foo[code] != []):
                # self.product_promo = foo[code][0].name
                for x in foo[code]:
                    self.products_promo.append(x.name)
                # print(self.products_promo)

def test_5():
    pass

def test_6():

    cart = Cart()
    cart.add_product(book, 10)
    cart.add_product(pen)
    cart.add_product(book, 5)
    cart.add_product(usb, 5)
    cart.add_product(usb, 15)
    cart.add_product(pen, 2)

    print(cart.get_total())

    # Применение промокода в 50% на книги и флешки
    cart.apply_promo('sale')
    print(cart.get_total())

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~





def main():
    # test_1()
    # test_2()
    # test_3()
    # test_4()
    # test_5()
    test_6()


if __name__ == '__main__':
    main()