#!/usr/bin/env python3
"""
公牛充电桩 API 测试

TDD 开发流程：
1. 编写测试用例定义接口行为
2. 实现 API 模块使测试通过
"""

import unittest
from unittest.mock import patch, MagicMock
import json


class TestGongniuAPI(unittest.TestCase):
    """公牛充电桩 API 测试"""

    def setUp(self):
        """测试初始化"""
        self.sample_response = {
            "resultCode": "100",
            "businessCode": "1",
            "msg": "成功",
            "data": {
                "pageNo": 1,
                "pageSize": 10,
                "pageCount": 1,
                "totalCount": 5,
                "dataList": [
                    {
                        "id": "2046838875488825345",
                        "stationId": "2046592030206775298",
                        "stationName": "Giant内部充电站",
                        "type": 1,
                        "typeName": "直流",
                        "power": 20,
                        "connectorCode": "9500020260401801",
                        "connectorName": "Giant内部充电桩（SSL-18）01",
                        "workStatus": 3,
                        "workStatusName": "占用充电中",
                        "soc": 97
                    },
                    {
                        "id": "2046839158578163713",
                        "stationId": "2046592030206775298",
                        "stationName": "Giant内部充电站",
                        "type": 1,
                        "typeName": "直流",
                        "power": 20,
                        "connectorCode": "9500020260401901",
                        "connectorName": "Giant内部充电桩（SSL-19）01",
                        "workStatus": 1,
                        "workStatusName": "空闲",
                        "soc": 0
                    },
                    {
                        "id": "2047490019695710210",
                        "stationId": "2046592030206775298",
                        "type": 2,
                        "typeName": "交流",
                        "power": 7,
                        "connectorCode": "9500030411378101",
                        "connectorName": "Giant内部充电桩（JSF-01）01",
                        "workStatus": 0,
                        "workStatusName": "离线",
                        "soc": 0
                    }
                ]
            }
        }

    def test_parse_work_status_to_state_type(self):
        """测试状态码映射"""
        from gongniu_api import GongniuAPI

        api = GongniuAPI()

        # 状态码映射测试
        self.assertEqual(api.parse_work_status(0), "offline")  # 离线
        self.assertEqual(api.parse_work_status(1), "free")     # 空闲
        self.assertEqual(api.parse_work_status(2), "occupied") # 占用（未充电）
        self.assertEqual(api.parse_work_status(3), "charging") # 充电中
        self.assertEqual(api.parse_work_status(99), "unknown") # 未知状态

    def test_parse_type_to_connector_type(self):
        """测试充电桩类型映射"""
        from gongniu_api import GongniuAPI

        api = GongniuAPI()

        self.assertEqual(api.parse_connector_type(1), "DC")  # 直流
        self.assertEqual(api.parse_connector_type(2), "AC")  # 交流
        self.assertEqual(api.parse_connector_type(3), "AC")  # 未知类型默认 AC

    def test_normalize_connector_data(self):
        """测试数据标准化 - 转换为统一格式"""
        from gongniu_api import GongniuAPI

        api = GongniuAPI()
        raw_data = self.sample_response["data"]["dataList"][0]  # DC 充电中

        normalized = api.normalize_connector(raw_data)

        # 验证标准化后的字段
        self.assertEqual(normalized["connector_id"], "9500020260401801")
        self.assertEqual(normalized["connector_name"], "Giant内部充电桩（SSL-18）01")
        self.assertEqual(normalized["type"], "DC")
        self.assertEqual(normalized["power"], 20)
        self.assertEqual(normalized["state"]["type"], "charging")
        self.assertEqual(normalized["state"]["desc"], "占用充电中")
        self.assertEqual(normalized["charging_progress"], 97)
        self.assertEqual(normalized["vendor"], "gongniu")

    def test_normalize_free_connector(self):
        """测试空闲状态数据标准化"""
        from gongniu_api import GongniuAPI

        api = GongniuAPI()
        raw_data = self.sample_response["data"]["dataList"][1]  # DC 空闲

        normalized = api.normalize_connector(raw_data)

        self.assertEqual(normalized["state"]["type"], "free")
        # 空闲状态不应有 charging_progress 字段
        self.assertNotIn("charging_progress", normalized)

    def test_filter_dc_only(self):
        """测试只过滤 DC 桩"""
        from gongniu_api import GongniuAPI

        api = GongniuAPI()
        connectors = api.parse_connectors(self.sample_response, dc_only=True)

        # 只应该返回 2 个 DC 桩
        self.assertEqual(len(connectors), 2)
        for c in connectors:
            self.assertEqual(c["type"], "DC")

    def test_filter_all_types(self):
        """测试不过滤，返回所有类型"""
        from gongniu_api import GongniuAPI

        api = GongniuAPI()
        connectors = api.parse_connectors(self.sample_response, dc_only=False)

        # 应该返回 3 个桩
        self.assertEqual(len(connectors), 3)

    @patch('requests.post')
    def test_fetch_connectors_success(self, mock_post):
        """测试 API 调用成功"""
        from gongniu_api import GongniuAPI

        # Mock 响应
        mock_response = MagicMock()
        mock_response.status_code = 200
        mock_response.json.return_value = self.sample_response
        mock_post.return_value = mock_response

        api = GongniuAPI(station_id="2046592030206775298")
        result = api.fetch_connectors()

        self.assertTrue(result["success"])
        self.assertEqual(len(result["connectors"]), 2)  # DC only
        self.assertEqual(result["vendor"], "gongniu")

    @patch('requests.post')
    def test_fetch_connectors_api_error(self, mock_post):
        """测试 API 调用失败"""
        from gongniu_api import GongniuAPI

        # Mock 错误响应
        mock_response = MagicMock()
        mock_response.status_code = 500
        mock_post.return_value = mock_response

        api = GongniuAPI(station_id="2046592030206775298")
        result = api.fetch_connectors()

        self.assertFalse(result["success"])
        self.assertIn("error", result)


