from django.contrib.auth.models import User as django_user
from django.db import models
from django.db.models import Index
# Create your models here.
from django.utils import timezone

from accounts.models import FifaAccount, PlayerCard
from sbc.consts import SBC_TARGET_NATIONS, SBC_TARGET_LEAGUES, SBC_TARGET_CLUBS, SBC_TARGET_RARITIES, \
    SBC_TARGET_POSITION, SBC_TARGET_LEVEL, SBC_TARGET_CHEMISTRY, SBCOrderStatus, SBC_TARGET_TRADABLE_TYPE, \
    SBC_TYPE_REPEATABLE_TYPE, rarity_2_help_text
from sbc.managers import SBCWorkerManager, SBCOrderManager, AccountCheckHealthyWorkerManager, \
    AccountCheckHealthyOrderManager


class SBCOrder(models.Model):
    creator = models.ForeignKey(django_user, on_delete=models.PROTECT, null=True)
    create_time = models.DateTimeField(default=timezone.now)
    file_name = models.CharField(max_length=255, verbose_name='File_name')
    status = models.CharField(max_length=100, choices=SBCOrderStatus, verbose_name='Status')
    workers_count = models.IntegerField(default=0)

    objects = SBCOrderManager()


class SBCType(models.Model):
    # creator = models.ForeignKey(django_user, on_delete=models.SET_NULL, null=True, blank=True)
    name = models.CharField(max_length=255)
    sbc_number = models.IntegerField(default=0)
    priority = models.IntegerField(default=0)
    sbc_link = models.CharField(max_length=1000)
    sbc_special_link = models.CharField(max_length=1000, null=True, blank=True)
    sbc_price = models.IntegerField(default=0)
    must_done = models.IntegerField(default=0, choices=((0, 'de-active'), (1, 'active'), (2, 'special')))
    sbc_actual_price = models.IntegerField(default=0)
    father_number = models.IntegerField(default=0)
    submit_sbc = models.IntegerField(default=1)
    open_packs = models.IntegerField(default=2, choices=((1, 'After Solve'), (2, 'End of Work')))
    updating_price = models.IntegerField(default=0)
    update_time = models.DateTimeField(default=timezone.now)
    checker_account = models.ForeignKey('accounts.FifaAccount', on_delete=models.SET_NULL, null=True, blank=True)
    need_recheck = models.BooleanField(default=False)
    need_recheck_time = models.DateTimeField(default=timezone.now)
    console_cant_use = models.BooleanField(default=False)
    console_can_use = models.BooleanField(default=True)
    can_pass = models.BooleanField(default=True)
    can_pass_on_error = models.BooleanField(default=True)
    team_min_rate = models.IntegerField(default=0)
    repeatable = models.CharField(max_length=255, default='', choices=SBC_TYPE_REPEATABLE_TYPE, blank=True)
    max_try_repeats_per_worker = models.IntegerField(default=20, verbose_name='Max try repeats per worker')
    solvation_type = models.IntegerField(default=0, choices=((0, 'Both'), (1, 'Old'), (2, 'New - auto maker')))
    expire_time = models.DateTimeField(blank=True, null=True)

    def __str__(self):
        return f'({self.id}) {self.name} , {self.sbc_number}'


class SBCTargetFilter(models.Model):
    # creator = models.ForeignKey(django_user, on_delete=models.SET_NULL, null=True, blank=True)
    rarity_ids = models.CharField(max_length=10, choices=SBC_TARGET_RARITIES, null=True, blank=True)
    position = models.CharField(max_length=20, choices=SBC_TARGET_POSITION, null=True, blank=True)
    chemistry_style = models.IntegerField(default=0, choices=SBC_TARGET_CHEMISTRY, null=True, blank=True)
    level = models.CharField(max_length=20, choices=SBC_TARGET_LEVEL, null=True, blank=True)
    nation = models.IntegerField(default=0, choices=SBC_TARGET_NATIONS, null=True, blank=True)
    league = models.IntegerField(default=0, choices=SBC_TARGET_LEAGUES, null=True, blank=True)
    team = models.IntegerField(default=0, choices=SBC_TARGET_CLUBS, null=True, blank=True)
    type_name = models.CharField(max_length=20, default='player', null=True, blank=True)
    buy_now_price = models.IntegerField(default=300)
    max_rating = models.IntegerField(default=0, help_text='Item Rating < this')
    min_rating = models.IntegerField(default=0)
    use_special_players = models.BooleanField(default=False)
    excluded_rarity_ids = models.ManyToManyField('sbc.RareFlag', blank=True)


