"""
课程模块测试
"""
import pytest
from httpx import AsyncClient
from sqlalchemy.ext.asyncio import AsyncSession

from app.models.course import Course, CourseStatus, CourseCategory
from app.services.course_service import course_service


class TestCourseAPI:
    """课程API测试类"""
    
    @pytest.mark.asyncio
    async def test_create_course_success(self, client: AsyncClient, admin_headers: dict):
        """测试成功创建课程"""
        course_data = {
            "name": "测试课程",
            "description": "这是一个测试课程",
            "category": "technology",
            "difficulty_level": 3,
            "tags": ["Python", "测试"]
        }
        
        response = await client.post(
            "/api/v1/courses",
            json=course_data,
            headers=admin_headers
        )
        
        assert response.status_code == 201
        data = response.json()
        assert data["code"] == 200
        assert data["message"] == "创建课程成功"
        assert data["data"]["name"] == course_data["name"]
        assert data["data"]["status"] == "draft"
    
    @pytest.mark.asyncio
    async def test_create_course_unauthorized(self, client: AsyncClient, user_headers: dict):
        """测试非管理员创建课程失败"""
        course_data = {
            "name": "测试课程",
            "description": "这是一个测试课程"
        }
        
        response = await client.post(
            "/api/v1/courses",
            json=course_data,
            headers=user_headers
        )
        
        assert response.status_code == 403
    
    @pytest.mark.asyncio
    async def test_get_courses_list(self, client: AsyncClient, user_headers: dict, db_session: AsyncSession):
        """测试获取课程列表"""
        # 先创建几个测试课程
        courses = [
            Course(
                name=f"测试课程{i}",
                description=f"描述{i}",
                category=CourseCategory.TECHNOLOGY if i % 2 == 0 else CourseCategory.BUSINESS,
                status=CourseStatus.PUBLISHED if i < 2 else CourseStatus.DRAFT,
                is_featured=i == 0
            )
            for i in range(3)
        ]
        
        for course in courses:
            db_session.add(course)
        await db_session.commit()
        
        # 测试获取所有课程
        response = await client.get(
            "/api/v1/courses",
            headers=user_headers
        )
        
        assert response.status_code == 200
        data = response.json()
        assert data["code"] == 200
        assert len(data["data"]["items"]) == 3
        assert data["data"]["total"] == 3
        
        # 测试筛选已发布课程
        response = await client.get(
            "/api/v1/courses?status=published",
            headers=user_headers
        )
        
        assert response.status_code == 200
        data = response.json()
        assert len(data["data"]["items"]) == 2
        
        # 测试分类筛选
        response = await client.get(
            "/api/v1/courses?category=technology",
            headers=user_headers
        )
        
        assert response.status_code == 200
        data = response.json()
        assert len(data["data"]["items"]) == 2
    
    @pytest.mark.asyncio
    async def test_get_course_detail(self, client: AsyncClient, user_headers: dict, db_session: AsyncSession):
        """测试获取课程详情"""
        # 创建测试课程
        course = Course(
            name="测试课程详情",
            description="详细描述",
            category=CourseCategory.TECHNOLOGY,
            status=CourseStatus.PUBLISHED
        )
        db_session.add(course)
        await db_session.commit()
        await db_session.refresh(course)
        
        # 获取课程详情
        response = await client.get(
            f"/api/v1/courses/{course.id}",
            headers=user_headers
        )
        
        assert response.status_code == 200
        data = response.json()
        assert data["data"]["id"] == course.id
        assert data["data"]["name"] == course.name
    
    @pytest.mark.asyncio
    async def test_get_course_not_found(self, client: AsyncClient, user_headers: dict):
        """测试获取不存在的课程"""
        response = await client.get(
            "/api/v1/courses/99999",
            headers=user_headers
        )
        
        assert response.status_code == 404
    
    @pytest.mark.asyncio
    async def test_update_course(self, client: AsyncClient, admin_headers: dict, db_session: AsyncSession):
        """测试更新课程"""
        # 创建测试课程
        course = Course(
            name="原始课程名",
            description="原始描述",
            category=CourseCategory.TECHNOLOGY,
            status=CourseStatus.DRAFT
        )
        db_session.add(course)
        await db_session.commit()
        await db_session.refresh(course)
        
        # 更新课程
        update_data = {
            "name": "更新后的课程名",
            "status": "published"
        }
        
        response = await client.put(
            f"/api/v1/courses/{course.id}",
            json=update_data,
            headers=admin_headers
        )
        
        assert response.status_code == 200
        data = response.json()
        assert data["data"]["name"] == update_data["name"]
        assert data["data"]["status"] == "published"
        assert data["data"]["published_at"] is not None
    
    @pytest.mark.asyncio
    async def test_delete_course(self, client: AsyncClient, admin_headers: dict, db_session: AsyncSession):
        """测试删除课程"""
        # 创建测试课程
        course = Course(
            name="待删除课程",
            description="这个课程将被删除",
            category=CourseCategory.GENERAL,
            status=CourseStatus.DRAFT
        )
        db_session.add(course)
        await db_session.commit()
        await db_session.refresh(course)
        
        # 删除课程
        response = await client.delete(
            f"/api/v1/courses/{course.id}",
            headers=admin_headers
        )
        
        assert response.status_code == 200
        data = response.json()
        assert data["data"] is True
        
        # 验证软删除
        deleted_course = await course_service.get_by_id(db_session, course.id)
        assert deleted_course is None  # 因为get_by_id会过滤掉软删除的记录
    
    @pytest.mark.asyncio
    async def test_delete_published_course_fail(self, client: AsyncClient, admin_headers: dict, db_session: AsyncSession):
        """测试删除已发布课程失败"""
        # 创建已发布课程
        course = Course(
            name="已发布课程",
            description="这是已发布的课程",
            category=CourseCategory.TECHNOLOGY,
            status=CourseStatus.PUBLISHED
        )
        db_session.add(course)
        await db_session.commit()
        await db_session.refresh(course)
        
        # 尝试删除
        response = await client.delete(
            f"/api/v1/courses/{course.id}",
            headers=admin_headers
        )
        
        assert response.status_code == 400


