import asyncio
import datetime
import logging
import pathlib
import sys

from db_calls_card_creation import *
from creation_helpers import get_position_string, write_to_csv, ordered_positions, defense_rg, ordered_pitching_positions

date = f'{datetime.datetime.now().year}-{datetime.datetime.now().month}-{datetime.datetime.now().day}'
log_level = logging.INFO
logging.basicConfig(
    filename=f'logs/{date}.log',
    format='%(asctime)s - card-creation - %(levelname)s - %(message)s',
    level=log_level
)


def get_batter_rarity(total_ops):
    if total_ops < .7:
        return 'Replacement'
    elif total_ops < .8:
        return 'Reserve'
    elif total_ops < .9:
        return 'Starter'
    elif total_ops < 1:
        return 'All-Star'
    elif total_ops < 1.2:
        return 'MVP'
    else:
        return 'HoF'


def get_pitcher_rarity(total_ops, s_rat):
    if s_rat > 3:
        if total_ops <= .4:
            return 'HoF'
        elif total_ops <= .475:
            return 'MVP'
        elif total_ops <= .53:
            return 'All-Star'
        elif total_ops <= .6:
            return 'Starter'
        elif total_ops <= .675:
            return 'Reserve'
        else:
            return 'Replacement'
    else:
        if total_ops <= .325:
            return 'HoF'
        elif total_ops <= .4:
            return 'MVP'
        elif total_ops <= .475:
            return 'All-Star'
        elif total_ops <= .55:
            return 'Starter'
        elif total_ops <= .625:
            return 'Reserve'
        else:
            return 'Replacement'


