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


import flask
import os
from pritunl_dedicated.blueprints import api_dedicated
from pritunl_dedicated.extensions import db
from pritunl_dedicated.models.pritunl_dedicated import Subscription, SubscriptionCheck, Version
from pritunl_dedicated.application import STATIC_FOLDER

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


def get_remote_ip() -> str:
    if 'X-Forwarded-For' in flask.request.headers:
        return flask.request.headers.getlist("X-Forwarded-For")[0].rpartition(' ')[-1]
    else:
        return flask.request.remote_addr or 'untrackable'


@api_dedicated.route('/subscription', methods=['GET'])
def get_subscription():

    application_id = flask.request.json.get('id')  # Application installation ID

    license_key = flask.request.json.get('license')  # Application installation licence
    version_integer = flask.request.json.get('version')  # Application installation version

    found_version = Version.query.filter_by(version_integer=version_integer).first()

    subscription_check = SubscriptionCheck()
    subscription_check.version = found_version
    subscription_check.ip_address = get_remote_ip()
    subscription_check.version_integer = version_integer
    subscription_check.application_id = application_id

    found_subscription = Subscription.query.filter_by(license_key=license_key, is_valid=True).first()
    if not found_subscription:
        subscription_check.is_ok = False
        subscription_check.status_message = 'License key is invalid (470)'
        db.session.add(subscription_check)

        # Create new subscription with this key to block it
        failed_subscription = Subscription()
        failed_subscription.license_key = license_key
        failed_subscription.is_active = False
        failed_subscription.is_valid = False
        failed_subscription.is_cancel_at_period_end = False
        failed_subscription.is_last_check_ok = subscription_check.is_ok
        failed_subscription.subscription_checks.append(subscription_check)

        db.session.add(failed_subscription)
        db.session.commit()
        return flask.jsonify({'error_msg': 'License key is invalid'}), 470

    if found_subscription.versions:
        if not found_version:
            subscription_check.is_ok = False
            subscription_check.status_message = 'Version {} not recognized (473)'.format(version_integer)
            db.session.add(subscription_check)
            found_subscription.subscription_checks.append(subscription_check)
            found_subscription.is_last_check_ok = subscription_check.is_ok
            db.session.add(found_subscription)
            db.session.commit()
            return flask.jsonify({'error_msg': 'Version {} not recognized'.format(version_integer)}), 473

        if found_version not in found_subscription.versions:
            subscription_check.is_ok = False
            subscription_check.status_message = 'Version {} not recognized (473) (Not in allowed versions.)'.format(version_integer)
            db.session.add(subscription_check)
            found_subscription.subscription_checks.append(subscription_check)
            found_subscription.is_last_check_ok = subscription_check.is_ok
            db.session.add(found_subscription)
            db.session.commit()
            return flask.jsonify({'error_msg': 'Version {} not recognized'.format(version_integer)}), 473

    subscription_check.is_ok = True
    subscription_check.status_message = 'OK'
    db.session.add(subscription_check)
    found_subscription.subscription_checks.append(subscription_check)
    found_subscription.is_last_check_ok = subscription_check.is_ok
    db.session.add(found_subscription)
    db.session.commit()

    try:
        with open(os.path.join(STATIC_FOLDER, 'subscription', '{}.css'.format(found_subscription.subscription_plan.name)), 'r') as css_file:
            style = css_file.read()
    except FileNotFoundError:
        style = None

    data = {
        'active': found_subscription.is_active,  # boolean
        'status': 'active' if found_subscription.is_active else 'inactive',  # textual status
        'plan': found_subscription.subscription_plan.name,  # one of ['premium', 'enterprise', 'enterprise_plus']]
        'quantity': found_subscription.quantity,  # integer, special action when quantity == 1000, can be None
        'amount': found_subscription.amount,  # Price amount in cents can be None
        'period_end': found_subscription.period_end.timestamp() if found_subscription.period_end else None,  # When current subscription period ends timestamp INT can be None
        'trial_end': found_subscription.trial_end.timestamp() if found_subscription.trial_end else None,  # When trial period ends timestamp INT, can be None
        'cancel_at_period_end': found_subscription.is_cancel_at_period_end,  # Boolean if cancel subscription on period_end
        'balance': found_subscription.balance,  # Must be negative number to show, maybe invoice payment ? Can be None
        'url_key': found_subscription.url_key,  # string https://app.pritunl.com/support/%'url_key%, Can be None
        'styles': {
            'etag': 'W/"wzsdm-1533603987-128671-1753221263"',
            'last_modified': 'Mon, 06 Aug 2018 21:06:27 GMT',
            'data': style
        },  # !IMPORTANT CSS styles for given PLAN! Css styles actually changes functionality in prinutl!
    }

    return flask.jsonify(data), 200


