from flask import current_app
from ownchatbot.db import get_db, is_cool
from ownchatbot.owncast_com import send_chat, send_private_chat
from ownchatbot.reward_handlers import run_script, add_to_queue, add_to_vote, add_to_goal, was_goal_reached, goal_reached, is_reward_active, check_vote, all_active_goals, goal_left, was_milestone_reached, save_alerts
from ownchatbot.user_handlers import spend_points, get_users_points, refund_points, get_all_users_with_user_id
import os


def porps(points):  # Pluralize points based on the number of points
    if points == 1:
        num = 'point'
    else:
        num = 'points'
    return f'{points} {num}'


def mas(time_diff):  # Convert time difference decimal number to minutes and seconds
    minutes = int(time_diff)
    seconds = (time_diff - minutes) * 60
    seconds = round(seconds)
    if minutes > 1:
        mnum = 'minutes'
    else:
        mnum = 'minute'
    if seconds > 1:
        snum = 'seconds'
    else:
        snum = 'second'
    if minutes == 0:
        return f'{seconds} {snum}'
    else:
        return f'{minutes} {mnum} and {seconds} {snum}'


def do_reward(message, user_id):  # Parse the chat command
    db = get_db()
    for user in get_all_users_with_user_id(db, user_id):
        username = user[1]
    prefix = current_app.config['PREFIX']
    alerts_dict = current_app.config['ALERTS']
    split_message = message[1:].split(maxsplit=1)
    reward = split_message[0]
    if len(split_message) == 1:  # If it's a goal contribution, split the command and the contribution
        contribution = None
    else:
        contribution = split_message[1]

    if reward not in current_app.config['REWARDS']:  # Check if it's a command or a reward
        send_private_chat(user_id, f'{username}, \"{prefix}{reward}\" is not a chat command or a reward. Check your spelling?')
        return
    if not is_reward_active(reward):  # If reward isn't active, say so
        send_chat(f'Sorry, {username}. \"{prefix}{reward}\" is not currently an active reward.')
        return

    reward_type = current_app.config['REWARDS'][reward]['type']
    points = get_users_points(db, user_id)

    if reward_type == 'goal':  # If it's a goal contribution, do the thing
        if not contribution:
            send_private_chat(user_id, f'{username}, you didn\'t tell me how many points you want to contribute.')
            return
        if goal_reached(db, reward):
            send_private_chat(user_id, f'{username}, we already completed this goal.')
            return
        if int(contribution) > goal_left(db, reward):  # If they're contributing more than they need to
            current_app.logger.info(f'{username} contributed more than what was needed to reach the target.')
            contribution = goal_left(db, reward)  # only spend what is needed to reach the goal.
        if int(contribution) > points:
            send_private_chat(user_id, f'{username}, you don\'t have that many points.')
        elif int(contribution) < 0:
            send_private_chat(user_id, f'{username}, you can\'t contribute negative points.')
        elif int(contribution) == 0:
            send_private_chat(user_id, f'{username}, you can\'t contribute zero points.')
        elif add_to_goal(db, user_id, reward, int(contribution)):
            send_chat(f'{username} contributed {porps(contribution)} to the \"{prefix}{reward}\" goal.')
            if was_goal_reached(db, reward):  # Was a goal reached?
                alerts_dict['g_name'] = username
                alerts_dict['g_reward'] = reward
                save_alerts(alerts_dict)
                send_chat(f'\"{prefix}{reward}\" target reached! 🎉')
            else:  # If goal wasn't reached, was a milestone passed?
                check_milestones = was_milestone_reached(db, reward)
                if check_milestones is not False:  # Testing it this way because non-false returns two values
                    wmr, next_milestone = check_milestones
                    alerts_dict['m_name'] = username
                    alerts_dict['m_reward'] = wmr
                    save_alerts(alerts_dict)
                    send_chat(f'{wmr} milestone reached!')
                    if next_milestone == 'Done':
                        send_chat(f'Last milestone passed!')
                    else:
                        send_chat(f'Next milestone is \"{next_milestone}\"')
        else:
            send_private_chat(user_id, f'Couldn\'t contribute to the \"{prefix}{reward}\" goal for {username}, for some highly technical reason.')
        return

    price = current_app.config['REWARDS'][reward]['price']  # Do they have enough points?
    if not points or points < price:
        send_private_chat(user_id, f'{username}, you don\'t have enough points for \"{prefix}{reward}\".')
        return

    if reward_type == 'vote':  # If it's a vote, do the thing
        if check_vote(db, reward, user_id):  # See if viewer already voted
            send_private_chat(user_id, f'{username}, you already voted for \"{prefix}{reward}\".')
        else:
            if add_to_vote(db, reward, user_id) and spend_points(db, user_id, price):
                send_chat(f'{username} voted for \"{prefix}{reward}\" for {porps(price)}.')
            else:
                send_private_chat(user_id, f'Couldn\'t vote for \"{prefix}{reward}\" for {username}, for some highly technical reason.')

    elif reward_type == 'redeem':  # If it's a redeem, do the thing
        if is_cool(reward)[0]:  # Is there an active cool down?
            if (add_to_queue(db, user_id, reward) and
                    spend_points(db, user_id, price)):
                send_chat(f'{username} redeemed \"{prefix}{reward}\" for {porps(price)}.')
            else:
                send_private_chat(user_id, f'Couldn\'t redeem \"{prefix}{reward}\"for {username}, for some highly technical reason.')
        else:
            hot_time = is_cool(reward)[1]
            send_chat(f'\"{prefix}{reward}\" has {mas(hot_time)} left to cool down.')

    elif reward_type == 'special':  # If it's a special, do the thing
        if is_cool(reward)[0]:  # Is there an active cool down?
            script_cmd = current_app.config['REWARDS'][reward]['cmd']
            script_ran = run_script(reward, script_cmd)
            used_points = spend_points(db, user_id, price)
            if (script_ran and used_points):
                send_chat(f'{username} redeemed \'{prefix}{reward}\' for {porps(price)}.')
            else:
                if refund_points(db, user_id, price):
                    send_private_chat(user_id, f'Couldn\'t redeem \"{prefix}{reward}\"for {username}, for some highly technical reason.')
        else:
            hot_time = is_cool(reward)[1]
            send_chat(f'\"{prefix}{reward}\" has {mas(hot_time)} left to cool down.')

    else:  # If we can't find the reward, say so
        send_private_chat(user_id, f'\"{prefix}{reward}\", {username}? No such reward.')


