# 文件路径: app/services/inbound/base_service.py

from app.extensions import db
from app.models.base import MaterialBase
from app.models.inbound.buy import StockBuy
from app.models.inbound.semi import StockSemi
from sqlalchemy import or_
import traceback


class MaterialBaseService:
    """
    基础物料服务层
    负责处理 MaterialBase 的增删改查及搜索逻辑
    """

    @staticmethod
    def search_material(keyword):
        """
        根据关键字搜索已启用的基础物料
        (供 /api/v1/inbound/base/search 接口调用)
        """
        try:
            if not keyword:
                return []

            # ✅ 搜索范围增加 common_name (俗名)
            query = MaterialBase.query.filter(
                MaterialBase.is_enabled == True,
                or_(
                    MaterialBase.name.ilike(f'%{keyword}%'),
                    MaterialBase.common_name.ilike(f'%{keyword}%'),
                    MaterialBase.spec_model.ilike(f'%{keyword}%')
                )
            ).limit(20)

            results = []
            for item in query.all():
                results.append({
                    'id': item.id,
                    'name': item.name,
                    'commonName': item.common_name, # ✅ 返回俗名
                    'spec': item.spec_model,
                    'category': item.category,
                    'unit': item.unit,
                    'type': item.material_type,
                    'status': '启用'
                })
            return results
        except Exception as e:
            traceback.print_exc()
            return []

    @staticmethod
    def get_list(page, limit, filters=None):
        """
        获取基础信息列表 (带分页和筛选)
        """
        try:
            query = MaterialBase.query

            if filters:
                # 1. 关键词模糊搜索 (名称 或 俗名 或 规格型号)
                if filters.get('keyword'):
                    kw = f"%{filters['keyword']}%"
                    # ✅ 增加俗名搜索
                    query = query.filter(or_(
                        MaterialBase.name.ilike(kw),
                        MaterialBase.common_name.ilike(kw),
                        MaterialBase.spec_model.ilike(kw)
                    ))

                # 2. 精确筛选
                if filters.get('category'):
                    query = query.filter_by(category=filters['category'])

                if filters.get('type'):
                    query = query.filter_by(material_type=filters['type'])

                if filters.get('isEnabled') is not None:
                    # 前端传 1/0，转为 Boolean
                    is_active = bool(int(filters['isEnabled']))
                    query = query.filter_by(is_enabled=is_active)

            # 按 ID 倒序排列
            pagination = query.order_by(MaterialBase.id.desc()).paginate(page=page, per_page=limit, error_out=False)

            items = [item.to_dict() for item in pagination.items]
            return {"total": pagination.total, "items": items}

        except Exception as e:
            print(f"查询基础信息列表失败: {e}")
            return {"total": 0, "items": []}

    @staticmethod
    def create_material(data):
        """新增基础信息"""
        try:
            # 0. 基础校验
            if not data.get('name') or not data.get('spec'):
                raise ValueError("名称和规格型号不能为空")

            # 1. 查重 (名称+规格型号 唯一)
            # 注意：俗名不参与唯一性校验，允许重复或为空
            exist = MaterialBase.query.filter_by(
                name=data['name'],
                spec_model=data['spec']
            ).first()
            if exist:
                raise ValueError(f"已存在相同名称和规格的数据 (ID: {exist.id})")

            # 2. 创建对象
            new_material = MaterialBase(
                name=data['name'],
                common_name=data.get('commonName'), # ✅ 读取俗名
                spec_model=data['spec'],
                category=data.get('category'),
                material_type=data.get('type'),
                unit=data.get('unit'),
                visibility_level=data.get('visibilityLevel'),
                manual_link=data.get('generalManual'),
                product_image=data.get('generalImage'),
                is_enabled=True if data.get('isEnabled', 1) == 1 else False
            )

            db.session.add(new_material)
            db.session.commit()
            return new_material

        except Exception as e:
            db.session.rollback()
            raise e

    @staticmethod
    def update_material(m_id, data):
        """修改基础信息"""
        try:
            material = MaterialBase.query.get(m_id)
            if not material:
                raise ValueError("数据不存在")

            # 更新字段
            if 'name' in data: material.name = data['name']
            if 'commonName' in data: material.common_name = data['commonName'] # ✅ 更新俗名
            if 'spec' in data: material.spec_model = data['spec']
            if 'category' in data: material.category = data['category']
            if 'type' in data: material.material_type = data['type']
            if 'unit' in data: material.unit = data['unit']
            if 'visibilityLevel' in data: material.visibility_level = data['visibilityLevel']
            if 'generalManual' in data: material.manual_link = data['generalManual']
            if 'generalImage' in data: material.product_image = data['generalImage']

            if 'isEnabled' in data:
                material.is_enabled = bool(int(data['isEnabled']))

            db.session.commit()
            return material

        except Exception as e:
            db.session.rollback()
            raise e

    @staticmethod
    def delete_material(m_id):
        """
        删除基础信息 (带依赖检查)
        """
        try:
            material = MaterialBase.query.get(m_id)
            if not material:
                raise ValueError("数据不存在")

            # 1. 依赖检查：采购入库引用
            buy_usage_count = StockBuy.query.filter_by(base_id=m_id).count()

            # 2. 依赖检查：半成品入库引用
            semi_usage_count = StockSemi.query.filter_by(base_id=m_id).count()

            total_usage = buy_usage_count + semi_usage_count

            if total_usage > 0:
                raise ValueError(
                    f"无法删除：该基础物料正被使用中。\n"
                    f"- 采购库存记录: {buy_usage_count} 条\n"
                    f"- 半成品库存记录: {semi_usage_count} 条\n"
                    f"请先清理相关库存或仅‘禁用’此条目。"
                )

            # 3. 执行删除
            db.session.delete(material)
            db.session.commit()
            return True

        except Exception as e:
            db.session.rollback()
            print(f"删除基础信息失败: {e}")
            raise e