"""
测试 BusinessObject 的完整 API 端点
包括 reset, timeline, add_parameters_to_log, get_log_parameters 等
"""
from django.test import TestCase
from rest_framework.test import APIClient
from rest_framework import status
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from stateflow import models, services

User = get_user_model()


class BusinessObjectAPITestCase(TestCase):
    """测试 BusinessObject 的所有 API 端点"""
    
    def setUp(self):
        self.client = APIClient()
        self.user = User.objects.create_user(username='testuser', password='testpass')
        self.client.force_authenticate(user=self.user)
        
        # 创建状态
        self.state1 = models.State.objects.create(name='状态1', description='第一个状态')
        self.state2 = models.State.objects.create(name='状态2', description='第二个状态')
        self.state3 = models.State.objects.create(name='状态3', description='第三个状态')
        
        # 为状态添加参数
        self.param1 = models.StateParameter.objects.create(
            key='temperature', 
            value='', 
            is_required=True,
            description='温度'
        )
        self.param2 = models.StateParameter.objects.create(
            key='humidity', 
            value='', 
            is_required=False,
            description='湿度'
        )
        self.state1.parameters.add(self.param1, self.param2)
        
        # 创建流程
        self.process = models.Process.objects.create(name='测试流程')
        models.ProcessNode.objects.create(process=self.process, state=self.state1, order=0)
        models.ProcessNode.objects.create(process=self.process, state=self.state2, order=1)
        models.ProcessNode.objects.create(process=self.process, state=self.state3, order=2)
        
        self.process_content_type = ContentType.objects.get_for_model(models.Process)
        
        # 创建业务对象
        self.business_object = models.BusinessObject.objects.create(
            name='测试业务对象',
            process=self.process,
            content_type=self.process_content_type,
            object_id=self.process.id,
        )
    
    def test_reset_api(self):
        """测试重置进度 API"""
        # 先推进两次
        self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {'parameters': {'temperature': '25.5'}},
            format='json'
        )
        self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/')
        
        # 验证已有进度
        self.business_object.refresh_from_db()
        self.assertIsNotNone(services.get_business_object_current_state(self.business_object))
        self.assertEqual(self.business_object.state_logs.count(), 2)
        
        # 重置进度
        response = self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/reset/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertTrue(response.data['success'])
        self.assertIn('重置', response.data['message'])
        
        # 验证进度已重置（current_state 返回第一个待执行的节点）
        self.business_object.refresh_from_db()
        current_state = services.get_business_object_current_state(self.business_object)
        self.assertEqual(current_state.name, self.state1.name)
        self.assertEqual(self.business_object.state_logs.filter(is_cancelled=False).count(), 0)
    
    def test_reset_api_not_started(self):
        """测试重置未开始的业务对象"""
        # 未开始也可以重置（不会报错）
        response = self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/reset/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertTrue(response.data['success'])
    
    def test_timeline_api(self):
        """测试状态时间线 API"""
        # 未开始时的时间线
        response = self.client.get(f'/api/v1/stateflow/business-objects/{self.business_object.id}/timeline/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data), 3)
        
        # 验证所有状态都是待执行
        for item in response.data:
            self.assertEqual(item['status'], 'not_started')
            self.assertIsNone(item['completed_at'])
            self.assertIsNone(item['completed_by'])
            self.assertFalse(item['is_cancelled'])
        
        # 推进第一个状态
        self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {'parameters': {'temperature': '25.5'}},
            format='json'
        )
        
        # 再次获取时间线
        response = self.client.get(f'/api/v1/stateflow/business-objects/{self.business_object.id}/timeline/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data), 3)
        
        # 第一个状态应该是已完成
        self.assertEqual(response.data[0]['status'], 'completed')
        self.assertIsNotNone(response.data[0]['completed_at'])
        self.assertEqual(response.data[0]['completed_by'], 'testuser')
        self.assertFalse(response.data[0]['is_cancelled'])
        
        # 第二和第三个状态都是未开始
        self.assertEqual(response.data[1]['status'], 'not_started')
        self.assertEqual(response.data[2]['status'], 'not_started')
    
    def test_timeline_api_with_step_back(self):
        """测试时间线 API 包含回退后的已撤销状态"""
        # 推进两次
        self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {'parameters': {'temperature': '25.5'}},
            format='json'
        )
        self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/')
        
        # 回退一次
        self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/step_back/')
        
        # 获取时间线
        response = self.client.get(f'/api/v1/stateflow/business-objects/{self.business_object.id}/timeline/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        
        # 第一个状态：已完成且未撤销
        self.assertEqual(response.data[0]['status'], 'completed')
        self.assertFalse(response.data[0]['is_cancelled'])
        
        # 第二个状态：已撤销
        self.assertEqual(response.data[1]['status'], 'cancelled')
        self.assertTrue(response.data[1]['is_cancelled'])
        self.assertIsNotNone(response.data[1]['cancelled_at'])
        
        # 第三个状态：待执行
        self.assertEqual(response.data[2]['status'], 'not_started')
    
    def test_add_parameters_to_log_api(self):
        """测试为状态流转记录补充参数 API"""
        # 先推进一次
        response = self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {'parameters': {'temperature': '25.5'}},
            format='json'
        )
        
        state_log_id = response.data['state_log']['id']
        
        # 补充参数
        response = self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/{state_log_id}/add-parameters/',
            {
                'parameters': {
                    'humidity': '60%',
                    'operator': '张三'
                },
                'remark': '补充测量数据'
            },
            format='json'
        )
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertTrue(response.data['success'])
        self.assertIn('parameter_record', response.data)
        
        # 验证参数记录
        param_record = response.data['parameter_record']
        self.assertEqual(param_record['parameters']['humidity'], '60%')
        self.assertEqual(param_record['parameters']['operator'], '张三')
        self.assertEqual(param_record['remark'], '补充测量数据')
    
    def test_add_parameters_to_log_api_empty_parameters(self):
        """测试补充空参数应该失败"""
        # 先推进一次
        response = self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {'parameters': {'temperature': '25.5'}},
            format='json'
        )
        
        state_log_id = response.data['state_log']['id']
        
        # 尝试补充空参数
        response = self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/{state_log_id}/add-parameters/',
            {
                'parameters': {},
                'remark': '空参数测试'
            },
            format='json'
        )
        
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertFalse(response.data['success'])
        self.assertIn('不能为空', response.data['message'])
    
    def test_add_parameters_to_log_api_nonexistent_log(self):
        """测试为不存在的记录补充参数应该失败"""
        response = self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/99999/add-parameters/',
            {
                'parameters': {'test': 'value'},
                'remark': '测试'
            },
            format='json'
        )
        
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
        self.assertFalse(response.data['success'])
        self.assertIn('不存在', response.data['message'])
    
    def test_get_log_parameters_api_all_records(self):
        """测试获取状态流转记录的所有参数记录 API"""
        # 推进并提供初始参数
        response = self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {'parameters': {'temperature': '25.5', 'humidity': '60%'}},
            format='json'
        )
        
        state_log_id = response.data['state_log']['id']
        
        # 补充参数两次
        self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/{state_log_id}/add-parameters/',
            {
                'parameters': {'temperature': '26.0'},
                'remark': '第一次重测'
            },
            format='json'
        )
        self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/{state_log_id}/add-parameters/',
            {
                'parameters': {'temperature': '26.5'},
                'remark': '第二次重测'
            },
            format='json'
        )
        
        # 获取所有参数记录
        response = self.client.get(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/{state_log_id}/parameters/'
        )
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['state_log_id'], state_log_id)
        self.assertFalse(response.data['is_cancelled'])
        self.assertEqual(response.data['count'], 3)
        
        # 验证汇总数据
        summary = response.data['summary']
        self.assertEqual(summary['temperature'], '26.5')  # 最新值
        self.assertEqual(summary['humidity'], '60%')
        
        # 验证记录列表
        self.assertEqual(len(response.data['records']), 3)
    def test_get_log_parameters_api_key_history(self):
        """测试获取指定参数 key 的历史记录"""
        response = self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {'parameters': {'temperature': '25.5'}},
            format='json'
        )
        state_log_id = response.data['state_log']['id']

        self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/{state_log_id}/add-parameters/',
            {
                'parameters': {'temperature': '26.0'},
                'remark': '重测'
            },
            format='json'
        )

        response = self.client.get(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/{state_log_id}/parameters/?key=temperature'
        )
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data['history']), 2)
        self.assertEqual(response.data['history'][0]['value'], '25.5')
        self.assertEqual(response.data['history'][1]['value'], '26.0')
        self.assertEqual(response.data['history'][1]['remark'], '重测')
    
    def test_get_log_parameters_api_cancelled_state_excluded(self):
        """测试已撤销状态的参数默认不可见"""
        # 推进
        response = self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {'parameters': {'temperature': '25.5'}},
            format='json'
        )
        
        state_log_id = response.data['state_log']['id']
        
        # 回退（撤销状态）
        self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/step_back/')
        
        # 默认获取参数（应该返回空）
        response = self.client.get(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/{state_log_id}/parameters/'
        )
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertTrue(response.data['is_cancelled'])
        self.assertEqual(len(response.data['summary']), 0)  # 汇总应该为空
        self.assertEqual(len(response.data['records']), 0)  # 记录列表应该为空
    
    def test_get_log_parameters_api_cancelled_state_with_include_flag(self):
        """测试 include_cancelled=true 可以查看已撤销状态的参数"""
        # 推进
        response = self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {'parameters': {'temperature': '25.5', 'humidity': '60%'}},
            format='json'
        )
        
        state_log_id = response.data['state_log']['id']
        
        # 回退（撤销状态）
        self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/step_back/')
        
        # 使用 include_cancelled=true 获取参数
        response = self.client.get(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/{state_log_id}/parameters/?include_cancelled=true'
        )
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertTrue(response.data['is_cancelled'])
        self.assertEqual(len(response.data['summary']), 2)  # 应该能看到参数
        self.assertEqual(response.data['summary']['temperature'], '25.5')
        self.assertEqual(response.data['summary']['humidity'], '60%')
    
    def test_get_log_parameters_api_key_history_cancelled_excluded(self):
        """测试已撤销状态的参数历史默认不可见"""
        # 推进
        response = self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {'parameters': {'temperature': '25.5'}},
            format='json'
        )
        
        state_log_id = response.data['state_log']['id']
        
        # 补充参数
        self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/{state_log_id}/add-parameters/',
            {'parameters': {'temperature': '26.0'}, 'remark': '重测'},
            format='json'
        )
        
        # 回退
        self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/step_back/')
        
        # 获取参数历史（默认应该为空）
        response = self.client.get(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/{state_log_id}/parameters/?key=temperature'
        )
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data['history']), 0)
        
        # 使用 include_cancelled=true 查看
        response = self.client.get(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/{state_log_id}/parameters/?key=temperature&include_cancelled=true'
        )
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data['history']), 2)
    
    def test_get_log_parameters_api_nonexistent_log(self):
        """测试获取不存在的记录的参数应该返回 404"""
        response = self.client.get(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/99999/parameters/'
        )
        
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
        self.assertFalse(response.data['success'])
    
    def test_advance_api_with_parameters(self):
        """测试推进 API 携带参数"""
        response = self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {
                'parameters': {
                    'temperature': '25.5',
                    'humidity': '60%',
                    'operator': '张三'
                }
            },
            format='json'
        )
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertTrue(response.data['success'])
        self.assertIn('state_log', response.data)
        
        # 验证参数摘要（API 返回的是 parameters_summary，不是 parameter_records）
        state_log = response.data['state_log']
        self.assertIn('parameters_summary', state_log)
        
        params = state_log['parameters_summary']
        self.assertEqual(params['temperature'], '25.5')
        self.assertEqual(params['humidity'], '60%')
        self.assertEqual(params['operator'], '张三')
    
    def test_advance_api_missing_required_parameter(self):
        """测试推进 API 缺少必填参数应该失败"""
        response = self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {
                'parameters': {
                    'humidity': '60%'  # 只提供可选参数，缺少必填的 temperature
                }
            },
            format='json'
        )
        
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertFalse(response.data['success'])
        self.assertIn('缺失必填参数', response.data['message'])
        self.assertIn('temperature', response.data['message'])
    
    def test_timeline_completed_all_states(self):
        """测试完成所有状态后的时间线"""
        # 完成所有状态
        self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {'parameters': {'temperature': '25.5'}},
            format='json'
        )
        self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/')
        self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/')
        
        # 获取时间线
        response = self.client.get(f'/api/v1/stateflow/business-objects/{self.business_object.id}/timeline/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        
        # 所有状态都应该是已完成
        for item in response.data:
            self.assertEqual(item['status'], 'completed')
            self.assertIsNotNone(item['completed_at'])
            self.assertIsNotNone(item['completed_by'])
            self.assertFalse(item['is_cancelled'])
    
    def test_get_state_logs_api_with_parameters(self):
        """测试获取状态流转记录列表（包含参数）"""
        # 未开始时应返回空列表
        response = self.client.get(f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['count'], 0)
        self.assertEqual(len(response.data['state_logs']), 0)
        
        # 推进两次
        self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {'parameters': {'temperature': '25.5', 'humidity': '60%'}},
            format='json'
        )
        self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/')
        
        # 获取记录列表（默认包含参数）
        response = self.client.get(f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['count'], 2)
        self.assertEqual(len(response.data['state_logs']), 2)
        
        # 验证第一条记录包含参数摘要
        log1 = response.data['state_logs'][0]
        self.assertIn('parameters_summary', log1)
        self.assertEqual(log1['parameters_summary']['temperature'], '25.5')
        self.assertEqual(log1['parameters_summary']['humidity'], '60%')
        self.assertEqual(log1['state_name'], '状态1')
        
        # 验证第二条记录（无参数）
        log2 = response.data['state_logs'][1]
        self.assertIn('parameters_summary', log2)
        self.assertEqual(len(log2['parameters_summary']), 0)
        self.assertEqual(log2['state_name'], '状态2')
    
    def test_get_state_logs_api_without_parameters(self):
        """测试获取状态流转记录列表（不包含参数）"""
        # 推进两次
        self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {'parameters': {'temperature': '25.5'}},
            format='json'
        )
        self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/')
        
        # 获取记录列表（不包含参数）
        response = self.client.get(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/?include_parameters=false'
        )
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['count'], 2)
        
        # 验证不包含 parameters_summary 字段
        log1 = response.data['state_logs'][0]
        self.assertNotIn('parameters_summary', log1)
        self.assertIn('state_name', log1)
        self.assertIn('completed_at', log1)
        self.assertIn('completed_by_username', log1)
    
    def test_get_state_logs_api_exclude_cancelled(self):
        """测试获取状态流转记录列表（排除已撤销记录）"""
        # 推进两次
        self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {'parameters': {'temperature': '25.5'}},
            format='json'
        )
        self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/')
        
        # 回退一次（撤销第二条记录）
        self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/step_back/')
        
        # 默认包含已撤销记录
        response = self.client.get(f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/')
        self.assertEqual(response.data['count'], 2)
        
        # 验证第二条是已撤销的
        self.assertTrue(response.data['state_logs'][1]['is_cancelled'])
        
        # 排除已撤销记录
        response = self.client.get(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/?include_cancelled=false'
        )
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['count'], 1)
        self.assertEqual(len(response.data['state_logs']), 1)
        
        # 验证只有第一条记录（未撤销）
        self.assertFalse(response.data['state_logs'][0]['is_cancelled'])
        self.assertEqual(response.data['state_logs'][0]['state_name'], '状态1')
    
    def test_get_state_logs_api_order(self):
        """测试状态流转记录按时间排序"""
        # 推进三次
        self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {'parameters': {'temperature': '25.5'}},
            format='json'
        )
        self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/')
        self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/')
        
        # 获取记录列表
        response = self.client.get(f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['count'], 3)
        
        # 验证按时间顺序排列
        logs = response.data['state_logs']
        self.assertEqual(logs[0]['state_name'], '状态1')
        self.assertEqual(logs[1]['state_name'], '状态2')
        self.assertEqual(logs[2]['state_name'], '状态3')
        
        # 验证时间递增
        from datetime import datetime
        time1 = datetime.fromisoformat(logs[0]['completed_at'])
        time2 = datetime.fromisoformat(logs[1]['completed_at'])
        time3 = datetime.fromisoformat(logs[2]['completed_at'])
        self.assertLessEqual(time1, time2)
        self.assertLessEqual(time2, time3)
    
    def test_get_state_logs_api_cancelled_state_with_parameters(self):
        """测试获取已撤销状态的工艺参数（bug修复验证）"""
        # 推进并提供参数
        self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {'parameters': {'temperature': '25.5', 'humidity': '60%'}},
            format='json'
        )
        
        # 回退（撤销该状态）
        self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/step_back/')
        
        # 使用 include_cancelled=true 和 include_parameters=true 获取状态记录
        response = self.client.get(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/state-logs/?include_cancelled=true&include_parameters=true'
        )
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        
        # 验证返回2条记录（撤销后原来的记录也在，只是标记为已撤销）
        self.assertEqual(response.data['count'], 1)
        
        # 验证记录包含工艺参数
        logs = response.data['state_logs']
        self.assertEqual(len(logs), 1)
        
        state_log = logs[0]
        self.assertTrue(state_log['is_cancelled'])
        self.assertIn('parameters_summary', state_log)
        self.assertEqual(state_log['parameters_summary']['temperature'], '25.5')
        self.assertEqual(state_log['parameters_summary']['humidity'], '60%')
    
    def test_advance_when_already_completed(self):
        """测试流程已完成时尝试推进（预期错误）"""
        # 完成所有状态
        self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/',
            {'parameters': {'temperature': '25.5'}},
            format='json'
        )
        self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/')
        self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/')
        
        # 验证已完成
        self.assertEqual(services.get_overall_status(self.business_object), 'completed')
        
        # 尝试再次推进（应该失败）
        response = self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/'
        )
        
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertFalse(response.data['success'])
        self.assertIn('流程已完成', response.data['message'])
        self.assertIn('无法继续推进', response.data['message'])
    
    def test_step_back_when_not_started(self):
        """测试未开始时尝试回退（预期错误）"""
        # 验证进行中（废除了 not_started，初始状态也是 in_progress）
        self.assertEqual(services.get_overall_status(self.business_object), 'in_progress')
        
        # 尝试回退（应该失败）
        response = self.client.post(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/step_back/'
        )
        
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertFalse(response.data['success'])
        self.assertIn('没有任何状态流转记录', response.data['message'])
    
    def test_advance_process_without_nodes(self):
        """测试流程没有节点时尝试推进（预期错误）"""
        # 创建一个没有节点的流程
        empty_process = models.Process.objects.create(name='空流程')
        empty_business_object = models.BusinessObject.objects.create(
            name='空业务对象',
            process=empty_process,
            content_type=self.process_content_type,
            object_id=empty_process.id,
        )
        
        # 尝试推进（应该失败）
        response = self.client.post(
            f'/api/v1/stateflow/business-objects/{empty_business_object.id}/advance/'
        )
        
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertFalse(response.data['success'])
        self.assertIn('流程没有任何节点', response.data['message'])
    
    def test_get_process_nodes(self):
        """测试获取业务对象所属流程的所有状态节点 API"""
        response = self.client.get(
            f'/api/v1/stateflow/business-objects/{self.business_object.id}/process-nodes/'
        )
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertIn('count', response.data)
        self.assertIn('nodes', response.data)
        
        # 验证节点数量
        self.assertEqual(response.data['count'], 3)
        self.assertEqual(len(response.data['nodes']), 3)
        
        # 验证节点内容和顺序
        nodes = response.data['nodes']
        
        self.assertEqual(nodes[0]['state_id'], self.state1.id)
        self.assertEqual(nodes[0]['state_name'], self.state1.name)
        self.assertEqual(nodes[0]['order'], 0)
        
        self.assertEqual(nodes[1]['state_id'], self.state2.id)
        self.assertEqual(nodes[1]['state_name'], self.state2.name)
        self.assertEqual(nodes[1]['order'], 1)
        
        self.assertEqual(nodes[2]['state_id'], self.state3.id)
        self.assertEqual(nodes[2]['state_name'], self.state3.name)
        self.assertEqual(nodes[2]['order'], 2)
        
        # 验证每个节点都有必要的字段
        for node in nodes:
            self.assertIn('id', node)
            self.assertIn('state_id', node)
            self.assertIn('state_name', node)
            self.assertIn('order', node)
