"""
Phase 1 导入功能测试
"""

import os
import tempfile
import shutil
import asyncio
from pathlib import Path
from datetime import datetime
import pandas as pd
import pytest
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
from sqlalchemy import select

from app.core.database import Base
from app.models.raw_orders import RawOrder, ProcessedFile
from app.services.import_service import ImportService
from app.utils.file_hash import calculate_file_sha1
from app.utils.excel_reader import ExcelReader


@pytest.fixture
async def test_db():
    """创建测试数据库"""
    # 使用内存SQLite数据库
    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
def temp_directory():
    """创建临时目录"""
    temp_dir = tempfile.mkdtemp()
    yield Path(temp_dir)
    shutil.rmtree(temp_dir)


@pytest.fixture
def sample_excel_file(temp_directory):
    """创建示例Excel文件"""
    data = {
        '原始订单编号': ['ORDER001', 'ORDER001', 'ORDER002'],
        '网店名称': ['测试店铺', '测试店铺', '测试店铺'],
        '交易状态': ['交易成功', '交易成功', '交易关闭'],
        '付款时间': ['2025-01-15 10:30:00', '2025-01-15 10:30:00', '2025-01-16 14:20:00'],
        '线上宝贝名称': ['Nike 运动鞋', 'Nike T恤', 'Adidas 外套'],
        '线上销售属性': ['颜色:黑色;尺码:42', '颜色:白色;尺码:L', '颜色:蓝色;尺码:XL'],
        '线上商家编码': ['NK001', 'NK002', 'AD001'],
        '商品编号': ['SP001', 'SP002', 'SP003'],
        'SKU编号': ['SKU001', 'SKU002', 'SKU003'],
        '数量': [1, 2, 1],
        '订单单价': [599.0, 199.0, 899.0],
        '订单金额': [599.0, 398.0, 899.0],
        '买家留言': ['尽快发货', '尽快发货', ''],
        '卖家备注': ['', '', '大客户']
    }
    
    df = pd.DataFrame(data)
    excel_path = temp_directory / 'test_orders.xlsx'
    df.to_excel(excel_path, index=False)
    
    return excel_path


def test_file_hash_calculation(sample_excel_file):
    """测试文件哈希计算"""
    hash1 = calculate_file_sha1(sample_excel_file)
    hash2 = calculate_file_sha1(sample_excel_file)
    
    # 同一文件的哈希值应该相同
    assert hash1 == hash2
    assert len(hash1) == 40  # SHA1是40个字符的十六进制字符串


def test_excel_reader_basic(sample_excel_file):
    """测试Excel读取器基本功能"""
    reader = ExcelReader()
    
    # 读取Excel文件
    df = reader.read_excel(sample_excel_file)
    assert len(df) == 3
    assert '原始订单编号' in df.columns
    
    # 规范化列名
    df_normalized = reader.normalize_column_names(df)
    assert all(isinstance(col, str) for col in df_normalized.columns)
    
    # 清理数据
    df_cleaned = reader.clean_data(df_normalized)
    assert len(df_cleaned) == 3
    
    # 解析日期
    df_parsed = reader.parse_dates(df_cleaned)
    assert df_parsed['付款时间'].dtype.name.startswith('datetime')


def test_excel_reader_convert_to_records(sample_excel_file):
    """测试Excel转换为记录"""
    reader = ExcelReader()
    records = reader.process_excel_file(sample_excel_file)
    
    assert len(records) == 3
    
    # 检查第一条记录
    first_record = records[0]
    assert first_record['原始订单编号'] == 'ORDER001'
    assert first_record['网店名称'] == '测试店铺'
    assert first_record['数量'] == 1
    assert first_record['订单单价'] == 599.0
    assert 'row_idx' in first_record


@pytest.mark.asyncio
async def test_import_service_scan_files(temp_directory, sample_excel_file):
    """测试文件扫描功能"""
    # 修改导入服务的配置以使用临时目录
    import_service = ImportService()
    
    # 手动设置路径
    from app.core.config import settings
    original_path = settings.SHARED_INBOX_DIR
    settings.SHARED_INBOX_DIR = str(temp_directory)
    
    try:
        files = await import_service.scan_files()
        assert len(files) == 1
        assert files[0].name == 'test_orders.xlsx'
    finally:
        settings.SHARED_INBOX_DIR = original_path


@pytest.mark.asyncio
async def test_import_service_check_processed(test_db, sample_excel_file):
    """测试文件处理状态检查"""
    db = test_db
        import_service = ImportService()
        
        # 文件未处理时应返回None
        result = await import_service.check_file_processed(db, sample_excel_file)
        assert result is None
        
        # 添加处理记录
        file_hash = calculate_file_sha1(sample_excel_file)
        processed_file = ProcessedFile(
            file_name=sample_excel_file.name,
            file_hash=file_hash,
            rows_total=3,
            rows_imported=3,
            rows_failed=0,
            status="success"
        )
        
        db.add(processed_file)
        await db.commit()
        
        # 再次检查应返回记录
        result = await import_service.check_file_processed(db, sample_excel_file)
        assert result is not None
        assert result.file_hash == file_hash


