import pytest
from httpx import AsyncClient


@pytest.mark.asyncio
@pytest.mark.integration
async def test_get_projects_all_users_success(
    client: AsyncClient, admin_token: str, db_session
):
    """测试所有用户获取项目列表成功"""
    # 创建测试项目
    from src.models.project import Project
    from datetime import date

    project = Project(
        project_no="PRJ001",
        name="测试项目",
        engineering_type="基建",
        contract_amount=100.0,
        signing_date=date(2026, 1, 1),
        created_by=1,
    )
    db_session.add(project)
    await db_session.commit()

    response = await client.get(
        "/api/v1/projects",
        headers={"Authorization": f"Bearer {admin_token}"},
    )

    assert response.status_code == 200
    data = response.json()
    assert data["success"] is True
    assert "items" in data["data"]
    assert "total" in data["data"]


@pytest.mark.asyncio
@pytest.mark.integration
async def test_get_projects_with_pagination(
    client: AsyncClient, admin_token: str, db_session
):
    """测试项目列表分页"""
    from src.models.project import Project
    from datetime import date

    # 创建5个测试项目
    for i in range(5):
        project = Project(
            project_no=f"PRJ{i:03d}",
            name=f"测试项目{i}",
            engineering_type="基建",
            contract_amount=100.0,
            signing_date=date(2026, 1, 1),
            created_by=1,
        )
        db_session.add(project)
    await db_session.commit()

    response = await client.get(
        "/api/v1/projects?page=1&page_size=3",
        headers={"Authorization": f"Bearer {admin_token}"},
    )

    assert response.status_code == 200
    data = response.json()
    assert data["success"] is True
    assert data["data"]["page"] == 1
    assert data["data"]["page_size"] == 3
    assert len(data["data"]["items"]) == 3


@pytest.mark.asyncio
@pytest.mark.integration
async def test_get_projects_with_filters(
    client: AsyncClient, admin_token: str, db_session
):
    """测试项目列表组合筛选"""
    from src.models.project import Project
    from datetime import date

    # 创建不同类型的项目
    project1 = Project(
        project_no="PRJ001",
        name="基建项目",
        engineering_type="基建",
        contract_amount=100.0,
        signing_date=date(2026, 1, 1),
        created_by=1,
    )
    project2 = Project(
        project_no="PRJ002",
        name="业扩项目",
        engineering_type="业扩",
        contract_amount=200.0,
        signing_date=date(2026, 2, 1),
        created_by=1,
    )
    db_session.add(project1)
    db_session.add(project2)
    await db_session.commit()

    # 筛选：工程类别=基建 AND 签订日期>=2026-01-01
    response = await client.get(
        "/api/v1/projects?engineering_type=基建&signing_date_start=2026-01-01",
        headers={"Authorization": f"Bearer {admin_token}"},
    )

    assert response.status_code == 200
    data = response.json()
    assert data["success"] is True
    assert len(data["data"]["items"]) == 1
    assert data["data"]["items"][0]["engineering_type"] == "基建"


@pytest.mark.asyncio
@pytest.mark.integration
async def test_get_projects_sort_by_contract_amount(
    client: AsyncClient, admin_token: str, db_session
):
    """测试按合同金额排序"""
    from src.models.project import Project
    from datetime import date

    # 创建不同金额的项目
    project1 = Project(
        project_no="PRJ001",
        name="项目1",
        engineering_type="基建",
        contract_amount=100.0,
        signing_date=date(2026, 1, 1),
        created_by=1,
    )
    project2 = Project(
        project_no="PRJ002",
        name="项目2",
        engineering_type="基建",
        contract_amount=200.0,
        signing_date=date(2026, 1, 1),
        created_by=1,
    )
    db_session.add(project1)
    db_session.add(project2)
    await db_session.commit()

    response = await client.get(
        "/api/v1/projects?sort_by=contract_amount&sort_order=desc",
        headers={"Authorization": f"Bearer {admin_token}"},
    )

    assert response.status_code == 200
    data = response.json()
    assert data["success"] is True
    assert data["data"]["items"][0]["contract_amount"] == 200.0
    assert data["data"]["items"][1]["contract_amount"] == 100.0


@pytest.mark.asyncio
@pytest.mark.integration
async def test_create_project_admin_success(
    client: AsyncClient, admin_token: str, admin_user
):
    """测试管理员创建项目成功"""
    response = await client.post(
        "/api/v1/projects",
        headers={"Authorization": f"Bearer {admin_token}"},
        json={
            "project_no": "PRJ001",
            "name": "新项目",
            "engineering_type": "基建",
            "contract_amount": 100.0,
            "signing_date": "2026-01-01",
        },
    )

    assert response.status_code == 200
    data = response.json()
    assert data["success"] is True
    assert data["message"] == "项目创建成功"
    assert data["data"]["project_no"] == "PRJ001"


