"""
工艺参数 API 测试
"""
from django.test import TestCase
from django.contrib.auth import get_user_model
from rest_framework.test import APIClient
from rest_framework import status
from stateflow.models import StateParameter, State

User = get_user_model()


class StateParameterAPITestCase(TestCase):
    """工艺参数 API 测试"""
    
    def setUp(self):
        """设置测试数据"""
        # 创建用户
        self.user = User.objects.create_user(username='testuser', password='testpass123')
        
        # 创建多个工艺参数
        self.param1 = StateParameter.objects.create(
            key='color',
            value='红色',
            description='颜色参数',
            is_required=True,
            is_image_path=False
        )
        self.param2 = StateParameter.objects.create(
            key='size',
            value='大号',
            description='尺寸参数',
            is_required=False,
            is_image_path=False
        )
        self.param3 = StateParameter.objects.create(
            key='logo_image',
            value='/images/logo.png',
            description='Logo图片',
            is_required=True,
            is_image_path=True
        )
        self.param4 = StateParameter.objects.create(
            key='material',
            value='纯棉',
            description='材料参数',
            is_required=False,
            is_image_path=False
        )
        
        # 创建状态并关联参数
        self.state1 = State.objects.create(
            name='设计状态',
            description='设计阶段'
        )
        self.state1.parameters.add(self.param1, self.param3)
        
        self.state2 = State.objects.create(
            name='生产状态',
            description='生产阶段'
        )
        self.state2.parameters.add(self.param2, self.param4)
        
        # 配置 API 客户端
        self.client = APIClient()
        self.client.force_authenticate(user=self.user)
    
    def test_list_parameters(self):
        """测试获取工艺参数列表"""
        response = self.client.get('/api/v1/parameters/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['count'], 4)
        
        # 验证返回的数据结构
        for item in response.data['results']:
            self.assertIn('id', item)
            self.assertIn('key', item)
            self.assertIn('value', item)
            self.assertIn('description', item)
            self.assertIn('is_required', item)
            self.assertIn('is_image_path', item)
            self.assertIn('attachment', item)
            self.assertIn('attachment_url', item)
    
    def test_retrieve_parameter(self):
        """测试获取单个工艺参数详情"""
        response = self.client.get(f'/api/v1/parameters/{self.param1.id}/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['key'], 'color')
        self.assertEqual(response.data['value'], '红色')
        self.assertEqual(response.data['description'], '颜色参数')
        self.assertEqual(response.data['is_required'], True)
        self.assertEqual(response.data['is_image_path'], False)
    
    def test_create_parameter(self):
        """测试创建工艺参数"""
        data = {
            'key': 'weight',
            'value': '500g',
            'description': '重量参数',
            'is_required': False,
            'is_image_path': False
        }
        response = self.client.post('/api/v1/parameters/', data)
        
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(response.data['key'], 'weight')
        self.assertEqual(response.data['value'], '500g')
        self.assertEqual(response.data['description'], '重量参数')
        
        # 验证数据库中是否创建成功
        self.assertTrue(StateParameter.objects.filter(key='weight').exists())
    
    def test_create_parameter_duplicate_key(self):
        """测试创建重复 key 的参数（应该失败）"""
        data = {
            'key': 'color',  # 已存在
            'value': '蓝色',
            'description': '另一个颜色参数',
            'is_required': False,
            'is_image_path': False
        }
        response = self.client.post('/api/v1/parameters/', data)
        
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertIn('key', response.data)
    
    def test_update_parameter_full(self):
        """测试完整更新工艺参数 (PUT)"""
        data = {
            'key': 'color_updated',
            'value': '蓝色',
            'description': '更新后的颜色参数',
            'is_required': False,
            'is_image_path': False
        }
        response = self.client.put(f'/api/v1/parameters/{self.param1.id}/', data)
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['key'], 'color_updated')
        self.assertEqual(response.data['value'], '蓝色')
        self.assertEqual(response.data['is_required'], False)
        
        # 验证数据库中的更新
        self.param1.refresh_from_db()
        self.assertEqual(self.param1.key, 'color_updated')
        self.assertEqual(self.param1.value, '蓝色')
    
    def test_update_parameter_partial(self):
        """测试部分更新工艺参数 (PATCH)"""
        data = {
            'value': '绿色',
            'description': '修改后的描述'
        }
        response = self.client.patch(f'/api/v1/parameters/{self.param1.id}/', data)
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['key'], 'color')  # key 未改变
        self.assertEqual(response.data['value'], '绿色')  # value 已改变
        self.assertEqual(response.data['description'], '修改后的描述')
        
        # 验证数据库中的更新
        self.param1.refresh_from_db()
        self.assertEqual(self.param1.key, 'color')
        self.assertEqual(self.param1.value, '绿色')
    
    def test_delete_parameter_not_allowed(self):
        """测试删除工艺参数（应该被禁止）"""
        response = self.client.delete(f'/api/v1/parameters/{self.param1.id}/')
        
        self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)
        self.assertIn('detail', response.data)
        
        # 验证数据库中参数仍然存在
        self.assertTrue(StateParameter.objects.filter(id=self.param1.id).exists())
    
    def test_search_parameters(self):
        """测试搜索工艺参数"""
        response = self.client.get('/api/v1/parameters/?search=颜色')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['count'], 1)
        self.assertEqual(response.data['results'][0]['key'], 'color')
    
    def test_search_parameters_by_key(self):
        """测试按 key 搜索工艺参数"""
        response = self.client.get('/api/v1/parameters/?search=size')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['count'], 1)
        self.assertEqual(response.data['results'][0]['key'], 'size')
    
    def test_filter_required_parameters(self):
        """测试筛选必填参数"""
        response = self.client.get('/api/v1/parameters/?is_required=true')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['count'], 2)  # color 和 logo_image
        for item in response.data['results']:
            self.assertTrue(item['is_required'])
    
    def test_filter_optional_parameters(self):
        """测试筛选可选参数"""
        response = self.client.get('/api/v1/parameters/?is_required=false')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['count'], 2)  # size 和 material
        for item in response.data['results']:
            self.assertFalse(item['is_required'])
    
    def test_filter_image_path_parameters(self):
        """测试筛选图片路径参数"""
        response = self.client.get('/api/v1/parameters/?is_image_path=true')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['count'], 1)
        self.assertEqual(response.data['results'][0]['key'], 'logo_image')
        self.assertTrue(response.data['results'][0]['is_image_path'])
    
    def test_get_required_parameters_action(self):
        """测试获取所有必填参数的自定义 action"""
        response = self.client.get('/api/v1/parameters/required/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data), 2)
        keys = [item['key'] for item in response.data]
        self.assertIn('color', keys)
        self.assertIn('logo_image', keys)
    
    def test_get_optional_parameters_action(self):
        """测试获取所有可选参数的自定义 action"""
        response = self.client.get('/api/v1/parameters/optional/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data), 2)
        keys = [item['key'] for item in response.data]
        self.assertIn('size', keys)
        self.assertIn('material', keys)
    
    def test_get_parameter_states(self):
        """测试获取使用该参数的所有状态"""
        response = self.client.get(f'/api/v1/parameters/{self.param1.id}/states/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['parameter_id'], self.param1.id)
        self.assertEqual(response.data['parameter_key'], 'color')
        self.assertEqual(response.data['count'], 1)
        self.assertEqual(len(response.data['states']), 1)
        self.assertEqual(response.data['states'][0]['name'], '设计状态')
    
    def test_get_parameter_states_multiple(self):
        """测试获取被多个状态使用的参数"""
        # 让 param2 也被 state1 使用
        self.state1.parameters.add(self.param2)
        
        response = self.client.get(f'/api/v1/parameters/{self.param2.id}/states/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['count'], 2)  # 被两个状态使用
        state_names = [state['name'] for state in response.data['states']]
        self.assertIn('设计状态', state_names)
        self.assertIn('生产状态', state_names)
    
    def test_unauthorized_access(self):
        """测试未认证访问"""
        self.client.force_authenticate(user=None)
        response = self.client.get('/api/v1/parameters/')
        
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
    
    def test_create_parameter_minimal(self):
        """测试创建最小参数（只有必需字段）"""
        data = {
            'key': 'simple_param'
        }
        response = self.client.post('/api/v1/parameters/', data)
        
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(response.data['key'], 'simple_param')
        self.assertIsNone(response.data['value'])
        self.assertEqual(response.data['description'], '')
        self.assertFalse(response.data['is_required'])
        self.assertFalse(response.data['is_image_path'])
