from flask import Blueprint, request, jsonify, current_app
from app.services.bom_service import BomService
from app.models.base import MaterialBase
from app.models.bom import BomTable
from app.extensions import db
from flask_jwt_extended import jwt_required, get_jwt
from app.utils.decorators import permission_required, audit_log
from app.services.auth_service import AuthService

bom_bp = Blueprint('bom', __name__)


# ==============================================================================
# 辅助函数：获取当前用户的完整权限列表（基于角色查询）
# ==============================================================================
def get_current_user_permissions():
    """
    返回当前用户拥有的所有权限码列表（包括菜单和元素）
    此函数根据角色查询数据库得到权限。
    """
    claims = get_jwt()
    user_role = claims.get('role')
    if not user_role:
        return []
    # 超级管理员返回所有字段权限 (忽略大小写)
    if user_role.upper() == 'SUPER_ADMIN':
        return ['bom_manage:*']
    perm_dict = AuthService.get_user_permissions(user_role)
    # 合并菜单和元素权限
    perms = perm_dict.get('menus', []) + perm_dict.get('elements', [])
    return perms


def filter_item_by_permissions(item_dict, user_permissions):
    """
    根据用户权限过滤 item 字典，无权限的字段值置为 None
    """
    # 字段名到权限码的映射（与前端 permissionMap 保持一致）
    field_to_perm = {
        'bom_no': 'bom_manage:bom_no',
        'parent_name': 'bom_manage:parent_name',
        'parent_spec': 'bom_manage:parent_spec',
        'version': 'bom_manage:version',
        'is_enabled': 'bom_manage:status',
        'child_count': 'bom_manage:child_count',
    }
    # 如果用户是超级管理员且有 'bom_manage:*'，则不过滤
    if 'bom_manage:*' in user_permissions:
        return item_dict
    for field, perm_code in field_to_perm.items():
        if field in item_dict and perm_code not in user_permissions:
            item_dict[field] = None
    return item_dict


# ==================== 新版 BOM 接口（基于 bom_no） ====================

@bom_bp.route('/list', methods=['GET'])
@jwt_required()
@permission_required('bom_manage')
def get_bom_list():
    """获取所有 BOM 配方列表，支持 keyword 搜索和 active_only 过滤"""
    try:
        keyword = request.args.get('keyword', '').strip()
        # 将字符串 'true' 转为布尔值
        active_only = request.args.get('active_only', 'false').lower() == 'true'

        data = BomService.get_bom_list(keyword=keyword, active_only=active_only)
        # 字段级脱敏
        user_permissions = get_current_user_permissions()
        if isinstance(data, list):
            data = [filter_item_by_permissions(item, user_permissions) for item in data]
        return jsonify({
            'code': 200,
            'msg': 'success',
            'data': data
        })
    except Exception as e:
        current_app.logger.error(f'获取BOM列表失败: {str(e)}')
        return jsonify({'code': 500, 'msg': '内部服务器错误'}), 500


@bom_bp.route('/detail/<path:bom_no>', methods=['GET'])
@jwt_required()
@permission_required('bom_manage')
def get_bom_detail(bom_no):
    """
    根据 BOM 编号获取配方详情
    Query参数: ?version=V1.0 (如果不传则取最新)
    """
    try:
        version = request.args.get('version')
        data = BomService.get_bom_detail(bom_no, version=version)
        if not data:
            return jsonify({'code': 404, 'msg': 'BOM 不存在'}), 404
        # 字段级脱敏
        user_permissions = get_current_user_permissions()
        data = filter_item_by_permissions(data, user_permissions)
        return jsonify({
            'code': 200,
            'msg': 'success',
            'data': data
        })
    except Exception as e:
        current_app.logger.error(f'获取BOM详情失败: {str(e)}')
        return jsonify({'code': 500, 'msg': '内部服务器错误'}), 500