@pytest.mark.asyncio
@pytest.mark.integration
async def test_create_project_market_success(
    client: AsyncClient, market_token: str, market_user
):
    """测试市场部用户创建项目成功"""
    response = await client.post(
        "/api/v1/projects",
        headers={"Authorization": f"Bearer {market_token}"},
        json={
            "project_no": "PRJ002",
            "name": "市场部项目",
            "engineering_type": "业扩",
            "contract_amount": 200.0,
            "signing_date": "2026-01-01",
        },
    )

    assert response.status_code == 200
    data = response.json()
    assert data["success"] is True


@pytest.mark.asyncio
@pytest.mark.integration
async def test_create_project_other_forbidden(
    client: AsyncClient, other_token: str, other_user
):
    """测试其他部门用户创建项目被禁止"""
    response = await client.post(
        "/api/v1/projects",
        headers={"Authorization": f"Bearer {other_token}"},
        json={
            "project_no": "PRJ003",
            "name": "其他部门项目",
            "engineering_type": "基建",
            "contract_amount": 100.0,
        },
    )

    assert response.status_code == 403
    data = response.json()
    assert data["success"] is False
    assert data["error_code"] == "3001"


@pytest.mark.asyncio
@pytest.mark.integration
async def test_create_project_duplicate_project_no(
    client: AsyncClient, admin_token: str, db_session, admin_user
):
    """测试创建重复项目编号"""
    from src.models.project import Project
    from datetime import date

    project = Project(
        project_no="PRJ001",
        name="已存在项目",
        engineering_type="基建",
        contract_amount=100.0,
        signing_date=date(2026, 1, 1),
        created_by=admin_user.id,
    )
    db_session.add(project)
    await db_session.commit()

    response = await client.post(
        "/api/v1/projects",
        headers={"Authorization": f"Bearer {admin_token}"},
        json={
            "project_no": "PRJ001",
            "name": "新项目",
            "engineering_type": "基建",
            "contract_amount": 100.0,
        },
    )

    assert response.status_code == 409
    data = response.json()
    assert data["success"] is False
    assert data["error_code"] == "2002"


@pytest.mark.asyncio
@pytest.mark.integration
async def test_create_project_missing_required_fields(
    client: AsyncClient, admin_token: str
):
    """测试创建项目时缺少必填字段"""
    response = await client.post(
        "/api/v1/projects",
        headers={"Authorization": f"Bearer {admin_token}"},
        json={
            "project_no": "PRJ001",
            # 缺少 name
            "engineering_type": "基建",
            "contract_amount": 100.0,
        },
    )

    assert response.status_code == 400
    data = response.json()
    assert data["success"] is False
    assert data["error_code"] == "1001"


@pytest.mark.asyncio
@pytest.mark.integration
async def test_update_project_admin_success(
    client: AsyncClient, admin_token: str, db_session, admin_user
):
    """测试管理员更新项目成功"""
    from src.models.project import Project
    from datetime import date

    project = Project(
        project_no="PRJ001",
        name="原项目名称",
        engineering_type="基建",
        contract_amount=100.0,
        signing_date=date(2026, 1, 1),
        created_by=admin_user.id,
    )
    db_session.add(project)
    await db_session.commit()
    await db_session.refresh(project)

    response = await client.put(
        f"/api/v1/projects/{project.id}",
        headers={"Authorization": f"Bearer {admin_token}"},
        json={"name": "更新后的项目名称", "contract_amount": 200.0},
    )

    assert response.status_code == 200
    data = response.json()
    assert data["success"] is True
    assert data["data"]["name"] == "更新后的项目名称"


@pytest.mark.asyncio
@pytest.mark.integration
async def test_update_project_market_own_project(
    client: AsyncClient, market_token: str, db_session, market_user
):
    """测试市场部用户更新自己的项目"""
    from src.models.project import Project
    from datetime import date

    project = Project(
        project_no="PRJ001",
        name="市场部项目",
        engineering_type="业扩",
        contract_amount=100.0,
        signing_date=date(2026, 1, 1),
        created_by=market_user.id,
    )
    db_session.add(project)
    await db_session.commit()
    await db_session.refresh(project)

    response = await client.put(
        f"/api/v1/projects/{project.id}",
        headers={"Authorization": f"Bearer {market_token}"},
        json={"name": "更新后的项目名称"},
    )

    assert response.status_code == 200
    data = response.json()
    assert data["success"] is True


