import uuid
import base64
import json
from datetime import timedelta
from flask import Flask, request, jsonify, g
from flask_bcrypt import Bcrypt
import redis
import pymysql
from pymysql.err import OperationalError

app = Flask(__name__)
# 输出 JSON 时保留非 ASCII 字符（如中文）
app.config['JSON_AS_ASCII'] = False

DB_CONFIG = {
    'host': '120.77.232.73',
    'port': 3306,
    'user': 'yswg_it_cangchu',
    'password': 'Yswg@inv-cangchu241011420',
    'db': 'inventory'
}
# REDIS_CONN = {
#     "redis_host": "120.77.232.73",
#     "redis_port": 6379,
#     "redis_pwd": "yswgInventoryTest@202307#",
#     "redis_db": 1
#
# }
REDIS_CONN = {
    "redis_host": "113.100.143.162",
    "redis_port": 6379,
    "redis_pwd": "fG7#vT6kQ1pX",
    "redis_db": 14

}


def mysql_db_conn():
    connect_mysql_db = pymysql.connect(host=DB_CONFIG['host'], port=DB_CONFIG['port'],
                                       user=DB_CONFIG['user'],
                                       password=DB_CONFIG['password'], database=DB_CONFIG['db'],
                                       charset="utf8mb4")
    return connect_mysql_db


def redis_db_conn():
    redis_client = redis.Redis(host=REDIS_CONN['redis_host'], port=REDIS_CONN['redis_port'],
                               password=REDIS_CONN['redis_pwd'], db=REDIS_CONN['redis_db'])
    return redis_client


# 初始化Flask-Bcrypt
dbcrypt = Bcrypt(app)


# 生成 UUID
def generate_token():
    raw = uuid.uuid4().bytes
    token = base64.urlsafe_b64encode(raw).rstrip(b'=').decode('utf-8')
    return token


# 公共方法：获取当前请求的用户信息
def get_current_user():
    """
    从 flask.g 获取当前用户信息（dict），如果不存在返回 None
    """
    return getattr(g, 'current_user', None)

# 中间件：在每次请求前校验 token（除登录外）
@app.before_request
def verify_token_middleware():
    # 登录接口不需要校验 token
    if request.endpoint == 'login':
        return None

    token = request.headers.get('inventory-token')
    print(' 从请求的 headers 获取 token： ', token)
    if not token:
        return jsonify({'code': 401, 'error': '缺少 inventory-token'})

    redis_client = redis_db_conn()
    user_json = redis_client.get(token)
    redis_client.close()
    print('根据 token 去redis查询 是否过期')
    if not user_json:
        return jsonify({'code': 401, 'error': '无效或已过期的 token'})
    try:
        g.current_user = json.loads(user_json)
    except json.JSONDecodeError:
        return jsonify({'code': 500, 'error': '解析信息失败'})

@app.route('/index', methods=['GET'])
def index_():
    user = get_current_user()
    print('打印请求用户的信息：', user)
    return jsonify({
        'message': f'欢迎，{user["name"]}！',
        'user_id': user['id']
    })

@app.route('/user/members/index', methods=['GET'])
def user_index():
    user = get_current_user()
    print('打印请求用户的信息：', user)
    return jsonify({
        'message': f'欢迎，{user["name"]}！',
        'user_id': user['id']
    })


@app.route('/login', methods=['POST'])
def login():
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    print(username)
    print(password)
    if not username or not password:
        return jsonify({"code": 400, 'error': '用户名和密码不能为空'})

    # SQL 查询用户
    try:
        conn = mysql_db_conn()
        # 设置 pymysql.cursors.DictCursor 字典输出 格式
        with conn.cursor(pymysql.cursors.DictCursor) as cursor:
            sql = f"SELECT `password`,id,name,email FROM users WHERE wechat_id='{username}' LIMIT 1"
            print(sql)
            cursor.execute(sql)
            user = cursor.fetchone()
            print('查询用户是否存在：', user)
    except OperationalError:
        # 数据库连接失败，请检查配置
        return jsonify({"code": 500, 'error': '服务端 错误'})
    finally:
        try:
            conn.close()
        except:
            pass
    if user is None:
        return jsonify({"code": 404, 'error': '用户不存在'})
    # 检查密码
    if not dbcrypt.check_password_hash(user['password'], password):
        return jsonify({"code": 401, 'error': '密码 或 用户名 错误'})
    # 生成token并存储到Redis中
    token = generate_token()
    user_obj = {
        'id': user['id'],
        'name': user['name'],
        'email': user['email'],
    }
    print(token)
    # 序列化时保留中文
    redis_client = redis_db_conn()
    redis_client.setex(token, timedelta(hours=23), json.dumps(user_obj, ensure_ascii=False))
    redis_client.close()
    return jsonify({"code": 200, 'token': token}), 200


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)