@api_dedicated.route('/ip', methods=['GET'])
def get_ip():
    """
    Detect remote public IP
    :return: detected remote IP
    """

    # 200 ON OK
    return flask.jsonify({'ip': get_remote_ip()}), 200  # Return IP address


@api_dedicated.route('/notification/<int:version_int>', methods=['GET'])
def get_notification(version_int: int):

    # www: can be 'ok' or 'disabled' when disabled, www interface throws 401 on every request
    # vpn: does noting in pritunl
    # message: when filled, shows popup message on homepage

    return flask.jsonify({'message': '', 'www': 'ok', 'vpn': 'ok'}), 200  # Return IP address


@api_dedicated.route('/subscription', methods=['DELETE'])
def delete_subscription():

    license = flask.request.json.get('license')  # Application installation licence

    # 200 ON OK
    return flask.jsonify(), 200


@api_dedicated.route('/subscription', methods=['PUT'])
def put_subscription():

    license = flask.request.json.get('license')  # Application installation licence
    card = flask.request.json.get('card')  # Application installation licence stripe.token.id
    plan = flask.request.json.get('plan')  # Application installation licence one of ['premium', 'enterprise', 'enterprise_plus']
    email = flask.request.json.get('email')  # Application installation licence stripe.email

    # 200 ON OK
    return flask.jsonify(), 200


@api_dedicated.route('/v1/request/azure', methods=['GET'])
def get_sso_azure():
    license = flask.request.json.get('license')
    callback = flask.request.json.get('callback')
    state = flask.request.json.get('state')
    secret = flask.request.json.get('secret')
    directory_id = flask.request.json.get('directory_id')
    app_id = flask.request.json.get('app_id')
    app_secret = flask.request.json.get('app_secret')

    # Non 200 return code is error, 401 for denied
    # return flask.jsonify({}), 401

    return flask.jsonify({'url', ''}), 200 # redirect URL


@api_dedicated.route('/update/azure', methods=['GET'])
def update_sso_azure():
    user = flask.request.args.get('user')
    license = flask.request.args.get('license')
    directory_id = flask.request.args.get('directory_id')
    app_id = flask.request.args.get('app_id')
    app_secret = flask.request.args.get('app_secret')

    return flask.jsonify({}), 200  # 200 OK


@api_dedicated.route('/v1/request/google', methods=['GET'])
def get_sso_google():
    license = flask.request.json.get('license')
    callback = flask.request.json.get('callback')
    state = flask.request.json.get('state')
    secret = flask.request.json.get('secret')

    # Non 200 return code is error, 401 for denied
    # return flask.jsonify({}), 401

    return flask.jsonify({'url', ''}), 200  # redirect URL


@api_dedicated.route('/update/google', methods=['GET'])
def update_sso_google():
    user = flask.request.args.get('user')
    license = flask.request.args.get('license')

    return flask.jsonify({}), 200  # 200 OK


@api_dedicated.route('/v1/request/slack', methods=['GET'])
def get_sso_slack():
    license = flask.request.json.get('license')
    callback = flask.request.json.get('callback')
    state = flask.request.json.get('state')
    secret = flask.request.json.get('secret')

    # Non 200 return code is error, 401 for denied
    # return flask.jsonify({}), 401

    return flask.jsonify({'url', ''}), 200  # redirect URL


@api_dedicated.route('/update/slack', methods=['GET'])
def update_sso_slack():
    user = flask.request.args.get('user')
    team = flask.request.args.get('team')
    license = flask.request.args.get('license')

    return flask.jsonify({}), 200  # 200 OK


@api_dedicated.route('/v1/request/saml', methods=['GET'])
def sso_saml():
    license = flask.request.json.get('license')
    callback = flask.request.json.get('callback')
    state = flask.request.json.get('state')
    secret = flask.request.json.get('secret')
    sso_url = flask.request.json.get('sso_url')
    issuer_url = flask.request.json.get('issuer_url')
    cert = flask.request.json.get('cert')

    # Non 200 return code is error, 401 for denied
    # return flask.jsonify({}), 401

    return flask.jsonify({'content', 'XML'}), 200  # XML