"""
Phase 3 集成测试
测试产品聚合、采购管理的完整流程
"""

import pytest
from datetime import datetime, timedelta
from decimal import Decimal

from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker

from app.core.database import Base
from app.models.raw_orders import RawOrder
from app.models.normalized_orders import OrderItemNorm, ProcurementStatus
from app.models.products import (
    Product, PendingPurchase, PurchaseList, PurchaseListItem,
    ProductCategory, ProcurementPriority
)
from app.services.product_service import ProductAggregationService
from app.services.procurement_service import ProcurementService


@pytest.fixture
async def test_db():
    """创建测试数据库"""
    engine = create_async_engine("sqlite+aiosqlite:///:memory:", echo=False)
    
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)
    
    async_session = async_sessionmaker(engine, expire_on_commit=False)
    
    async with async_session() as session:
        yield session
    
    await engine.dispose()


@pytest.fixture
async def sample_normalized_orders(test_db):
    """创建示例标准化订单数据"""
    orders = [
        OrderItemNorm(
            id=1,
            product_key="prod_nike_001",
            sku_id="nike_aj1234_black_42",
            品牌="NIKE",
            货号="AJ1234",
            线上宝贝名称="Nike Air Jordan篮球鞋",
            颜色="黑色",
            尺寸="42",
            数量=2,
            订单单价=Decimal("899.00"),
            付款时间=datetime.now() - timedelta(days=5),
            procurement_status=ProcurementStatus.WAITING,
            图片='["http://img1.jpg", "http://img2.jpg"]'
        ),
        OrderItemNorm(
            id=2,
            product_key="prod_nike_001",  # 同一产品
            sku_id="nike_aj1234_black_42",
            品牌="NIKE",
            货号="AJ1234", 
            线上宝贝名称="Nike Air Jordan篮球鞋",
            颜色="黑色",
            尺寸="42",
            数量=1,
            订单单价=Decimal("899.00"),
            付款时间=datetime.now() - timedelta(days=3),
            procurement_status=ProcurementStatus.WAITING,
            图片='["http://img1.jpg"]'
        ),
        OrderItemNorm(
            id=3,
            product_key="prod_ysl_001",
            sku_id="ysl_999_red",
            品牌="圣罗兰",
            货号="999",
            线上宝贝名称="YSL圣罗兰口红999号色",
            颜色="红色",
            尺寸="标准",
            数量=5,
            订单单价=Decimal("320.00"),
            付款时间=datetime.now() - timedelta(days=2),
            procurement_status=ProcurementStatus.WAITING,
            图片='["http://img3.jpg"]'
        )
    ]
    
    for order in orders:
        test_db.add(order)
    await test_db.commit()
    
    return orders


@pytest.mark.asyncio
async def test_product_aggregation_service(test_db, sample_normalized_orders):
    """测试产品聚合服务"""
    service = ProductAggregationService()
    
    # 执行聚合
    result = await service.aggregate_products(test_db, force_rebuild=True)
    
    assert result["status"] == "success"
    assert result["processed_orders"] == 3
    assert result["created_products"] == 2  # 两个不同的产品
    assert result["updated_products"] == 0
    
    # 验证产品数据
    from sqlalchemy import select
    
    result = await test_db.execute(select(Product))
    products = result.scalars().all()
    
    assert len(products) == 2
    
    # 验证Nike产品聚合
    nike_product = next((p for p in products if p.品牌 == "NIKE"), None)
    assert nike_product is not None
    assert nike_product.总销量 == 3  # 2+1
    assert nike_product.订单数量 == 2
    assert nike_product.待采购数量 == 3
    assert nike_product.category == ProductCategory.SS  # 应该分类为鞋子
    assert nike_product.procurement_priority in [ProcurementPriority.LOW, ProcurementPriority.MEDIUM]
    
    # 验证YSL产品聚合
    ysl_product = next((p for p in products if p.品牌 == "圣罗兰"), None)
    assert ysl_product is not None
    assert ysl_product.总销量 == 5
    assert ysl_product.订单数量 == 1
    assert ysl_product.待采购数量 == 5
    assert ysl_product.category == ProductCategory.MC  # 应该分类为美妆


@pytest.mark.asyncio
async def test_pending_purchase_creation(test_db, sample_normalized_orders):
    """测试待采购记录创建"""
    service = ProductAggregationService()
    
    # 先聚合产品
    await service.aggregate_products(test_db, force_rebuild=True)
    
    # 验证待采购记录
    from sqlalchemy import select
    
    result = await test_db.execute(select(PendingPurchase))
    pending_purchases = result.scalars().all()
    
    assert len(pending_purchases) == 2
    
    # 检查数量
    total_demand = sum(p.需求数量 for p in pending_purchases)
    assert total_demand == 8  # 3 + 5