class SBCTargetFilterNationMoves(models.Model):
    nation = models.IntegerField(default=0, choices=SBC_TARGET_NATIONS, null=True, blank=True)
    move_right = models.IntegerField(default=0)
    move_down = models.IntegerField(default=0)
    move_r1 = models.IntegerField(default=0)


class SBCTargetFilterLeagueMoves(models.Model):
    league = models.IntegerField(default=0, choices=SBC_TARGET_LEAGUES, null=True, blank=True)
    move_right = models.IntegerField(default=0)
    move_down = models.IntegerField(default=0)
    move_r1 = models.IntegerField(default=0)


class SBCTargetFilterClubMoves(models.Model):
    team = models.IntegerField(default=0, choices=SBC_TARGET_CLUBS, null=True, blank=True)
    league = models.IntegerField(default=0, choices=SBC_TARGET_LEAGUES, null=True, blank=True)
    move_right = models.IntegerField(default=0)
    move_down = models.IntegerField(default=0)
    move_r1 = models.IntegerField(default=0)


class RareFlag(models.Model):
    create_time = models.DateTimeField(default=timezone.now)
    name = models.CharField(max_length=255)
    rare_id = models.CharField(max_length=5)
    considered_rare = models.BooleanField(default=True)

    def __str__(self):
        return f'({self.id}) {self.name}'


class SBCTarget(models.Model):
    sbc_type = models.ForeignKey(SBCType, on_delete=models.CASCADE)
    position = models.IntegerField(default=0)
    team = models.IntegerField(default=0)
    asset_id = models.IntegerField(default=0)
    price = models.IntegerField(default=0)
    pos = models.CharField(max_length=20, null=True)
    player = models.ForeignKey('accounts.PlayerCard', on_delete=models.CASCADE)
    rare = models.IntegerField(default=0)
    name = models.TextField(null=True, blank=True)
    rating = models.IntegerField(default=0)
    team_name = models.TextField(null=True, blank=True)
    special_name = models.TextField(null=True, blank=True)
    target_filter = models.ForeignKey(SBCTargetFilter, on_delete=models.SET_NULL, null=True, blank=True)
    tradable_type = models.IntegerField(default=0, choices=SBC_TARGET_TRADABLE_TYPE)
    use_squad_players = models.BooleanField(default=False)

    def __str__(self):
        return f'({self.id}) type:{self.sbc_type},  price:{self.price}'


