import time
from flask import Blueprint, request, session, url_for, send_file
from flask import render_template, redirect, jsonify
from werkzeug.security import gen_salt
from authlib.integrations.flask_oauth2 import current_token
from authlib.oauth2 import OAuth2Error
from .models import db, User, OAuth2Client
from .oauth2 import authorization, require_oauth
from .settings import resource_api
import requests
import json
import logging
import sys, os


log_path = os.path.dirname(os.path.abspath(__file__))
log_file = os.path.join(log_path, 'logs/test.log')
logging.basicConfig(filename=log_file, level=logging.DEBUG)
log = logging.getLogger("authlib")

bp = Blueprint('home', __name__)


def current_user():
    if 'id' in session:
        uid = session['id']
        return User.query.get(uid)
    return None


def split_by_crlf(s):
    return [v for v in s.splitlines() if v]

@bp.route('/apple-app-site-association', methods=["GET"])
def apple_app_association():
    return send_file("./files/apple-app-site-association")


@bp.route('/', methods=('GET', 'POST'))
def home():
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        user = User.query.filter_by(username=username, password=password).first()
        if not user:
            # 返回错误信息
            # user = User(username=username)
            # db.session.add(user)
            # db.session.commit()
            return render_template('login.html')
        
        session['id'] = user.id
        # if user is not just to log in, but need to head back to the auth page, then go for it
        next_page = request.args.get('next')
        if next_page:
            return redirect(next_page)
        return redirect('/')
    user = current_user()
    # if user:
    #     clients = OAuth2Client.query.filter_by(user_id=user.id).all()
    # else:
    #     clients = []
    clients = []

    return render_template('login.html', user=user, clients=clients)


@bp.route('/logout')
def logout():
    del session['id']
    return redirect('/')


@bp.route('/create_client', methods=('GET', 'POST'))
def create_client():
    user = current_user()
    if not user:
        return redirect('/')
    if request.method == 'GET':
        return render_template('create_client.html')

    client_id = gen_salt(24)
    client_id_issued_at = int(time.time())
    client = OAuth2Client(
        client_id=client_id,
        client_id_issued_at=client_id_issued_at,
        user_id=user.id,
    )

    form = request.form
    client_metadata = {
        "client_name": form["client_name"],
        "client_uri": form["client_uri"],
        "grant_types": split_by_crlf(form["grant_type"]),
        "redirect_uris": split_by_crlf(form["redirect_uri"]),
        "response_types": split_by_crlf(form["response_type"]),
        "scope": form["scope"],
        "token_endpoint_auth_method": form["token_endpoint_auth_method"]
    }
    client.set_client_metadata(client_metadata)

    if form['token_endpoint_auth_method'] == 'none':
        client.client_secret = ''
    else:
        client.client_secret = gen_salt(48)

    db.session.add(client)
    db.session.commit()
    return redirect('/')


@bp.route('/oauth/authorize', methods=['GET', 'POST'])
def authorize():
    user = current_user()
    # if user log status is not true (Auth server), then to log it in
    if not user:
        return redirect(url_for('home.home', next=request.url))
    if request.method == 'GET':
        try:
            grant = authorization.get_consent_grant(end_user=user)
        except OAuth2Error as error:
            return error.error
        return render_template('authorize.html', user=user, grant=grant)
    if not user and 'username' in request.form:
        username = request.form.get('username')
        user = User.query.filter_by(username=username).first()
    if request.form['confirm']:
        grant_user = user
    else:
        grant_user = None
        authorization.create_authorization_response(grant_user=grant_user)
    log.debug("123")
    log.info("post res: {}".format(authorization.create_authorization_response(grant_user=grant_user).__dict__))
    return authorization.create_authorization_response(grant_user=grant_user)


@bp.route('/oauth/token', methods=['POST'])
def issue_token():
    return authorization.create_token_response()


@bp.route('/oauth/revoke', methods=['POST'])
def revoke_token():
    return authorization.create_endpoint_response('revocation')


@bp.route('/api/me', methods=['POST', 'GET'])
@require_oauth('profile')
def api_me():
    # token中获取用户信息
    user = current_token.user

    # resource flask中请求 oath不链接资源服务器
    param = request.get_json()
    result = _get_resource(param, user)
    return jsonify(result)

    user = current_token.user
    return jsonify(id=user.id, username=user.username)


def _get_resource(param, user):

    print(param)
    intent = param.get('intent')
    url = resource_api + '/' + intent + '?user=' + user.username
    res = requests.post(url, json=param, timeout=5)
    # 通用错误信息需要定义
    _data = {}

    if res.status_code == 200:
        _data =  json.loads(res.content)

    print(_data)
    return _data
