<?php

namespace App\Filament\Pages;

use App\Services\KnowledgeServiceApi;
use BackedEnum;
use Filament\Actions\Action;
use Filament\Pages\Page;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use UnitEnum;

class KnowledgePointDetail extends Page
{
    protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-document-text';

    protected static ?int $navigationSort = 2;

    // 不在导航菜单中显示这个页面
    protected static bool $shouldRegisterNavigation = false;

    protected string $view = 'filament.pages.knowledge-point-detail';

    public ?string $kpCode = null;

    public ?string $phaseFilter = null;

    public ?array $knowledgePoint = null;

    public array $graphData = [
        'nodes' => [],
        'edges' => [],
    ];

    protected ?KnowledgeServiceApi $knowledgeService = null;

    protected function getKnowledgeService(): KnowledgeServiceApi
    {
        if (!$this->knowledgeService) {
            $this->knowledgeService = app(KnowledgeServiceApi::class);
        }

        return $this->knowledgeService;
    }

    public function mount(Request $request): void
    {
        $this->kpCode = $request->query('kp_code');
        $this->phaseFilter = $request->query('phase');

        if (!$this->kpCode) {
            abort(404, '知识点代码不能为空');
        }

        // 加载知识点详细信息
        $this->knowledgePoint = $this->getKnowledgeService()->getFullGraphData($this->kpCode);

        if (!$this->knowledgePoint) {
            abort(404, '知识点不存在');
        }

        $this->graphData = $this->buildGraphData($this->knowledgePoint);
    }

    public function getTitle(): string
    {
        return $this->knowledgePoint['cn_name'] ?? '知识点详情';
    }

    public function getBreadcrumb(): string
    {
        return '知识点详情';
    }

    public function getKnowledgePointProperty(): ?array
    {
        return $this->knowledgePoint;
    }

    public function getSkillsProperty(): Collection
    {
        return collect($this->knowledgePoint['skills'] ?? []);
    }

    public function getParentNodesProperty(): array
    {
        return $this->knowledgePoint['parent_details'] ?? [];
    }

    public function getChildNodesProperty(): array
    {
        return $this->knowledgePoint['child_details'] ?? [];
    }

    protected function getHeaderActions(): array
    {
        return [
            Action::make('back_to_list')
                ->label('返回列表')
                ->icon('heroicon-o-arrow-left')
                ->url(route('filament.admin.resources.knowledge-points.index'))
                ->color('gray'),
        ];
    }

    public function getKnowledgeStatsProperty(): array
    {
        $skills = $this->skills;
        $parents = collect($this->parentNodes);
        $children = collect($this->childNodes);

        return [
            'skills_count' => $skills->count(),
            'parents_count' => $parents->count(),
            'children_count' => $children->count(),
            'importance' => $this->knowledgePoint['importance'] ?? 0,
            'category' => $this->knowledgePoint['category'] ?? '未分类',
            'phase' => $this->knowledgePoint['phase'] ?? '未知学段',
        ];
    }

    protected function buildGraphData(?array $point): array
    {
        if (empty($point)) {
            return [
                'nodes' => [],
                'edges' => [],
            ];
        }

        $centerId = $point['kp_code'] ?? uniqid('kp_', true);
        $nodeMap = [
            $centerId => $this->formatGraphNode($point, 'current', 0),
        ];
        $edges = [];

        $nodeBuckets = [
            'prerequisite' => $this->extractNodeList($point, [
                'prerequisite_kps',
                'child_nodes',
                'children',
            ]),
            'post' => $this->extractNodeList($point, [
                'post_kps',
                'parent_nodes'
            ]),
            'related' => $this->extractNodeList($point, [
                'related_kps',
            ]),
        ];

        foreach ($nodeBuckets as $type => $nodes) {
            foreach ($nodes as $index => $item) {
                $formatted = $this->formatGraphNode($item, $type, $index + 1);
                if (! $formatted) {
                    continue;
                }

                $nodeMap[$formatted['id']] = $formatted;

                $edges[] = [
                    'source' => $type === 'prerequisite' ? $formatted['id'] : $centerId,
                    'target' => $type === 'prerequisite' ? $centerId : $formatted['id'],
                    'type' => $type,
                ];
            }
        }

        return [
            'nodes' => array_values($nodeMap),
            'edges' => $edges,
        ];
    }

    /**
     * @param array<string, mixed>|string $item
     */
    protected function formatGraphNode(array|string $item, string $type, int $index): ?array
    {
        if (is_array($item)) {
            $id = $item['kp_code'] ?? $item['id'] ?? $item['code'] ?? "{$type}-{$index}";
            $label = $item['cn_name'] ?? $item['label'] ?? $item['name'] ?? $id;
        } elseif (is_string($item)) {
            $id = $item;
            $label = $item;
            $item = [
                'kp_code' => $id,
                'cn_name' => $label,
            ];
        } else {
            return null;
        }

        return [
            'id' => $id,
            'label' => $label,
            'type' => $type,
            'distance' => $type === 'current' ? 0 : 1,
            'meta' => $item,
        ];
    }

    protected function extractNodeList(array $point, array $keys): array
    {
        foreach ($keys as $key) {
            if (!empty($point[$key]) && is_array($point[$key])) {
                return $point[$key];
            }
        }

        return [];
    }
}