@pytest.mark.asyncio
@pytest.mark.integration
async def test_update_project_market_other_project(
    client: AsyncClient, market_token: str, db_session, admin_user
):
    """测试市场部用户更新其他人的项目被禁止"""
    from src.models.project import Project
    from datetime import date

    project = Project(
        project_no="PRJ001",
        name="管理员项目",
        engineering_type="基建",
        contract_amount=100.0,
        signing_date=date(2026, 1, 1),
        created_by=admin_user.id,
    )
    db_session.add(project)
    await db_session.commit()
    await db_session.refresh(project)

    response = await client.put(
        f"/api/v1/projects/{project.id}",
        headers={"Authorization": f"Bearer {market_token}"},
        json={"name": "更新后的项目名称"},
    )

    assert response.status_code == 403
    data = response.json()
    assert data["success"] is False


@pytest.mark.asyncio
@pytest.mark.integration
async def test_update_project_not_found(
    client: AsyncClient, admin_token: str
):
    """测试更新不存在的项目"""
    response = await client.put(
        "/api/v1/projects/99999",
        headers={"Authorization": f"Bearer {admin_token}"},
        json={"name": "更新后的项目名称"},
    )

    assert response.status_code == 404
    data = response.json()
    assert data["success"] is False
    assert data["error_code"] == "2001"


@pytest.mark.asyncio
@pytest.mark.integration
async def test_delete_project_admin_success(
    client: AsyncClient, admin_token: str, db_session, admin_user
):
    """测试管理员删除项目成功"""
    from src.models.project import Project
    from datetime import date

    project = Project(
        project_no="PRJ001",
        name="待删除项目",
        engineering_type="基建",
        contract_amount=100.0,
        signing_date=date(2026, 1, 1),
        created_by=admin_user.id,
    )
    db_session.add(project)
    await db_session.commit()
    await db_session.refresh(project)

    response = await client.delete(
        f"/api/v1/projects/{project.id}",
        headers={"Authorization": f"Bearer {admin_token}"},
    )

    assert response.status_code == 200
    data = response.json()
    assert data["success"] is True
    assert data["message"] == "项目删除成功"


@pytest.mark.asyncio
@pytest.mark.integration
async def test_delete_project_market_own_project(
    client: AsyncClient, market_token: str, db_session, market_user
):
    """测试市场部用户删除自己的项目成功"""
    from src.models.project import Project
    from datetime import date

    project = Project(
        project_no="PRJ001",
        name="市场部项目",
        engineering_type="业扩",
        contract_amount=100.0,
        signing_date=date(2026, 1, 1),
        created_by=market_user.id,
    )
    db_session.add(project)
    await db_session.commit()
    await db_session.refresh(project)

    response = await client.delete(
        f"/api/v1/projects/{project.id}",
        headers={"Authorization": f"Bearer {market_token}"},
    )

    assert response.status_code == 200
    data = response.json()
    assert data["success"] is True


@pytest.mark.asyncio
@pytest.mark.integration
async def test_delete_project_market_other_project_forbidden(
    client: AsyncClient, market_token: str, db_session, admin_user
):
    """测试市场部用户删除其他人的项目被禁止"""
    from src.models.project import Project
    from datetime import date

    project = Project(
        project_no="PRJ001",
        name="管理员项目",
        engineering_type="基建",
        contract_amount=100.0,
        signing_date=date(2026, 1, 1),
        created_by=admin_user.id,
    )
    db_session.add(project)
    await db_session.commit()
    await db_session.refresh(project)

    response = await client.delete(
        f"/api/v1/projects/{project.id}",
        headers={"Authorization": f"Bearer {market_token}"},
    )

    assert response.status_code == 403
    data = response.json()
    assert data["success"] is False


@pytest.mark.asyncio
@pytest.mark.integration
async def test_delete_project_not_found(
    client: AsyncClient, admin_token: str
):
    """测试删除不存在的项目"""
    response = await client.delete(
        "/api/v1/projects/99999",
        headers={"Authorization": f"Bearer {admin_token}"},
    )

    assert response.status_code == 404
    data = response.json()
    assert data["success"] is False
    assert data["error_code"] == "2001"


@pytest.mark.asyncio
@pytest.mark.integration
async def test_get_project_detail_success(
    client: AsyncClient, admin_token: str, db_session, admin_user
):
    """测试获取项目详情成功"""
    from src.models.project import Project
    from datetime import date

    project = Project(
        project_no="PRJ001",
        name="测试项目",
        engineering_type="基建",
        contract_amount=100.0,
        signing_date=date(2026, 1, 1),
        created_by=admin_user.id,
    )
    db_session.add(project)
    await db_session.commit()
    await db_session.refresh(project)

    response = await client.get(
        f"/api/v1/projects/{project.id}",
        headers={"Authorization": f"Bearer {admin_token}"},
    )

    assert response.status_code == 200
    data = response.json()
    assert data["success"] is True
    assert data["data"]["project_no"] == "PRJ001"