class SBCSolvationModel(models.Model):
    sbc_type = models.ForeignKey(SBCType, on_delete=models.CASCADE)
    formation = models.CharField(default='3-4-3', max_length=20)
    num_players = models.IntegerField(default=1)
    update_link = models.CharField(max_length=500, null=True, blank=True)
    players_in_position = models.BooleanField(
        default=False, help_text='PLAYERS_IN_POSITION = True => No player will be out of position and False implies otherwise.')
    fix_players = models.TextField(null=True, blank=True)
    remove_players = models.TextField(null=True, blank=True)
    # Set only one of the below to True to change the objective type.
    minimize_max_cost = models.BooleanField(
        default=False, help_text='Set only one of the [minimize_max_cost and maximize_total_cost] to True to change the objective type.')
    maximize_total_cost = models.BooleanField(default=False)
    # Set only one of the below to True and the other to False. Both can't be False.
    use_preferred_position = models.BooleanField(
        default=True, help_text="Set only one of the [use_preferred_position and use_alternate_positions] to True and the other to False. Both can't be False.")
    use_alternate_positions = models.BooleanField(default=False)
    # Set only one of the below to True and the others to False if duplicates are to be prioritized.
    use_all_duplicates = models.BooleanField(
        default=False, help_text='Set only one of the [use_all_duplicates and use_at_least_half_duplicates and use_at_least_one_duplicate] to True and the others to False if duplicates are to be prioritized.')
    use_at_least_half_duplicates = models.BooleanField(default=False)
    use_at_least_one_duplicate = models.BooleanField(default=False)
    consider_as_rare = models.TextField(null=True, blank=True)
    # club
    club = models.TextField(null=True, blank=True, verbose_name='Special Name Club')
    num_club = models.TextField(null=True, blank=True, verbose_name='Num Special Name Club')  # Total players from i^th list >= NUM_CLUB[i]
    max_num_club = models.IntegerField(default=0, verbose_name='Max Same Club')  # Same Club Count: Max X / Max X Players from the Same Club
    min_num_club = models.IntegerField(default=0, verbose_name='Min Same Club')  # Same Club Count: Min X / Min X Players from the Same Club
    num_unique_club = models.TextField(null=True, blank=True, verbose_name='Uniq Club', help_text="example : [6, 'Max']")  # Clubs: Max / Min / Exactly X
    # league
    league = models.TextField(null=True, blank=True, verbose_name='Special Name League')
    num_league = models.TextField(null=True, blank=True, verbose_name='Num Special Name League')  # Total players from i^th list >= NUM_LEAGUE[i]
    max_num_league = models.IntegerField(default=0, verbose_name='Max Same League')  # Same League Count: Max X / Max X Players from the Same League
    min_num_league = models.IntegerField(default=0, verbose_name='Min Same League')  # Same League Count: Min X / Min X Players from the Same League
    num_unique_league = models.TextField(null=True, blank=True, verbose_name='Uniq League', help_text="example : [2, 'Min']")  # Leagues: Max / Min / Exactly X
    # nation , country
    country = models.TextField(null=True, blank=True, verbose_name='Special Name Country')
    num_country = models.TextField(null=True, blank=True, verbose_name='Num Special Name Country')  # Total players from i^th list >= NUM_COUNTRY[i]
    max_num_country = models.IntegerField(default=0, verbose_name='Max Same Country')  # Same Nation Count: Max X / Max X Players from the Same Nation
    min_num_country = models.IntegerField(default=0, verbose_name='Min Same Country')  # Same Nation Count: Min X / Min X Players from the Same Nation
    num_unique_country = models.TextField(null=True, blank=True, verbose_name='Uniq Country', help_text="example : [5, 'Exactly']")  # Nations: Max / Min / Exactly X
    # ratiry
    rarity_1 = models.TextField(null=True, blank=True)
    num_rarity_1 = models.TextField(null=True, blank=True)  # This is for cases like "Gold TOTW: Min X (0/X)"
    rarity_2 = models.TextField(null=True, blank=True, help_text=rarity_2_help_text)
    num_rarity_2 = models.TextField(null=True, blank=True)  # Total players from i^th Rarity / Color >= NUM_RARITY_2[i]
    group_rarity = models.TextField(null=True, blank=True) # todo : use this and bellow line
    num_group_rarity = models.TextField(null=True, blank=True)
    squad_rating = models.IntegerField(default=0) # Squad Rating: Min XX
    min_overall = models.TextField(null=True, blank=True)
    num_min_overall = models.TextField(null=True, blank=True)  # Minimum OVR of XX : Min X
    chemistry = models.IntegerField(default=0)  # Squad Total Chemistry Points: Min X
    chem_per_player = models.IntegerField(default=0)  # Chemistry Points Per Player: Min X

    min_rating_players = models.IntegerField(default=0, help_text='Item Rating > this')
    max_rating_players = models.IntegerField(default=85, help_text='Item Rating < this')
    excluded_rarity_ids = models.ManyToManyField('sbc.RareFlag', blank=True)
    tradable_type = models.IntegerField(default=1, choices=SBC_TARGET_TRADABLE_TYPE)
    buy_player = models.BooleanField(default=False)
    buy_player_links = models.TextField(
        null=True, blank=True,
        help_text="example : [f'https://www.futbin.com/players?ps_price=200-500&page={random.randint(1, 5)}',]")
    required_positions = models.TextField(null=True, blank=True, help_text="example : 0,1,2,3")
    uniq_quality = models.TextField(null=True, blank=True, help_text="example : ['Gold', 'Min'] means min gold")
    difficulty = 0


class SBCSolvationModelPlayers(models.Model):
    create_time = models.DateTimeField(default=timezone.now)
    sbc_worker = models.ForeignKey('sbc.SBCWorker', on_delete=models.CASCADE)
    sbc_type = models.ForeignKey(SBCType, on_delete=models.CASCADE)
    index_composition = models.IntegerField(default=0)
    asset_id = models.IntegerField(default=0)
    rating = models.IntegerField(default=0)
    rare = models.IntegerField(default=0)
    team = models.IntegerField(default=0)
    team_name = models.CharField(max_length=200, null=True, blank=True)
    nation = models.IntegerField(default=0)
    nation_name = models.CharField(max_length=200, null=True, blank=True)
    league = models.IntegerField(default=0)
    league_name = models.CharField(max_length=200, null=True, blank=True)
    position = models.CharField(max_length=20, null=True)
    alter_position = models.CharField(max_length=20, null=True)
    price = models.IntegerField(default=0)
    name = models.TextField(null=True, blank=True)
    special_name = models.TextField(null=True, blank=True)
    add_counter = models.IntegerField(default=0)


