# -*- coding: utf-8 -*-


import flask
import json
import dateutil.parser
from flask_jwt_extended import jwt_required, get_current_user
from pritunl_dedicated.blueprints import api_subscription
from pritunl_dedicated.models.pritunl_dedicated import Subscription, SubscriptionPlan, Version
from pritunl_dedicated.extensions import db
from pritunl_dedicated.views.api import filter_to_sqlalchemy, sort_to_sqlalchemy


__author__ = "Adam Schubert"
__date__ = "$18.8.2014 23:33:05$"


@api_subscription.route('', methods=['GET'], defaults={'page': 1})
@api_subscription.route('/page/<int:page>', methods=['GET'])
@jwt_required
def get_subscriptions(page: int):

    order_by = sort_to_sqlalchemy(
        Subscription,
        flask.request.args.get('sort_field'),
        int(flask.request.args.get('sort_order', 1)),
        {
            'license_key': 'license',
            'cancel_at_period_end': 'cancel_at_period_end',
            'period_end': 'period_end',
            'is_active': 'is_active'
        },
        'created'
    )

    subscriptions = Subscription.query.order_by(order_by)

    per_page = int(flask.request.args['per_page']) if 'per_page' in flask.request.args else subscriptions.count()
    filters = json.loads(flask.request.args['filters']) if 'filters' in flask.request.args else {}
    subscriptions_filter = filter_to_sqlalchemy(
        Subscription,
        filters,
        {
            'license_key': 'license_key',
            'cancel_at_period_end': 'cancel_at_period_end',
            'period_end': 'period_end',
            'is_active': 'is_active'
        }
    )

    paginator = subscriptions.filter(*subscriptions_filter).paginate(page, per_page)

    data_ret = []
    for subscription in paginator.items:
        data_ret.append(subscription.jsonify())

    ret = {
        'has_next': paginator.has_next,
        'has_prev': paginator.has_prev,
        'next_num': paginator.next_num,
        'prev_num': paginator.prev_num,
        'page': paginator.page,
        'pages': paginator.pages,
        'per_page': paginator.per_page,
        'total': paginator.total,
        'data': data_ret,
        'next': flask.url_for('api.subscription.get_subscriptions', page=paginator.next_num, _external=True),
        'prev': flask.url_for('api.subscription.get_subscriptions', page=paginator.prev_num, _external=True)
    }

    return flask.jsonify(ret), 200


@api_subscription.route('', methods=['PUT'])
@jwt_required
def set_subscription():
    subscription_id = flask.request.json.get('id')
    license_key = flask.request.json.get('license_key')
    is_active = flask.request.json.get('is_active')
    is_valid = flask.request.json.get('is_valid')
    quantity = flask.request.json.get('quantity')
    amount = flask.request.json.get('amount')
    period_end = flask.request.json.get('period_end')
    trial_end = flask.request.json.get('trial_end')
    is_cancel_at_period_end = flask.request.json.get('is_cancel_at_period_end')
    balance = flask.request.json.get('balance')
    url_key = flask.request.json.get('url_key')
    subscription_plan = flask.request.json.get('subscription_plan')
    versions = flask.request.json.get('versions')

    # Preprocess values
    try:
        trial_end = dateutil.parser.parse(trial_end) if trial_end else None
    except ValueError:
        return flask.jsonify({'message': 'trial_end has unknown datetime format!'}), 400

    try:
        period_end = dateutil.parser.parse(period_end) if period_end else None
    except ValueError:
        return flask.jsonify({'message': 'period_end has unknown datetime format!'}), 400

    subscription_found = Subscription.query.filter_by(id=subscription_id).first()
    if not subscription_found:
        return flask.jsonify({'message': 'Subscription not found'}), 404

    subscription_license_found = Subscription.query.filter_by(license_key=license_key).first()
    if subscription_license_found and subscription_license_found != subscription_found:
        return flask.jsonify({'message': 'Subscription license found'}), 409

    subscription_plan = SubscriptionPlan.query.filter_by(id=subscription_plan.get('id')).first()
    if not subscription_plan:
        return flask.jsonify({'message': 'Subscription plan not found'}), 404

    subscription_found.license_key = license_key
    subscription_found.is_active = is_active
    subscription_found.is_valid = is_valid
    subscription_found.quantity = quantity
    subscription_found.amount = amount
    subscription_found.period_end = period_end
    subscription_found.trial_end = trial_end
    subscription_found.is_cancel_at_period_end = is_cancel_at_period_end
    subscription_found.balance = balance
    subscription_found.url_key = url_key
    subscription_found.subscription_plan = subscription_plan

    subscription_found.versions = []
    for version_dict in versions:
        version = Version.query.filter_by(id=version_dict.get('id')).first()
        if version:
            subscription_found.versions.append(version)

    db.session.add(subscription_found)
    db.session.commit()

    return flask.jsonify(subscription_found.jsonify()), 200