@pytest.mark.asyncio
async def test_procurement_service(test_db, sample_normalized_orders):
    """测试采购服务"""
    # 先聚合产品数据
    product_service = ProductAggregationService()
    await product_service.aggregate_products(test_db, force_rebuild=True)
    
    procurement_service = ProcurementService()
    
    # 创建采购清单
    purchase_list = await procurement_service.create_purchase_list(
        db=test_db,
        title="测试采购清单",
        supplier_name="测试供应商",
        creator="测试用户"
    )
    
    assert purchase_list.采购单号.startswith("PO")
    assert purchase_list.采购标题 == "测试采购清单"
    assert purchase_list.状态 == "草稿"
    
    # 添加商品到采购清单
    items = [
        {
            "product_key": "prod_nike_001",
            "quantity": 3,
            "unit_price": 850.00,
            "notes": "Nike篮球鞋采购"
        },
        {
            "product_key": "prod_ysl_001", 
            "quantity": 5,
            "unit_price": 280.00,
            "notes": "YSL口红采购"
        }
    ]
    
    add_result = await procurement_service.add_items_to_purchase_list(
        db=test_db,
        purchase_list_id=purchase_list.id,
        items=items
    )
    
    assert add_result["added_items"] == 2
    assert add_result["total_quantity"] == 8
    assert add_result["total_amount"] == 3950.00  # 3*850 + 5*280
    
    # 提交采购清单
    submitted_list = await procurement_service.submit_purchase_list(
        db=test_db,
        purchase_list_id=purchase_list.id,
        submitter="测试提交者"
    )
    
    assert submitted_list.状态 == "已提交"
    assert submitted_list.提交时间 is not None
    
    # 确认采购清单
    confirmed_list = await procurement_service.confirm_purchase_list(
        db=test_db,
        purchase_list_id=purchase_list.id,
        approver="测试审批者"
    )
    
    assert confirmed_list.状态 == "已确认"
    assert confirmed_list.确认时间 is not None
    assert confirmed_list.审批人 == "测试审批者"


@pytest.mark.asyncio
async def test_receive_items(test_db, sample_normalized_orders):
    """测试收货流程"""
    # 准备数据：聚合产品 -> 创建采购清单 -> 添加商品 -> 确认
    product_service = ProductAggregationService()
    await product_service.aggregate_products(test_db, force_rebuild=True)
    
    procurement_service = ProcurementService()
    
    purchase_list = await procurement_service.create_purchase_list(
        db=test_db,
        title="收货测试清单",
        supplier_name="测试供应商"
    )
    
    items = [
        {
            "product_key": "prod_nike_001",
            "quantity": 3,
            "unit_price": 850.00
        }
    ]
    
    await procurement_service.add_items_to_purchase_list(
        db=test_db,
        purchase_list_id=purchase_list.id,
        items=items
    )
    
    await procurement_service.submit_purchase_list(test_db, purchase_list.id)
    await procurement_service.confirm_purchase_list(test_db, purchase_list.id)
    
    # 获取采购项ID
    from sqlalchemy import select
    from sqlalchemy.orm import selectinload
    
    result = await test_db.execute(
        select(PurchaseList)
        .options(selectinload(PurchaseList.items))
        .filter(PurchaseList.id == purchase_list.id)
    )
    updated_list = result.scalar_one()
    
    assert len(updated_list.items) == 1
    item = updated_list.items[0]
    
    # 执行收货
    receipts = [
        {
            "item_id": item.id,
            "received_quantity": 2,
            "notes": "首次收货"
        }
    ]
    
    receive_result = await procurement_service.receive_items(test_db, receipts)
    
    assert receive_result["received_items"] == 1
    assert receive_result["total_received_quantity"] == 2
    
    # 验证收货更新
    await test_db.refresh(item)
    assert item.已到货数量 == 2
    assert item.待收货数量 == 1
    assert not item.is_received  # 未完全收货
    
    # 完成剩余收货
    final_receipts = [
        {
            "item_id": item.id,
            "received_quantity": 1,
            "notes": "最后收货"
        }
    ]
    
    await procurement_service.receive_items(test_db, final_receipts)
    
    # 验证完全收货
    await test_db.refresh(item)
    assert item.已到货数量 == 3
    assert item.待收货数量 == 0
    assert item.is_received
    assert item.收货时间 is not None


@pytest.mark.asyncio
async def test_procurement_stats(test_db, sample_normalized_orders):
    """测试采购统计"""
    # 准备数据
    product_service = ProductAggregationService()
    await product_service.aggregate_products(test_db, force_rebuild=True)
    
    procurement_service = ProcurementService()
    
    # 获取统计
    stats = await procurement_service.get_procurement_stats(test_db)
    
    assert "pending_purchases" in stats
    assert "purchase_lists" in stats
    
    pending_stats = stats["pending_purchases"]
    assert pending_stats["count"] == 2
    assert pending_stats["total_quantity"] == 8
    
    # 优先级分布
    assert "priority_distribution" in pending_stats
    priority_dist = pending_stats["priority_distribution"]
    assert len(priority_dist) > 0


@pytest.mark.asyncio
async def test_get_pending_purchases(test_db, sample_normalized_orders):
    """测试获取待采购列表"""
    # 准备数据
    product_service = ProductAggregationService()
    await product_service.aggregate_products(test_db, force_rebuild=True)
    
    procurement_service = ProcurementService()
    
    # 获取待采购列表
    result = await procurement_service.get_pending_purchases(
        db=test_db,
        page=1,
        page_size=10
    )
    
    assert "pending_purchases" in result
    assert "pagination" in result
    
    pending_purchases = result["pending_purchases"]
    assert len(pending_purchases) == 2
    
    # 验证分页信息
    pagination = result["pagination"]
    assert pagination["page"] == 1
    assert pagination["total"] == 2


@pytest.mark.asyncio
async def test_product_stats(test_db, sample_normalized_orders):
    """测试产品统计"""
    # 准备数据
    service = ProductAggregationService()
    await service.aggregate_products(test_db, force_rebuild=True)
    
    # 获取统计
    stats = await service.get_product_stats(test_db)
    
    assert stats["total_products"] == 2
    
    # 分类分布
    category_dist = stats["category_distribution"]
    assert "SS" in category_dist  # Nike鞋子
    assert "MC" in category_dist  # YSL口红
    assert category_dist["SS"] == 1
    assert category_dist["MC"] == 1
    
    # 采购信息
    procurement = stats["procurement"]
    assert procurement["pending_products"] == 2
    assert procurement["total_pending_quantity"] == 8


if __name__ == '__main__':
    pytest.main([__file__, '-v'])