class SBCSolvationModelWorker(models.Model):
    create_time = models.DateTimeField(default=timezone.now)
    fifa_account = models.ForeignKey('accounts.FifaAccount', on_delete=models.CASCADE, null=True)
    solvation_model = models.ForeignKey('sbc.SBCSolvationModel', on_delete=models.CASCADE, null=True)
    is_complete = models.BooleanField(default=False)
    has_error = models.BooleanField(default=False)


class SBCWorker(models.Model):
    create_time = models.DateTimeField(default=timezone.now, null=True)  # remove null=true
    start_time = models.DateTimeField(default=timezone.now)
    fifa_account = models.ForeignKey('accounts.FifaAccount', on_delete=models.PROTECT)
    is_done = models.BooleanField(default=False)
    last_run_time = models.DateTimeField(default=timezone.now)
    has_error = models.BooleanField(default=False)
    error_description = models.TextField(null=True, blank=True)
    complete_number = models.IntegerField(default=0)
    first_xi = models.BooleanField(default=False)
    puzzle_master = models.BooleanField(default=False)
    task_id = models.CharField(max_length=500, null=True, blank=True)
    sbc_order = models.ForeignKey(SBCOrder, on_delete=models.PROTECT, null=True, blank=True)
    manual_loyal = models.BooleanField(default=False)
    must_done = models.BooleanField(default=False)
    running_platform = models.TextField(null=True, blank=True, default='web')
    loyal_played_numbers = models.IntegerField(default=0)
    main_squad = models.BooleanField(default=False)
    order_active_squad = models.BooleanField(default=False)
    order_active_squad_formation = models.CharField(max_length=20, null=True, blank=True)
    produced_coins = models.IntegerField(default=0)
    end_time = models.DateTimeField(default=timezone.now)
    status = models.TextField(null=True, blank=True, default='')
    status_change_time = models.DateTimeField(default=timezone.now)
    description = models.TextField(null=True, blank=True, default='')
    description_editor = models.ForeignKey(django_user, on_delete=models.SET_NULL, null=True, blank=True)
    start_coin = models.IntegerField(default=0)

    objects = SBCWorkerManager()


class SBCProcess(models.Model):
    create_time = models.DateTimeField(default=timezone.now)
    worker = models.ForeignKey(SBCWorker, on_delete=models.CASCADE)
    sbc_type = models.ForeignKey(SBCType, on_delete=models.CASCADE)
    is_done = models.BooleanField(default=False)
    has_error = models.BooleanField(default=False, null=True)  # todo : remove null=True
    start_time = models.DateTimeField(default=timezone.now)
    sbc_number = models.IntegerField(default=0)
    status = models.TextField(null=True, blank=True)
    sum_bought_items = models.IntegerField(default=0, null=True)  # todo : remove null=True


class SBCProcessTarget(models.Model):
    create_time = models.DateTimeField(default=timezone.now)
    sbc_process = models.ForeignKey(SBCProcess, on_delete=models.CASCADE)
    club_id = models.CharField(max_length=255)
    position = models.IntegerField(default=-1)
    asset_id = models.IntegerField(default=0)
    rare = models.IntegerField(default=0)
    rating = models.IntegerField(default=0)
    last_sale_price = models.IntegerField(default=0, null=True)


class SBCWorkerDetailsLog(models.Model):
    worker = models.ForeignKey(SBCWorker, on_delete=models.CASCADE)
    start_time = models.DateTimeField(default=timezone.now)
    end_time = models.DateTimeField(default=timezone.now)
    title = models.CharField(max_length=255)
    main_job = models.BooleanField(default=False)

    class Meta:
        indexes = [
            Index(fields=["worker"], name="idx_worker_mainjob_true", condition=models.Q(main_job=True))
        ]