@bom_bp.route('/save', methods=['POST'])
@jwt_required()
@permission_required('bom_manage:operation')
@audit_log(
    module='BOM管理',
    action='新增',
    get_target_name_fn=lambda: request.get_json().get('bom_no') if request.get_json() else None
)
def save_bom():
    """保存或更新 BOM 配方（支持自定义 bom_no 和 多版本）"""
    try:
        req_data = request.get_json()
        # 数据清洗：移除用户没有权限的字段
        user_permissions = get_current_user_permissions()
        # 超级管理员不过滤
        if 'bom_manage:*' not in user_permissions:
            # 字段名到权限码的映射
            field_to_perm = {
                'parent_id': 'bom_manage:parent_id',
                'version': 'bom_manage:version',
                'is_enabled': 'bom_manage:status',
                'bom_no': 'bom_manage:bom_no',
            }
            # 清洗顶级字段
            for field in list(req_data.keys()):
                perm_code = field_to_perm.get(field)
                if perm_code and perm_code not in user_permissions:
                    req_data.pop(field, None)
            # 清洗 children 中的字段
            if 'children' in req_data and isinstance(req_data['children'], list):
                for child in req_data['children']:
                    # 子件字段映射
                    child_field_to_perm = {
                        'child_id': 'bom_manage:child_id',
                        'dosage': 'bom_manage:dosage',
                        'remark': 'bom_manage:remark',
                    }
                    for field in list(child.keys()):
                        perm_code = child_field_to_perm.get(field)
                        if perm_code and perm_code not in user_permissions:
                            child.pop(field, None)

        # 必需字段校验
        if 'parent_id' not in req_data or 'children' not in req_data:
            return jsonify({'code': 400, 'msg': '缺少 parent_id 或 children 字段'}), 400

        # 校验 bom_no 不能为空
        if 'bom_no' in req_data and not req_data['bom_no']:
            return jsonify({'code': 400, 'msg': 'BOM编号不能为空'}), 400

        bom_no = BomService.save_bom(req_data)
        return jsonify({
            'code': 200,
            'msg': '保存成功',
            'data': {'bom_no': bom_no}
        })
    except ValueError as e:
        return jsonify({'code': 400, 'msg': str(e)}), 400
    except Exception as e:
        current_app.logger.error(f'保存BOM失败: {str(e)}')
        return jsonify({'code': 500, 'msg': '内部服务器错误'}), 500


@bom_bp.route('/stock/<path:bom_no>', methods=['GET'])
@jwt_required()
@permission_required('bom_manage')
def get_bom_with_stock_by_no(bom_no):
    """根据 BOM 编号获取配方详情及库存信息"""
    try:
        data = BomService.get_bom_with_stock_by_bom_no(bom_no)
        if not data:
            return jsonify({'code': 404, 'msg': 'BOM 不存在'}), 404
        # 字段级脱敏
        user_permissions = get_current_user_permissions()
        data = filter_item_by_permissions(data, user_permissions)
        return jsonify({
            'code': 200,
            'msg': 'success',
            'data': data
        })
    except Exception as e:
        current_app.logger.error(f'获取BOM库存信息失败: {str(e)}')
        return jsonify({'code': 500, 'msg': '内部服务器错误'}), 500


# ==================== 删除BOM接口 ====================

@bom_bp.route('/<path:bom_no>', methods=['DELETE'])
@jwt_required()
@permission_required('bom_manage:operation')
@audit_log(
    module='BOM管理',
    action='删除',
    get_target_id_fn=lambda: request.view_args.get('bom_no')
)
def delete_bom(bom_no):
    """
    根据 BOM 编号删除
    Query参数: ?version=V1.0 (如果不传，删除该编号下所有版本)
    """
    try:
        version = request.args.get('version')
        query = BomTable.query.filter_by(bom_no=bom_no)

        if version:
            query = query.filter_by(version=version)

        exist = query.first()
        if not exist:
            return jsonify({'code': 404, 'msg': 'BOM 不存在'}), 404

        # 删除
        query.delete()
        db.session.commit()
        return jsonify({
            'code': 200,
            'msg': '删除成功'
        })
    except Exception as e:
        current_app.logger.error(f'删除BOM失败: {str(e)}')
        return jsonify({'code': 500, 'msg': '内部服务器错误'}), 500


# ==================== 兼容旧接口 ====================