class TestMultiVendorDataStorage(unittest.TestCase):
    """多厂商数据存储测试"""

    def test_connector_with_vendor_field(self):
        """测试连接器数据包含 vendor 字段"""
        connector = {
            "connector_id": "9500020260401801",
            "connector_name": "Giant内部充电桩（SSL-18）01",
            "type": "DC",
            "power": 20,
            "state": {"type": "charging", "desc": "占用充电中"},
            "charging_progress": 97,
            "vendor": "gongniu"
        }

        self.assertEqual(connector["vendor"], "gongniu")

    def test_nio_connector_has_vendor(self):
        """测试 NIO 连接器数据包含 vendor 字段"""
        connector = {
            "connector_id": "DC-16",
            "connector_name": "16号枪",
            "type": "DC",
            "power": 20,
            "state": {"type": "charging", "desc": "充电中"},
            "vendor": "nio"
        }

        self.assertEqual(connector["vendor"], "nio")

    def test_merge_multi_vendor_connectors(self):
        """测试合并多厂商数据"""
        nio_connectors = [
            {"connector_id": "DC-16", "connector_name": "16号枪", "type": "DC", "power": 20,
             "state": {"type": "charging"}, "vendor": "nio"},
            {"connector_id": "DC-17", "connector_name": "17号枪", "type": "DC", "power": 20,
             "state": {"type": "free"}, "vendor": "nio"},
        ]

        gongniu_connectors = [
            {"connector_id": "9500020260401801", "connector_name": "SSL-18", "type": "DC", "power": 20,
             "state": {"type": "charging"}, "charging_progress": 97, "vendor": "gongniu"},
            {"connector_id": "9500020260401901", "connector_name": "SSL-19", "type": "DC", "power": 20,
             "state": {"type": "free"}, "vendor": "gongniu"},
        ]

        merged = nio_connectors + gongniu_connectors

        self.assertEqual(len(merged), 4)

        # 验证可以按厂商过滤
        nio_only = [c for c in merged if c.get("vendor") == "nio"]
        gongniu_only = [c for c in merged if c.get("vendor") == "gongniu"]

        self.assertEqual(len(nio_only), 2)
        self.assertEqual(len(gongniu_only), 2)


if __name__ == "__main__":
    unittest.main()
