"""
    This file is part of Accountant.

    Accountant is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Foobar is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with Accountant.  If not, see <http://www.gnu.org/licenses/>.
"""
from app import app
from app import db

from api.model.accounts import Account
from api.model.entries import Entry

from flask import json, request

from sqlalchemy import func, case, cast, extract, distinct

@app.route("/api/accounts", methods=["GET"])
def get_accounts():
    """
    Returns accounts with their solds.
    """
    session = db.session

    query = session.query(
      Account.id.label("id"),
      Account.name.label("name"),
      Account.authorized_overdraft.label("authorized_overdraft"),
      func.sum(Entry.value).label("future"),
      func.sum(case([(Entry.pointed, Entry.value,)], else_=cast(0, db.Numeric(15, 2)))).label("pointed"),
      func.sum(case([(Entry.operation_date < func.now(), Entry.value,)], else_=cast(0, db.Numeric(15, 2)))).label("current")
    ).outerjoin(Entry).group_by(Account.id).order_by(Account.id)

    return json.dumps([{
        "id": i.id,
        "name": i.name,
        "authorized_overdraft": i.authorized_overdraft,
        "current": str(i.current),
        "pointed": str(i.pointed),
        "future": str(i.future)
    } for i in query.all()])

@app.route("/api/accounts/<account_id>/months")
def get_months(account_id):
    session = db.session

    query = session.query(
      distinct(cast(extract("year", Entry.operation_date), db.String)).label("year"),
      cast(extract("month", Entry.operation_date), db.String).label("month")
    ).filter(Entry.account_id == account_id).order_by("year", "month")

    return json.dumps([{
        "year": i.year,
        "month": i.month.rjust(2, '0')
    } for i in query.all()])

@app.route("/api/accounts", methods=["PUT"])
def add_account():
    session = db.session

    try:
        account = Account(request.json['name'], request.json['authorized_overdraft'])

        session.add(account)
        session.commit()

        return json.dumps("Account added.")
    except:
        session.rollback()
        raise


@app.route("/api/accounts/<account_id>", methods=["PUT"])
def update_account(account_id):
    session = db.session

    try:
        account = session.query(Account).filter(Account.id == account_id).first()

        account.name = request.json['name']
        account.authorized_overdraft = request.json['authorized_overdraft']

        session.merge(account)
        session.commit()

        return json.dumps("Account #%s updated." % account_id)
    except:
        session.rollback()
        raise

@app.route("/api/accounts/<account_id>", methods=["DELETE"])
def delete_account(account_id):
    session = db.session

    try:
        account = session.query(Account).filter(Account.id == account_id).first()
    
        session.delete(account)
        session.commit()
    
        return json.dumps("Account #%s deleted." % account_id)
    except:
        session.rollback()
        raise

