<?php

namespace Tests\Unit\Services;

use Tests\TestCase;
use App\Services\KnowledgeGraphService;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class KnowledgeGraphServiceTest extends TestCase
{
    protected KnowledgeGraphService $service;

    protected function setUp(): void
    {
        parent::setUp();
        $this->service = new KnowledgeGraphService();
    }

    /** @test */
    public function it_initializes_with_correct_base_url()
    {
        // 默认URL
        $this->assertEquals('http://localhost:5011', $this->service->baseUrl);

        // 测试自定义URL
        $this->service = new KnowledgeGraphService();
        $this->service->baseUrl = 'http://knowledge-api.test';
        $this->assertEquals('http://knowledge-api.test', $this->service->baseUrl);
    }

    /** @test */
    public function it_trims_trailing_slash_from_base_url()
    {
        $this->service->baseUrl = 'http://localhost:5011/';
        $this->assertEquals('http://localhost:5011', $this->service->baseUrl);
    }

    /** @test */
    public function list_knowledge_points_returns_formatted_data()
    {
        Http::fake([
            'localhost:5011/knowledge-points/*' => Http::response([
                'data' => [
                    [
                        'id' => 'kp_1',
                        'kp_code' => 'KP1001',
                        'cn_name' => '因式分解基础',
                        'category' => '数学',
                        'phase' => '初中',
                        'grade' => 8,
                        'importance' => 5,
                    ],
                ],
            ], 200),
        ]);

        $result = $this->service->listKnowledgePoints();

        $this->assertIsArray($result);
        $this->assertCount(1, $result);
        $this->assertEquals('kp_1', $result[0]['id']);
        $this->assertEquals('KP1001', $result[0]['kp_code']);
        $this->assertEquals('因式分解基础', $result[0]['cn_name']);
        $this->assertEquals('数学', $result[0]['category']);
        $this->assertEquals('初中', $result[0]['phase']);
    }

    /** @test */
    public function list_knowledge_points_returns_fallback_data_on_error()
    {
        Http::fake([
            'localhost:5011/knowledge-points/*' => Http::response([], 500),
        ]);

        $result = $this->service->listKnowledgePoints();

        // 应该返回备用数据
        $this->assertIsArray($result);
        $this->assertGreaterThan(0, count($result));
        $this->assertArrayHasKey('id', $result[0]);
        $this->assertArrayHasKey('kp_code', $result[0]);
        $this->assertArrayHasKey('cn_name', $result[0]);
    }

    /** @test */
    public function list_knowledge_points_handles_multiple_field_names()
    {
        Http::fake([
            'localhost:5011/knowledge-points/*' => Http::response([
                'data' => [
                    [
                        'kp_id' => 'kp_1', // 使用kp_id而不是id
                        'kp_name' => '因式分解', // 使用kp_name而不是cn_name
                    ],
                ],
            ], 200),
        ]);

        $result = $this->service->listKnowledgePoints();

        $this->assertEquals('kp_1', $result[0]['id']);
        $this->assertEquals('KP_UNKNOWN', $result[0]['kp_code']);
        $this->assertEquals('因式分解', $result[0]['cn_name']);
    }

    /** @test */
    public function get_skills_by_knowledge_point_returns_formatted_data()
    {
        Http::fake([
            'localhost:5011/graph/node/*' => Http::response([
                'skills' => [
                    [
                        'skill_code' => 'SK001',
                        'skill_name' => '计算能力',
                        'weight' => 0.9,
                    ],
                ],
            ], 200),
        ]);

        $result = $this->service->getSkillsByKnowledgePoint('KP1001');

        $this->assertIsArray($result);
        $this->assertCount(1, $result);
        $this->assertEquals('SK001', $result[0]['code']);
        $this->assertEquals('计算能力', $result[0]['name']);
        $this->assertEquals(0.9, $result[0]['weight']);
    }

    /** @test */
    public function get_skills_by_knowledge_point_returns_empty_on_error()
    {
        Http::fake([
            'localhost:5011/graph/node/*' => Http::response([], 500),
        ]);

        $result = $this->service->getSkillsByKnowledgePoint('KP1001');

        $this->assertIsArray($result);
        $this->assertEmpty($result);
    }

    /** @test */
    public function list_skills_returns_formatted_data()
    {
        Http::fake([
            'localhost:5011/skills/*' => Http::response([
                'data' => [
                    [
                        'id' => 'sk_1',
                        'skill_code' => 'SK001',
                        'skill_name' => '计算能力',
                        'skill_type' => '基础技能',
                    ],
                ],
            ], 200),
        ]);

        $result = $this->service->listSkills();

        $this->assertIsArray($result);
        $this->assertCount(1, $result);
        $this->assertEquals('sk_1', $result[0]['id']);
        $this->assertEquals('SK001', $result[0]['code']);
        $this->assertEquals('计算能力', $result[0]['name']);
        $this->assertEquals('基础技能', $result[0]['category']);
    }

    /** @test */
    public function list_relations_returns_formatted_data()
    {
        Http::fake([
            'localhost:5011/graph/relations' => Http::response([
                'data' => [
                    [
                        'source' => 'R01',
                        'target' => 'R02',
                        'relation_type' => 'PREREQUISITE',
                        'relation_direction' => 'DOWNSTREAM',
                        'weight' => 0.9,
                        'description' => '前置依赖',
                    ],
                ],
            ], 200),
        ]);

        $result = $this->service->listRelations();

        $this->assertIsArray($result);
        $this->assertCount(1, $result);
        $this->assertEquals('R01', $result[0]['source_kp']);
        $this->assertEquals('R02', $result[0]['target_kp']);
        $this->assertEquals('PREREQUISITE', $result[0]['relation_type']);
        $this->assertEquals('DOWNSTREAM', $result[0]['relation_direction']);
        $this->assertEquals(0.9, $result[0]['weight']);
    }

    /** @test */
    public function export_graph_returns_api_data()
    {
        $graphData = [
            'nodes' => [
                ['id' => 'R01', 'label' => '有理数'],
            ],
            'edges' => [
                ['source' => 'R01', 'target' => 'R02'],
            ],
        ];

        Http::fake([
            'localhost:5011/graph/export' => Http::response($graphData, 200),
        ]);

        $result = $this->service->exportGraph();

        $this->assertIsArray($result);
        $this->assertArrayHasKey('nodes', $result);
        $this->assertArrayHasKey('edges', $result);
        $this->assertCount(1, $result['nodes']);
        $this->assertCount(1, $result['edges']);
    }

    /** @test */
    public function export_graph_returns_empty_on_error()
    {
        Http::fake([
            'localhost:5011/graph/export' => Http::response([], 500),
        ]);

        $result = $this->service->exportGraph();

        $this->assertIsArray($result);
        $this->assertArrayHasKey('nodes', $result);
        $this->assertArrayHasKey('edges', $result);
        $this->assertEmpty($result['nodes']);
        $this->assertEmpty($result['edges']);
    }

    /** @test */
    public function check_health_returns_true_when_healthy()
    {
        Http::fake([
            'localhost:5011/health' => Http::response([], 200),
        ]);

        $result = $this->service->checkHealth();

        $this->assertTrue($result);
    }

    /** @test */
    public function check_health_returns_false_when_unhealthy()
    {
        Http::fake([
            'localhost:5011/health' => Http::response([], 500),
        ]);

        $result = $this->service->checkHealth();

        $this->assertFalse($result);
    }

    /** @test */
    public function check_health_returns_false_on_exception()
    {
        Http::fake([
            'localhost:5011/health' => Http::throw(new \Exception('Connection failed')),
        ]);

        $result = $this->service->checkHealth();

        $this->assertFalse($result);
    }

    /** @test */
    public function get_mastery_color_returns_correct_colors()
    {
        $this->assertEquals('#10b981', $this->service->getMasteryColor(0.9));
        $this->assertEquals('#3b82f6', $this->service->getMasteryColor(0.7));
        $this->assertEquals('#f59e0b', $this->service->getMasteryColor(0.5));
        $this->assertEquals('#f97316', $this->service->getMasteryColor(0.3));
        $this->assertEquals('#ef4444', $this->service->getMasteryColor(0.1));
    }

    /** @test */
    public function get_mastery_color_handles_edge_cases()
    {
        $this->assertEquals('#10b981', $this->service->getMasteryColor(1.0));
        $this->assertEquals('#ef4444', $this->service->getMasteryColor(0.0));
        $this->assertEquals('#ef4444', $this->service->getMasteryColor(-0.1));
    }

    /** @test */
    public function get_student_mastery_returns_api_data()
    {
        Http::fake([
            'localhost:5010/api/mastery/*' => Http::response([
                'masteries' => [
                    ['kp_code' => 'R01', 'mastery_level' => 0.85, 'confidence_level' => 0.8],
                ],
            ], 200),
        ]);

        $result = $this->service->getStudentMastery(1001);

        $this->assertIsArray($result);
        $this->assertArrayHasKey('masteries', $result);
        $this->assertCount(1, $result['masteries']);
    }

    /** @test */
    public function get_student_mastery_returns_mock_data_on_error()
    {
        Http::fake([
            'localhost:5010/api/mastery/*' => Http::response([], 500),
        ]);

        $result = $this->service->getStudentMastery(1001);

        $this->assertIsArray($result);
        $this->assertArrayHasKey('masteries', $result);
        $this->assertCount(5, $result['masteries']);
    }

    /** @test */
    public function get_student_statistics_returns_api_data()
    {
        Http::fake([
            'localhost:5010/api/mastery/*/statistics' => Http::response([
                'total_knowledge_points' => 8,
                'average_mastery' => 0.65,
                'high_mastery_count' => 2,
                'medium_mastery_count' => 3,
                'low_mastery_count' => 3,
            ], 200),
        ]);

        $result = $this->service->getStudentStatistics(1001);

        $this->assertIsArray($result);
        $this->assertEquals(8, $result['total_knowledge_points']);
        $this->assertEquals(0.65, $result['average_mastery']);
        $this->assertEquals(2, $result['high_mastery_count']);
    }

    /** @test */
    public function get_student_statistics_returns_mock_data_on_error()
    {
        Http::fake([
            'localhost:5010/api/mastery/*/statistics' => Http::response([], 500),
        ]);

        $result = $this->service->getStudentStatistics(1001);

        $this->assertIsArray($result);
        $this->assertEquals(5, $result['total_knowledge_points']);
        $this->assertEquals(0.594, $result['average_mastery']);
    }

    /** @test */
    public function get_student_statistics_handles_api_exception()
    {
        Http::fake([
            'localhost:5010/api/mastery/*/statistics' => Http::throw(new \Exception('API Error')),
        ]);

        $result = $this->service->getStudentStatistics(1001);

        $this->assertIsArray($result);
        $this->assertArrayHasKey('total_knowledge_points', $result);
        $this->assertArrayHasKey('average_mastery', $result);
    }

    /** @test */
    public function import_graph_calls_api_correctly()
    {
        Http::fake([
            'localhost:5011/import/graph' => Http::response([
                'success' => true,
                'imported' => 100,
            ], 200),
        ]);

        $treeData = ['nodes' => []];
        $edgesData = ['edges' => []];

        $result = $this->service->importGraph($treeData, $edgesData);

        $this->assertTrue($result);
    }

    /** @test */
    public function import_graph_handles_api_error()
    {
        Http::fake([
            'localhost:5011/import/graph' => Http::response([
                'success' => false,
                'error' => 'Invalid data',
            ], 400),
        ]);

        $treeData = ['nodes' => []];
        $edgesData = ['edges' => []];

        $result = $this->service->importGraph($treeData, $edgesData);

        $this->assertFalse($result);
    }

    /** @test */
    public function get_knowledge_point_calls_correct_endpoint()
    {
        Http::fake([
            'localhost:5011/knowledge-points/*' => Http::response([
                'id' => 'KP1001',
                'name' => '因式分解基础',
            ], 200),
        ]);

        $result = $this->service->getKnowledgePoint('KP1001');

        $this->assertIsArray($result);
        $this->assertEquals('KP1001', $result['id']);
    }

    /** @test */
    public function create_knowledge_point_calls_correct_endpoint()
    {
        Http::fake([
            'localhost:5011/knowledge-points/*' => Http::response([], 201),
        ]);

        $data = [
            'kp_code' => 'KP1001',
            'cn_name' => '因式分解基础',
            'category' => '数学',
        ];

        $result = $this->service->createKnowledgePoint($data);

        $this->assertTrue($result);
    }

    /** @test */
    public function update_knowledge_point_calls_correct_endpoint()
    {
        Http::fake([
            'localhost:5011/knowledge-points/*' => Http::response([], 200),
        ]);

        $data = [
            'cn_name' => '因式分解进阶',
        ];

        $result = $this->service->updateKnowledgePoint('KP1001', $data);

        $this->assertTrue($result);
    }

    /** @test */
    public function delete_knowledge_point_calls_correct_endpoint()
    {
        Http::fake([
            'localhost:5011/knowledge-points/*' => Http::response([], 204),
        ]);

        $result = $this->service->deleteKnowledgePoint('KP1001');

        $this->assertTrue($result);
    }
}