@api_subscription.route('', methods=['POST'])
@jwt_required
def create_subscription():
    license_key = flask.request.json.get('license_key')
    is_active = flask.request.json.get('is_active')
    is_valid = flask.request.json.get('is_active')
    quantity = flask.request.json.get('quantity')
    amount = flask.request.json.get('amount')
    period_end = flask.request.json.get('period_end')
    trial_end = flask.request.json.get('trial_end')
    is_cancel_at_period_end = flask.request.json.get('is_cancel_at_period_end')
    balance = flask.request.json.get('balance')
    url_key = flask.request.json.get('url_key')
    subscription_plan = flask.request.json.get('subscription_plan')
    versions = flask.request.json.get('versions')

    # Preprocess values
    try:
        trial_end = dateutil.parser.parse(trial_end) if trial_end else None
    except ValueError:
        return flask.jsonify({'message': 'trial_end has unknown datetime format!'}), 400

    try:
        period_end = dateutil.parser.parse(period_end) if period_end else None
    except ValueError:
        return flask.jsonify({'message': 'period_end has unknown datetime format!'}), 400

    subscription_license_found = Subscription.query.filter_by(license_key=license_key).first()
    if subscription_license_found:
        return flask.jsonify({'message': 'Subscription license found'}), 409

    subscription_plan = SubscriptionPlan.query.filter_by(id=subscription_plan.get('id')).first()
    if not subscription_plan:
        return flask.jsonify({'message': 'Subscription plan not found'}), 404

    new_subscription = Subscription()
    new_subscription.is_valid = is_valid
    new_subscription.license_key = license_key
    new_subscription.is_active = is_active
    new_subscription.quantity = quantity
    new_subscription.amount = amount
    new_subscription.period_end = period_end
    new_subscription.trial_end = trial_end
    new_subscription.is_cancel_at_period_end = is_cancel_at_period_end
    new_subscription.balance = balance
    new_subscription.url_key = url_key
    new_subscription.subscription_plan = subscription_plan

    for version_dict in versions:
        version = Version.query.filter_by(id=version_dict.get('id')).first()
        if version:
            new_subscription.versions.append(version)

    db.session.add(new_subscription)
    db.session.commit()

    return flask.jsonify(new_subscription.jsonify()), 200


@api_subscription.route('/<int:subscription_id>', methods=['DELETE'])
@jwt_required
def delete_subscription(subscription_id: int):
    subscription_found = Subscription.query.filter_by(id=subscription_id).first()
    if not subscription_found:
        return flask.jsonify({'message': 'Subscription not found'}), 404
        
    subscription_data = subscription_found.jsonify()
    db.session.delete(subscription_found)
    db.session.commit()
    return flask.jsonify(subscription_data), 200


@api_subscription.route('/<int:subscription_id>', methods=['GET'])
@jwt_required
def get_subscription(subscription_id: int):
    subscription_found = Subscription.query.filter_by(id=subscription_id).first()
    if not subscription_found:
        return flask.jsonify({'message': 'Subscription not found'}), 404

    return flask.jsonify(subscription_found.jsonify()), 200