async def main(argv):
    cardset_name = input(f'What is the name of this Cardset? ')
    # cardset_name = '2022 Live'
    cardset = Cardset.get_or_none(fn.Lower(Cardset.set_title) == cardset_name.lower())

    if not cardset:
        print(f'There is no cardset named **{cardset_name}**.')
        return
    else:
        print(f'Got it! Starting on the {cardset.set_title} cardset.')

    now = datetime.datetime.now()
    output_path = pathlib.Path(f'card-output/{cardset.set_title} Cardset/')
    if not output_path.exists():
        output_path.mkdir(parents=True, exist_ok=True)

    all_players = Player.select()
    batter_output = [[
        'name', 'hand', 'rarity', 'pos', 'stealing', 'bunt', 'hnr', 'running', 'vl-2d6-1', 'vl-results-1',
        'vl-splits-1', 'vl-2d6-2', 'vl-results-2', 'vl-splits-2', 'vl-2d6-3', 'vl-results-3', 'vl-splits-3', 'vr-2d6-1',
        'vr-results-1', 'vr-splits-1', 'vr-2d6-2', 'vr-results-2', 'vr-splits-2', 'vr-2d6-3', 'vr-results-3',
        'vr-splits-3'
    ]]
    batter_rg_output = [[
        'sba_id', 'cardset_id', 'player_name', 'hand', 'vl_hr', 'vl_bphr', 'vl_tr', 'vl_do3', 'vl_do2', 'vl_doP',
        'vl_si2', 'vl_si1', 'vl_siC', 'vl_bpsi', 'vl_hbp', 'vl_bb', 'vl_k', 'vl_lo', 'vl_po', 'vl_flya', 'vl_flybq',
        'vl_flylfb', 'vl_flyrfb', 'vl_gba', 'vl_gbb', 'vl_gbc', 'vr_hr', 'vr_bphr', 'vr_tr', 'vr_do3', 'vr_do2',
        'vr_doP', 'vr_si2', 'vr_si1', 'vr_siC', 'vr_bpsi', 'vr_hbp', 'vr_bb', 'vr_k', 'vr_lo', 'vr_po', 'vr_flya',
        'vr_flybq', 'vr_flylfb', 'vr_flyrfb', 'vr_gba', 'vr_gbb', 'vr_gbc'
    ]]
    baserunning_output = [[
        'name', 'running', 'st-high', 'st-low', 'auto-jump', 'jump'
    ]]
    pitcher_output = [[
        'name', 'hand', 'rarity', 'starter', 'reliever', 'closer', 'hold', 'batting', 'balk', 'wp', 'defense', 'vl-2d6-1',
        'vl-results-1', 'vl-splits-1', 'vl-2d6-2', 'vl-results-2', 'vl-splits-2', 'vl-2d6-3', 'vl-results-3',
        'vl-splits-3', 'vr-2d6-1', 'vr-results-1', 'vr-splits-1', 'vr-2d6-2', 'vr-results-2', 'vr-splits-2', 'vr-2d6-3',
        'vr-results-3', 'vr-splits-3'
    ]]
    pitcher_peripherals_output = [[
        'name', 'starter', 'reliever', 'closer', 'hold', 'balk', 'wp'
    ]]
    pitcher_rg_output = [[
        'sba-id', 'cardset-id', 'player-name', 'hand', 'hr-vL', 'bp-hr-vL', 'tr-vL', 'do***-vL', 'do**-vL', 'do-cf-vL',
        'si**-vL', 'si*-vL', 'si-cf-vL', 'bp-si-vL', 'hbp-vL', 'bb-vL', 'so-vL', 'fo-b-cf-vL', 'fo-b-slap-vL',
        'gb-a-vL', 'gb-c-vL', 'gb-x-p-vL', 'gb-x-c-vL', 'gb-x-1b-vL', 'gb-x-2b-vL', 'gb-x-3b-vL', 'gb-x-ss-vL',
        'gb-x-lf-vL', 'gb-x-cf-vL', 'gb-x-rf-vL', 'hr-vR', 'bp-hr-vR', 'tr-vR', 'do***-vR', 'do**-vR', 'do-cf-vR',
        'si**-vR', 'si*-vR', 'si-cf-vR', 'bp-si-vR', 'hbp-vR', 'bb-vR', 'so-vR', 'fo-b-cf-vR', 'fo-b-slap-vR',
        'gb-a-vR', 'gb-c-vR', 'gb-x-p-vR', 'gb-x-c-vR', 'gb-x-1b-vR', 'gb-x-2b-vR', 'gb-x-3b-vR', 'gb-x-ss-vR',
        'gb-x-lf-vR', 'gb-x-cf-vR', 'gb-x-rf-vR'
    ]]
    player_json_output = [[
        'sba-id', 'name', '', 'fg-id', 'bbref-id', '', '', '', 'cardset-id'
    ]]
    defense_rg_output = [[
        'full name', 'p-rat', 'c-rat', '1b-rat', '2b-rat', '3b-rat', 'ss-rat', 'lf-rat', 'cf-rat', 'rf-rat', 'p-e',
        'c-e', '1b-e', '2b-e', '3b-e', 'ss-e', 'lf-e', 'cf-e', 'rf-e', 'of-arm', 'c-arm', 'c-throw', 'c-pb', 'p-wp',
        'p-bk'
    ]]

    print(f'Found {all_players.count()} players in this cardset...')
    for player in all_players:
        b_lines = CardColumns.select().where(
            CardColumns.b_ratings.is_null(False) & (CardColumns.player == player) &
            CardColumns.b_ratings.endswith(f'{cardset.id}')
        )

        this_output = [player.name, player.hand]
        if b_lines.count() == 2:
            vl_line = None
            vr_line = None
            for line in b_lines:
                this_columns = [
                    line.one_dice, line.one_results, line.one_splits, line.two_dice, line.two_results, line.two_splits,
                    line.three_dice, line.three_results, line.three_splits
                ]
                if 'vL' in line.b_ratings.id:
                    vl_line = this_columns
                else:
                    vr_line = this_columns

            vl_ratings = BatterRatings.get_or_none(
                BatterRatings.player == player, BatterRatings.cardset == cardset, BatterRatings.vs_hand == 'vL',
                BatterRatings.is_prep == 0
            )
            vr_ratings = BatterRatings.get_or_none(
                BatterRatings.player == player, BatterRatings.cardset == cardset, BatterRatings.vs_hand == 'vR',
                BatterRatings.is_prep == 0
            )

            # Calculate rarity
            ops_vl = vl_ratings.obp + vl_ratings.slg
            ops_vr = vr_ratings.obp + vr_ratings.slg
            total_ops = (ops_vl + ops_vr + min(ops_vl, ops_vr)) / 3
            rarity = get_batter_rarity(total_ops)

            this_json = [
                player.sba_id, player.name, None, player.fg_id, player.br_id, None, None, None, cardset.id, rarity, None
            ]
            this_output.append(rarity)

            batter_rg_output.append([
                player.sba_id, cardset.id, player.name, player.hand, vl_ratings.homerun, vl_ratings.bp_homerun,
                vl_ratings.triple, vl_ratings.double_three, vl_ratings.double_two, vl_ratings.double_pull,
                vl_ratings.single_two, vl_ratings.single_one, vl_ratings.single_center, vl_ratings.bp_single,
                vl_ratings.hbp, vl_ratings.walk, vl_ratings.strikeout, vl_ratings.lineout, vl_ratings.popout,
                vl_ratings.flyout_a, vl_ratings.flyout_bq, vl_ratings.flyout_lf_b, vl_ratings.flyout_rf_b,
                vl_ratings.groundout_a, vl_ratings.groundout_b, vl_ratings.groundout_c, vr_ratings.homerun, vr_ratings.bp_homerun,
                vr_ratings.triple, vr_ratings.double_three, vr_ratings.double_two, vr_ratings.double_pull,
                vr_ratings.single_two, vr_ratings.single_one, vr_ratings.single_center, vr_ratings.bp_single,
                vr_ratings.hbp, vr_ratings.walk, vr_ratings.strikeout, vr_ratings.lineout, vr_ratings.popout,
                vr_ratings.flyout_a, vr_ratings.flyout_bq, vr_ratings.flyout_lf_b, vr_ratings.flyout_rf_b,
                vr_ratings.groundout_a, vr_ratings.groundout_b, vr_ratings.groundout_c, rarity
            ])

            all_positions = Position.select().where((Position.player == player) & (Position.cardset == cardset))
            pos_list = [x for x in all_positions]
            position_string = get_position_string(pos_list, inc_p=False)
            this_json.extend(ordered_positions(pos_list))
            player_json_output.append(this_json)

            this_batter_data = BatterData.get_or_none(BatterData.player == player, BatterData.cardset == cardset)
            if this_batter_data:
                baserunning_output.append([
                    player.name, this_batter_data.running, this_batter_data.st_high, this_batter_data.st_low,
                    "Y" if this_batter_data.st_auto else "N", this_batter_data.st_jump
                ])

                this_output.extend([
                    position_string, this_batter_data.stealing, this_batter_data.bunting, this_batter_data.hit_and_run,
                    this_batter_data.running
                ])
                this_output.extend(vl_line)
                this_output.extend(vr_line)

                batter_output.append(this_output)

        p_lines = CardColumns.select().where(
            CardColumns.p_ratings.is_null(False) & (CardColumns.player == player) &
            CardColumns.p_ratings.endswith(f'{cardset.id}')
        )
        # if p_lines.count() > 0:
        #     print(f'player: {player.name}')
        #     print(f'p_lines ({p_lines.count()}): {p_lines}')

        this_output = [player.name, player.hand]
        if p_lines.count() == 2:
            vr_line = None
            vl_line = None

            for line in p_lines:
                this_columns = [
                    line.one_dice, line.one_results, line.one_splits, line.two_dice, line.two_results, line.two_splits,
                    line.three_dice, line.three_results, line.three_splits
                ]
                if 'vL' in line.p_ratings.id:
                    vl_line = this_columns
                else:
                    vr_line = this_columns

            if vr_line is not None and vl_line is not None:
                this_data = PitcherData.get_or_none(PitcherData.player == player, PitcherData.cardset_id == cardset.id)
                if this_data:
                    pitcher_peripherals_output.append([
                        player.name, this_data.starter_rating, this_data.relief_rating, this_data.closer_rating,
                        this_data.hold, this_data.wild_pitch, this_data.balk
                    ])

                    vl_ratings = PitcherRatings.get_or_none(
                        PitcherRatings.player == player, PitcherRatings.cardset == cardset,
                        PitcherRatings.vs_hand == 'vL', PitcherRatings.is_prep == 0
                    )
                    vr_ratings = PitcherRatings.get_or_none(
                        PitcherRatings.player == player, PitcherRatings.cardset == cardset,
                        PitcherRatings.vs_hand == 'vR', PitcherRatings.is_prep == 0
                    )

                    # Calculate rarity
                    ops_vl = vl_ratings.obp + vl_ratings.slg
                    ops_vr = vr_ratings.obp + vr_ratings.slg
                    total_ops = (ops_vl + ops_vr + min(ops_vl, ops_vr)) / 3
                    rarity = get_pitcher_rarity(total_ops, this_data.starter_rating)

                    this_json = [
                        player.sba_id, player.name, None, player.fg_id, player.br_id, None, None, None, cardset.id,
                        rarity, None
                    ]

                    this_output.extend([
                        rarity, this_data.starter_rating, this_data.relief_rating, this_data.closer_rating,
                        this_data.hold, this_data.batting, this_data.balk, this_data.wild_pitch
                    ])

                    pitcher_rg_output.append([
                        player.sba_id, cardset.id, player.name, player.hand, vl_ratings.homerun, vl_ratings.bp_homerun,
                        vl_ratings.triple, vl_ratings.double_three, vl_ratings.double_two, vl_ratings.double_cf,
                        vl_ratings.single_two, vl_ratings.single_one, vl_ratings.single_center, vl_ratings.bp_single,
                        vl_ratings.hbp, vl_ratings.walk, vl_ratings.strikeout, vl_ratings.fo_center, vl_ratings.fo_slap,
                        vl_ratings.groundout_a, vl_ratings.groundout_b, vl_ratings.xcheck_p, vl_ratings.xcheck_c,
                        vl_ratings.xcheck_1b, vl_ratings.xcheck_2b, vl_ratings.xcheck_3b, vl_ratings.xcheck_ss,
                        vl_ratings.xcheck_lf, vl_ratings.xcheck_cf, vl_ratings.xcheck_rf,
                        vr_ratings.homerun, vr_ratings.bp_homerun,
                        vr_ratings.triple, vr_ratings.double_three, vr_ratings.double_two, vr_ratings.double_cf,
                        vr_ratings.single_two, vr_ratings.single_one, vr_ratings.single_center, vr_ratings.bp_single,
                        vr_ratings.hbp, vr_ratings.walk, vr_ratings.strikeout, vr_ratings.fo_center, vr_ratings.fo_slap,
                        vr_ratings.groundout_a, vr_ratings.groundout_b, vr_ratings.xcheck_p, vr_ratings.xcheck_c,
                        vr_ratings.xcheck_1b, vr_ratings.xcheck_2b, vr_ratings.xcheck_3b, vr_ratings.xcheck_ss,
                        vr_ratings.xcheck_lf, vr_ratings.xcheck_cf, vr_ratings.xcheck_rf
                    ])

                    p_def = Position.get_or_none(
                        (Position.player == player) & (Position.cardset_id == cardset.id) & (Position.position == 'P')
                    )
                    if p_def:
                        this_output.append(f'p-{p_def.range}e{p_def.error}')
                        this_output.extend(vl_line)
                        this_output.extend(vr_line)

                        pitcher_output.append(this_output)
                        all_p_def = Position.select().where(
                            ((Position.player == player) & (Position.cardset == cardset)) & (
                                    (Position.position == 'SP') | (Position.position == 'RP') |
                                    (Position.position == 'CP')
                            )
                        )
                        pos_list = [x for x in all_p_def]
                        ordered_roles = ordered_pitching_positions(pos_list)
                        this_json.extend(ordered_roles)
                        player_json_output.append(this_json)

        all_pos = Position.select().where(
            (Position.player == player) & (Position.cardset == cardset)
        )
        if all_pos.count() > 0:
            this_data = [player.name]
            this_data.extend(defense_rg(all_pos))
            defense_rg_output.append(this_data)

    print(f'Done processing players; outputting to {output_path}')
    write_to_csv(output_path, f'batter-card-output-{now.strftime("%Y-%m-%d-%f")}', batter_output)
    write_to_csv(output_path, f'batter-rg-output-{now.strftime("%Y-%m-%d-%f")}', batter_rg_output)
    write_to_csv(output_path, f'batter-baserunning-{now.strftime("%Y-%m-%d-%f")}', baserunning_output)
    write_to_csv(output_path, f'pitcher-card-output-{now.strftime("%Y-%m-%d-%f")}', pitcher_output)
    write_to_csv(output_path, f'pitcher-peripherals-{now.strftime("%Y-%m-%d-%f")}', pitcher_peripherals_output)
    write_to_csv(output_path, f'pitcher-rg-output-{now.strftime("%Y-%m-%d-%f")}', pitcher_rg_output)
    write_to_csv(output_path, f'player-json-{now.strftime("%Y-%m-%d-%f")}', player_json_output)
    write_to_csv(output_path, f'defense-rg-{now.strftime("%Y-%m-%d-%f")}', defense_rg_output)
    print(f'All done!')


if __name__ == '__main__':
    asyncio.run(main(sys.argv[1:]))