@pytest.mark.asyncio
async def test_import_service_create_raw_order(sample_excel_file):
    """测试创建RawOrder实例"""
    import_service = ImportService()
    file_hash = calculate_file_sha1(sample_excel_file)
    
    record = {
        'row_idx': 2,
        '原始订单编号': 'ORDER001',
        '网店名称': '测试店铺',
        '交易状态': '交易成功',
        '付款时间': datetime.now(),
        '线上宝贝名称': 'Nike 运动鞋',
        '数量': 1,
        '订单单价': 599.0,
        '收货人手机号': '138****5678',
        '收货人身份证': '1101****1234'
        'extra_field': 'extra_value'  # 测试额外字段
    }
    
    raw_order = await import_service._create_raw_order(
        record, sample_excel_file.name, file_hash
    )
    
    assert raw_order.原始订单编号 == 'ORDER001'
    assert raw_order.file_name == sample_excel_file.name
    assert raw_order.file_hash == file_hash
    
    # 检查数据
    assert raw_order.收货人手机号 == '138****5678'
    assert raw_order.收货人身份证 == '1101****1234'
    
    # 检查额外字段
    assert raw_order.extra_fields == {'extra_field': 'extra_value'}


@pytest.mark.asyncio
async def test_import_service_batch_import(test_db, sample_excel_file):
    """测试批量导入"""
    async with test_db() as db:
        import_service = ImportService()
        
        # 读取记录
        reader = ExcelReader()
        records = reader.process_excel_file(sample_excel_file)
        
        # 批量导入
        file_hash = calculate_file_sha1(sample_excel_file)
        imported, failed, errors = await import_service._batch_import_records(
            db, records, sample_excel_file.name, file_hash
        )
        
        assert imported == 3
        assert failed == 0
        assert len(errors) == 0
        
        # 验证数据库中的记录
        result = await db.execute(select(RawOrder))
        raw_orders = result.scalars().all()
        
        assert len(raw_orders) == 3
        assert raw_orders[0].原始订单编号 == 'ORDER001'
        assert raw_orders[1].原始订单编号 == 'ORDER001'
        assert raw_orders[2].原始订单编号 == 'ORDER002'


@pytest.mark.asyncio
async def test_import_service_full_import(test_db, sample_excel_file):
    """测试完整导入流程"""
    async with test_db() as db:
        import_service = ImportService()
        
        # 设置非干跑模式
        from app.core.config import settings
        original_dry_run = settings.DRY_RUN_ANALYZE_ONLY
        settings.DRY_RUN_ANALYZE_ONLY = False
        
        try:
            result = await import_service.import_file(db, sample_excel_file)
            
            assert result['status'] == 'success'
            assert result['rows_total'] == 3
            assert result['rows_imported'] == 3
            assert result['rows_failed'] == 0
            assert len(result['errors']) == 0
            
            # 验证ProcessedFile记录
            processed_result = await db.execute(select(ProcessedFile))
            processed_files = processed_result.scalars().all()
            assert len(processed_files) == 1
            
            processed_file = processed_files[0]
            assert processed_file.rows_imported == 3
            assert processed_file.status == 'success'
            
            # 验证RawOrder记录
            orders_result = await db.execute(select(RawOrder))
            orders = orders_result.scalars().all()
            assert len(orders) == 3
            
        finally:
            settings.DRY_RUN_ANALYZE_ONLY = original_dry_run


@pytest.mark.asyncio
async def test_import_service_dry_run_mode(test_db, sample_excel_file):
    """测试干跑模式"""
    async with test_db() as db:
        import_service = ImportService()
        
        # 设置干跑模式
        from app.core.config import settings
        original_dry_run = settings.DRY_RUN_ANALYZE_ONLY
        settings.DRY_RUN_ANALYZE_ONLY = True
        
        try:
            result = await import_service.import_file(db, sample_excel_file)
            
            assert result['status'] == 'skipped'
            assert 'DRY_RUN' in result['message']
            
            # 验证没有记录被导入
            orders_result = await db.execute(select(RawOrder))
            orders = orders_result.scalars().all()
            assert len(orders) == 0
            
        finally:
            settings.DRY_RUN_ANALYZE_ONLY = original_dry_run


@pytest.mark.asyncio
async def test_import_service_duplicate_prevention(test_db, sample_excel_file):
    """测试重复导入防护"""
    async with test_db() as db:
        import_service = ImportService()
        
        from app.core.config import settings
        original_dry_run = settings.DRY_RUN_ANALYZE_ONLY
        settings.DRY_RUN_ANALYZE_ONLY = False
        
        try:
            # 第一次导入
            result1 = await import_service.import_file(db, sample_excel_file)
            assert result1['status'] == 'success'
            
            # 第二次导入同一文件
            processed = await import_service.check_file_processed(db, sample_excel_file)
            assert processed is not None
            
            # 验证import_all_pending_files会跳过已处理文件
            # 修改扫描路径
            original_path = settings.SHARED_INBOX_DIR
            settings.SHARED_INBOX_DIR = str(sample_excel_file.parent)
            
            results = await import_service.import_all_pending_files(db)
            
            # 应该有一个结果显示文件已处理
            assert len(results) == 1
            assert results[0]['status'] == 'already_processed'
            
            settings.SHARED_INBOX_DIR = original_path
            
        finally:
            settings.DRY_RUN_ANALYZE_ONLY = original_dry_run


@pytest.mark.asyncio
async def test_error_handling_invalid_file(test_db, temp_directory):
    """测试无效文件的错误处理"""
    # 创建一个非Excel文件
    invalid_file = temp_directory / 'invalid.txt'
    invalid_file.write_text('This is not an Excel file')
    
    async with test_db() as db:
        import_service = ImportService()
        
        from app.core.config import settings
        original_dry_run = settings.DRY_RUN_ANALYZE_ONLY
        settings.DRY_RUN_ANALYZE_ONLY = False
        
        try:
            result = await import_service.import_file(db, invalid_file)
            
            assert result['status'] == 'error'
            assert 'error_message' in result
            
        finally:
            settings.DRY_RUN_ANALYZE_ONLY = original_dry_run


if __name__ == '__main__':
    # 运行特定测试
    pytest.main([__file__, '-v'])