class TestKnowledgePointAPI:
    """知识点API测试类"""
    
    @pytest.mark.asyncio
    async def test_get_knowledge_points(self, client: AsyncClient, user_headers: dict, db_session: AsyncSession):
        """测试获取知识点列表"""
        # 创建测试课程
        course = Course(
            name="测试课程",
            description="包含知识点的课程",
            category=CourseCategory.TECHNOLOGY,
            status=CourseStatus.PUBLISHED
        )
        db_session.add(course)
        await db_session.commit()
        await db_session.refresh(course)
        
        # 获取知识点（应该为空）
        response = await client.get(
            f"/api/v1/courses/{course.id}/knowledge-points",
            headers=user_headers
        )
        
        assert response.status_code == 200
        data = response.json()
        assert data["data"] == []
    
    @pytest.mark.asyncio
    async def test_create_knowledge_point(self, client: AsyncClient, admin_headers: dict, db_session: AsyncSession):
        """测试创建知识点"""
        # 创建测试课程
        course = Course(
            name="测试课程",
            description="用于测试知识点",
            category=CourseCategory.TECHNOLOGY,
            status=CourseStatus.DRAFT
        )
        db_session.add(course)
        await db_session.commit()
        await db_session.refresh(course)
        
        # 创建知识点
        point_data = {
            "name": "Python基础",
            "description": "学习Python基础知识",
            "weight": 2.0,
            "estimated_hours": 10
        }
        
        response = await client.post(
            f"/api/v1/courses/{course.id}/knowledge-points",
            json=point_data,
            headers=admin_headers
        )
        
        assert response.status_code == 201
        data = response.json()
        assert data["data"]["name"] == point_data["name"]
        assert data["data"]["course_id"] == course.id
        assert data["data"]["level"] == 1
        assert data["data"]["parent_id"] is None