@bom_bp.route('/<int:parent_id>', methods=['GET'])
@jwt_required()
@permission_required('bom_manage')
def get_bom(parent_id):
    try:
        data = BomService.get_bom_with_stock(parent_id)
        # 字段级脱敏
        user_permissions = get_current_user_permissions()
        data = filter_item_by_permissions(data, user_permissions)
        return jsonify({
            'code': 200,
            'msg': 'success',
            'data': data
        })
    except Exception as e:
        current_app.logger.error(f'获取BOM失败: {str(e)}')
        return jsonify({'code': 500, 'msg': '内部服务器错误'}), 500


@bom_bp.route('', methods=['POST'])
@jwt_required()
@permission_required('bom_manage:operation')
@audit_log(
    module='BOM管理',
    action='新增',
    get_target_name_fn=lambda: request.get_json().get('bom_no') if request.get_json() else None
)
def save_bom_legacy():
    try:
        req_data = request.get_json()
        # 数据清洗：移除用户没有权限的字段
        user_permissions = get_current_user_permissions()
        # 超级管理员不过滤
        if 'bom_manage:*' not in user_permissions:
            # 字段名到权限码的映射
            field_to_perm = {
                'parent_id': 'bom_manage:parent_id',
                'version': 'bom_manage:version',
                'is_enabled': 'bom_manage:status',
                'bom_no': 'bom_manage:bom_no',
            }
            # 清洗顶级字段
            for field in list(req_data.keys()):
                perm_code = field_to_perm.get(field)
                if perm_code and perm_code not in user_permissions:
                    req_data.pop(field, None)
            # 清洗 children 中的字段
            if 'children' in req_data and isinstance(req_data['children'], list):
                for child in req_data['children']:
                    # 子件字段映射
                    child_field_to_perm = {
                        'child_id': 'bom_manage:child_id',
                        'dosage': 'bom_manage:dosage',
                        'remark': 'bom_manage:remark',
                    }
                    for field in list(child.keys()):
                        perm_code = child_field_to_perm.get(field)
                        if perm_code and perm_code not in user_permissions:
                            child.pop(field, None)

        parent_id = req_data.get('parent_id')
        child_list = req_data.get('children', [])
        if not parent_id or not isinstance(child_list, list):
            return jsonify({'code': 400, 'msg': '参数错误'}), 400
        BomService.create_or_update_bom(parent_id, child_list)
        return jsonify({
            'code': 200,
            'msg': '保存成功'
        })
    except ValueError as e:
        return jsonify({'code': 400, 'msg': str(e)}), 400
    except Exception as e:
        current_app.logger.error(f'保存BOM失败: {str(e)}')
        return jsonify({'code': 500, 'msg': '内部服务器错误'}), 500


@bom_bp.route('/base/list', methods=['GET'])
@jwt_required()
@permission_required('bom_manage')
def get_material_base_list():
    """获取所有基础物料列表，用于前端下拉框"""
    try:
        materials = MaterialBase.query.filter_by(is_enabled=True).order_by(MaterialBase.id.desc()).all()
        data = [item.to_dict() for item in materials]
        # 字段级脱敏 (如果需要，但此接口通常用于下拉选择，可能不需要脱敏)
        # 保持原样
        return jsonify({
            'code': 200,
            'msg': 'success',
            'data': data
        })
    except Exception as e:
        current_app.logger.error(f'获取基础物料列表失败: {str(e)}')
        return jsonify({'code': 500, 'msg': '内部服务器错误'}), 500


@bom_bp.route('/parents', methods=['GET'])
@jwt_required()
@permission_required('bom_manage')
def get_bom_parents():
    """获取所有已定义BOM的父件物料列表（兼容旧版）"""
    try:
        subq = db.session.query(BomTable.parent_id).distinct().subquery()
        parents = MaterialBase.query.join(subq, MaterialBase.id == subq.c.parent_id).all()
        data = [item.to_dict() for item in parents]
        # 字段级脱敏 (如果需要)
        user_permissions = get_current_user_permissions()
        data = [filter_item_by_permissions(item, user_permissions) for item in data]
        return jsonify({
            'code': 200,
            'msg': 'success',
            'data': data
        })
    except Exception as e:
        current_app.logger.error(f'获取BOM父件列表失败: {str(e)}')
        return jsonify({'code': 500, 'msg': '内部服务器错误'}), 500