class AccountCheckHealthyOrder(models.Model):
    creator = models.ForeignKey(django_user, on_delete=models.PROTECT, null=True, blank=True)
    create_time = models.DateTimeField(default=timezone.now)
    file_name = models.CharField(max_length=255, verbose_name='File_name')
    status = models.CharField(max_length=100, choices=SBCOrderStatus, verbose_name='Status')

    objects = AccountCheckHealthyOrderManager()


class AccountCheckHealthyWorker(models.Model):
    request_order = models.ForeignKey(AccountCheckHealthyOrder, on_delete=models.CASCADE, null=True, blank=True)
    create_time = models.DateTimeField(default=timezone.now)
    fifa_account = models.ForeignKey('accounts.FifaAccount', on_delete=models.CASCADE, null=True, blank=True)
    status = models.TextField(null=True, blank=True, default='')
    must_done = models.BooleanField(default=False)
    is_done = models.BooleanField(default=False)
    has_error = models.BooleanField(default=False)
    error_description = models.TextField(null=True, blank=True)
    running_platform = models.TextField(null=True, blank=True, default='web')
    task_id = models.CharField(max_length=500, null=True, blank=True)
    sbc_worker = models.ForeignKey(SBCWorker, on_delete=models.SET_NULL, null=True, blank=True)
    current_coins = models.IntegerField(default=0)
    open_preview_gold_pack = models.IntegerField(default=0)
    sell_items = models.IntegerField(default=0)
    sell_club_items = models.IntegerField(default=0)
    open_packs = models.IntegerField(default=0)
    create_club = models.IntegerField(default=0)
    order_active_squad = models.IntegerField(default=0)
    order_active_squad_formation = models.CharField(max_length=20, null=True, blank=True)
    sellable_players = models.IntegerField(default=0)

    objects = AccountCheckHealthyWorkerManager()


class SBCSolverServerSideHandlerWorker(models.Model):
    create_time = models.DateTimeField(default=timezone.now)
    fifa_account = models.ForeignKey('accounts.FifaAccount', on_delete=models.CASCADE, null=True, blank=True)
    sbc_worker = models.ForeignKey('sbc.SBCWorker', on_delete=models.CASCADE, null=True, blank=True)
    sbc_complete_status = models.CharField(max_length=500, null=True, blank=True)
    status = models.CharField(max_length=100, choices=SBCOrderStatus, verbose_name='Status')
    is_done = models.BooleanField(default=False)
    last_run_time = models.DateTimeField(default=timezone.now)
    has_error = models.BooleanField(default=False)
    error_description = models.TextField(null=True, blank=True)
    end_time = models.DateTimeField(default=timezone.now)
    task_id = models.CharField(max_length=500, null=True, blank=True)


class AccountSBCNeedPlayer(models.Model):
    create_time = models.DateTimeField(default=timezone.now)
    fifa_account = models.ForeignKey('accounts.FifaAccount', on_delete=models.CASCADE, null=True, blank=True)
    sbc_target = models.ForeignKey('sbc.SBCTarget', on_delete=models.CASCADE, null=True, blank=True)
    player_card = models.ForeignKey('accounts.PlayerCard', on_delete=models.CASCADE, null=True, blank=True)
    price = models.IntegerField(default=0, null=True)  # todo:  remove null=True


class SBCFileWorkTime(models.Model):
    create_time = models.DateTimeField(default=timezone.now)
    console = models.ForeignKey('accounts.Console', on_delete=models.CASCADE)
    start_time = models.TimeField(null=True, blank=True)
    end_time = models.TimeField(null=True, blank=True)


class HourlyAccountSBCDoneHistory(models.Model):
    create_time = models.DateTimeField(default=timezone.now)
    done_count = models.IntegerField(default=0)
    account_done_count = models.IntegerField(default=0)


class SBCFileWorkLog(models.Model):
    create_time = models.DateTimeField(default=timezone.now)
    console = models.ForeignKey('accounts.Console', on_delete=models.SET_NULL, null=True, blank=True)
    fifa_account = models.ForeignKey('accounts.FifaAccount', on_delete=models.SET_NULL, null=True, blank=True)
    work_type = models.CharField(max_length=100, choices=(('sbc', 'SBCFile'), ('discharge', 'Discharge')))
    work_status = models.CharField(max_length=100, null=True, blank=True)
    work_accounts_count = models.IntegerField(default=0)
    start_time = models.DateTimeField(null=True, blank=True)
    end_time = models.DateTimeField(null=True, blank=True)