def help_message(user_id):  # Build help message
    prefix = current_app.config['PREFIX']
    kofi_settings = current_app.config['KOFI_SETTINGS']
    kofi_integration = current_app.config['KOFI_SETTINGS']['integration']
    gb_settings = current_app.config['GB_SETTINGS']
    gb_integration = current_app.config['GB_SETTINGS']['integration']
    message = f'OwnchatBot v1.1.10<br> \
            You get {current_app.config["POINTS_AWARD"]} points for every {current_app.config["POINTS_INTERVAL"]} minutes you\'re in chat.<br> \
            You can see your points, the rewards queue, and other helpful information by clicking on the \"Points Rewards\" button.<br><br> \
            <b><u>Chat commands:</u></b><br> \
            <b>{prefix}help</b> to see this help message.<br> \
            <b>{prefix}points</b> to see your points.<br> \
            <b>{prefix}rewards</b> to see a list of currently active rewards.'
    if kofi_integration or gb_integration:
        message = f'{message}<br><br>\
            <b><u>Donations are enabled!</b></u><br>\
            Authenticate with Owncast, and register your email address on the OwnchatBot Info page to get donation perks.'
        if kofi_settings['donations']:
            message = f'{message}<br>\
            You\'ll recieve {porps(kofi_settings["donation_points"])} for every dollar you donate on Kofi'
        if kofi_settings['subs']:
            message = f'{message}, and {porps(kofi_settings["sub_points"])} every month for subscribing to my Kofi page.'
        if gb_settings['donations']:
            message = f'{message}<br>\
            You\'ll recieve {porps(gb_settings["donation_points"])} for every dollar you donate on GiveButter.'
        else:
            message = f'{message}'
    send_private_chat(user_id, message)


def save_announce(announce_dict):  # Write rewards to announce.py
    announce_file = os.path.join(current_app.instance_path, 'announce.py')
    new_announce = f"ANNOUNCEMENTS = {announce_dict['ANNOUNCEMENTS']}  # List of announcements\n\n\
ANNOUNCE_ENABLE = {announce_dict['ANNOUNCE_ENABLE']}  # Enable announcements\n\
ANNOUNCE_INTERVAL = {announce_dict['ANNOUNCE_INTERVAL']}  # How long, in minutes, between points announcements"

    try:
        with open(announce_file, 'w') as f:
            f.write(new_announce)
            f.close()
    except Exception as saerror:
        current_app.logger.error(f'Couldn\'t save announce.py: {saerror}')
        return False

    current_app.config.from_pyfile('announce.py', silent=True)
    return True
