from datetime import timedelta

from pyramid.view import view_config
from decimal import Decimal

from sqlalchemy.orm.exc import NoResultFound
from pyramid.httpexceptions import HTTPSeeOther

from toomuchwin import isk_fmt
from toomuchwin.models import DBSession, Prize, Play, Setting
from toomuchwin.models import UserBalanceError


@view_config(route_name='home', renderer='home.mako')
def home_view(request):
    return {
        'won_isk': Prize.total_won_isk(),
        'today_isk': Prize.total_won_isk(timefromnow=timedelta(hours=24)),
        'prizes': DBSession.query(Prize).filter_by(on_homepage=True).all(),
        'motd': Setting.get('motd'),
    }


@view_config(route_name='prize', permission='play', request_method='POST')
def prize_post(request):
    fee = Decimal(Setting.get('play_fee'))

    def redirect(id, chances=None):
        query = (('chances', chances),) if chances else None
        url = request.route_url('prize', prize_id=id, _query=query)
        return HTTPSeeOther(location=url)

    try:
        prize_id = int(request.matchdict['prize_id'])
        prize = DBSession.query(Prize).filter_by(id=prize_id) \
                                      .filter_by(on_homepage=True).one()
    except (ValueError, KeyError, NoResultFound):
        return HTTPSeeOther(location=request.route_url('home'))

    try:
        token = request.POST['csrf_token']
        chances = int(request.POST['chances'])
    except (ValueError, KeyError):
        return redirect(id=prize.id)

    if chances < 1 or chances > 100:
        request.messages.error('Invalid chance')
        return redirect(id=prize.id)

    if token != request.session.get_csrf_token():
        request.messages.error('Invalid CSRF token.')
        return redirect(id=prize.id, chances=chances)

    chances_r = Decimal(chances) / 100
    try:
        request.user.pay_prize(prize, chances_r, fee)
    except UserBalanceError as e:
        error = 'You are too poor. Get {} ISK and try again' \
                .format(isk_fmt(abs(e.difference)))
        request.messages.error(error)
        return redirect(id=prize.id, chances=chances)

    play = Play(user_id=request.user.id, prize_id=prize.id,
                chances=chances_r)
    play.flip_coin()
    DBSession.add(play)

    if play.lucky:
        won = 'You won! You can redeem your prize on your account.'
        request.messages.info(won)
    else:
        request.messages.error('Try again.')
    return redirect(id=prize.id, chances=chances)


@view_config(route_name='prize', renderer='prize.mako')
def prize_view(request):
    fee = Decimal(Setting.get('play_fee'))
    default_chances = int(Setting.get('default_chance'))

    try:
        id = int(request.matchdict['prize_id'])
        prize = DBSession.query(Prize).filter_by(id=id) \
                                      .filter_by(on_homepage=True).one()
    except (ValueError, KeyError, NoResultFound):
        return HTTPSeeOther(location=request.route_url('home'))

    try:
        chances = int(request.GET['chances'])
        if chances > 100 or chances < 0:
            raise ValueError
    except (KeyError, ValueError):
        chances = default_chances

    winners = DBSession.query(Play) \
                       .filter_by(lucky=True, prize_id=prize.id) \
                       .order_by(Play.create_date.desc()) \
                       .limit(10).all()
    winners = list(winners)

    return {
        'prize': prize,
        'winners': winners,
        'fee': fee,
        'chances': chances,
    }

