from sqlalchemy import select, literal, union_all, desc, asc, func, or_, cast, String, Numeric, Date
from app.extensions import db
from app.models.inbound.buy import StockBuy
from app.models.inbound.semi import StockSemi
from app.models.inbound.product import StockProduct
from app.models.base import MaterialBase
import traceback


class InboundSummaryService:

    @staticmethod
    def get_list(page=1, per_page=10, keyword=None, start_date=None, end_date=None, source_type=None):
        """
        聚合查询：
        1. 联合 StockBuy, StockSemi, StockProduct 三张表
        2. 关联 MaterialBase 获取名称规格
        3. 计算动态状态 (库存耗尽显示已出库)
        4. 排序：默认按入库日期倒序 (最近的在前)
        """
        try:
            # =========================================================
            # 1. 构建三个子查询 (Subqueries)
            # =========================================================

            # --- A. 采购件 (StockBuy) ---
            q_buy = db.session.query(
                StockBuy.id.label('id'),
                StockBuy.base_id.label('base_id'),
                StockBuy.sku.label('sku'),
                StockBuy.in_date.label('inbound_date'),
                StockBuy.in_quantity.label('in_qty'),
                StockBuy.stock_quantity.label('current_qty'),

                cast(StockBuy.supplier_name, String).label('source_info'),
                StockBuy.status.label('orig_status'),
                cast(StockBuy.batch_number, String).label('batch_number'),
                cast(literal('buy'), String).label('source_type')
            )

            # --- B. 半成品 (StockSemi) ---
            q_semi = db.session.query(
                StockSemi.id.label('id'),
                StockSemi.base_id.label('base_id'),
                StockSemi.sku.label('sku'),
                StockSemi.production_date.label('inbound_date'),
                StockSemi.in_quantity.label('in_qty'),
                StockSemi.stock_quantity.label('current_qty'),

                cast(StockSemi.production_manager, String).label('source_info'),
                StockSemi.status.label('orig_status'),
                cast(StockSemi.batch_number, String).label('batch_number'),
                cast(literal('semi'), String).label('source_type')
            )

            # --- C. 成品 (StockProduct) ---
            q_product = db.session.query(
                StockProduct.id.label('id'),
                StockProduct.base_id.label('base_id'),
                StockProduct.sku.label('sku'),
                StockProduct.production_date.label('inbound_date'),
                StockProduct.in_quantity.label('in_qty'),
                StockProduct.stock_quantity.label('current_qty'),

                cast(StockProduct.production_manager, String).label('source_info'),
                StockProduct.status.label('orig_status'),
                cast(StockProduct.serial_number, String).label('batch_number'),
                cast(literal('product'), String).label('source_type')
            )

            # =========================================================
            # 2. 组合查询 (UNION ALL)
            # =========================================================
            combined_query = union_all(q_buy, q_semi, q_product)
            cte = combined_query.subquery()

            # =========================================================
            # 3. 主查询：关联 MaterialBase
            # =========================================================
            query = db.session.query(
                cte,
                MaterialBase.name.label('material_name'),
                MaterialBase.spec_model.label('spec_model'),
                MaterialBase.category.label('category'),
                MaterialBase.material_type.label('material_type')
            ).outerjoin(
                MaterialBase, cte.c.base_id == MaterialBase.id
            )

            # =========================================================
            # 4. 过滤条件
            # =========================================================
            if keyword:
                rule = or_(
                    cte.c.sku.ilike(f'%{keyword}%'),
                    cte.c.source_info.ilike(f'%{keyword}%'),
                    cte.c.batch_number.ilike(f'%{keyword}%'),
                    MaterialBase.name.ilike(f'%{keyword}%'),
                    MaterialBase.spec_model.ilike(f'%{keyword}%')
                )
                query = query.filter(rule)

            if start_date and end_date:
                query = query.filter(cte.c.inbound_date.between(start_date, end_date))

            if source_type:
                query = query.filter(cte.c.source_type == source_type)

            # =========================================================
            # 5. 获取总数
            # =========================================================
            count_query = db.session.query(func.count()) \
                .select_from(cte) \
                .outerjoin(MaterialBase, cte.c.base_id == MaterialBase.id)

            if keyword:
                count_query = count_query.filter(rule)
            if start_date and end_date:
                count_query = count_query.filter(cte.c.inbound_date.between(start_date, end_date))
            if source_type:
                count_query = count_query.filter(cte.c.source_type == source_type)

            total = count_query.scalar() or 0

            # =========================================================
            # 6. 排序与分页
            # =========================================================
            # ★★★ 修改处：优先按入库日期倒序排列 (最近的在前) ★★★
            # 如果日期相同，再按 SKU 排序，保证分页稳定性
            query = query.order_by(desc(cte.c.inbound_date), asc(cte.c.sku))

            pagination = query.limit(per_page).offset((page - 1) * per_page).all()

            # =========================================================
            # 7. 数据格式化
            # =========================================================
            items = []
            type_map = {
                'buy': '采购入库',
                'semi': '半成品生产',
                'product': '成品完工'
            }

            for row in pagination:
                date_str = ""
                if row.inbound_date:
                    try:
                        date_str = row.inbound_date.strftime('%Y-%m-%d')
                    except Exception:
                        date_str = str(row.inbound_date)

                in_qty = float(row.in_qty) if row.in_qty is not None else 0.0
                current_qty = float(row.current_qty) if row.current_qty is not None else 0.0

                # 状态逻辑
                final_status = row.orig_status
                if current_qty <= 0:
                    final_status = "已出库"
                elif current_qty < in_qty:
                    final_status = "部分出库"

                items.append({
                    'id': row.id,
                    'sku': row.sku or "",
                    'name': row.material_name or "未知物品",
                    'spec_model': row.spec_model or "",
                    'category': row.category or "",
                    'material_type': row.material_type or "",

                    'inbound_date': date_str,
                    'quantity': in_qty,
                    'current_qty': current_qty,
                    'source_info': row.source_info or "",
                    'status': final_status,
                    'source_type': row.source_type,
                    'type_label': type_map.get(row.source_type, "未知类型"),
                    'batch_number': row.batch_number or ""
                })

            return {
                'items': items,
                'total': total,
                'pages': (total + per_page - 1) // per_page if per_page > 0 else 0,
                'current_page': page
            }

        except Exception as e:
            print("【InboundSummaryService Error】:", str(e))
            traceback.print_exc()
            raise e