from app.extensions import db
from app.models.bom import BomTable
from app.models.base import MaterialBase
from app.models.inbound.buy import StockBuy
from sqlalchemy import func

class BomService:
    @staticmethod
    def create_or_update_bom(parent_id, child_list):
        """
        保存/更新父件的BOM子件关系
        child_list: [{"child_id": int, "dosage": float, "loss_rate": float, "remark": str}, ...]
        """
        # 删除该父件原有的BOM记录
        BomTable.query.filter_by(parent_id=parent_id).delete()
        # 插入新的
        for item in child_list:
            bom = BomTable(
                parent_id=parent_id,
                child_id=item['child_id'],
                dosage=item.get('dosage', 0),
                loss_rate=item.get('loss_rate', 0),
                remark=item.get('remark', '')
            )
            db.session.add(bom)
        db.session.commit()
        return True

    @staticmethod
    def get_bom_with_stock(parent_id):
        """
        查询父件的BOM结构及库存信息
        """
        bom_items = db.session.query(
            BomTable,
            MaterialBase.name.label('child_name')
        ).join(
            MaterialBase, BomTable.child_id == MaterialBase.id
        ).filter(
            BomTable.parent_id == parent_id
        ).all()

        result = []
        for bom, child_name in bom_items:
            # 查询该子件在 StockBuy 中的可用库存总量
            stock_qty = db.session.query(
                func.coalesce(func.sum(StockBuy.available_quantity), 0)
            ).filter(
                StockBuy.base_id == bom.child_id
            ).scalar() or 0

            # 计算最大可生产数量
            dosage = float(bom.dosage) if bom.dosage else 0
            max_producible = int(stock_qty // dosage) if dosage > 0 else 0

            result.append({
                'child_id': bom.child_id,
                'child_name': child_name,
                'dosage': dosage,
                'current_stock': float(stock_qty),
                'max_producible': max_producible,
                'remark': bom.remark or ''
            })
        return result
