<?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 Illuminate\Support\Str;
use UnitEnum;

class KnowledgePoints extends Page
{
    protected static ?string $slug = 'knowledge-points-overview';

    protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-map';

    protected static string|UnitEnum|null $navigationGroup = '知识图谱管理';

    protected static ?string $navigationLabel = '知识点总览';

    protected static ?int $navigationSort = 9;

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

    public ?string $phaseFilter = null;

    public ?string $categoryFilter = null;

    public ?string $search = null;

    public int $page = 1;

    public int $perPage = 8;

    protected bool $loading = false;

    protected ?KnowledgeServiceApi $knowledgeService = null;

    protected ?string $selectedKpCode = null;

    // Private property to store loaded data
    private ?array $selectedPointData = null;

    public function mount(Request $request): void
    {
        // Only set properties that need to be available immediately
        // The search and filter properties will be set via getter
        $this->selectedKpCode = $request->query('selected');
        $this->page = (int) $request->query('page', 1);
    }

    public function getSelectedPointProperty(): ?array
    {
        if ($this->selectedPointData) {
            return $this->selectedPointData;
        }

        // If we have a specific kp code to load
        if ($this->selectedKpCode) {
            $this->selectedPointData = $this->getKnowledgeService()->getFullGraphData($this->selectedKpCode);
            return $this->selectedPointData;
        }

        // Get first point from paginated results
        $points = $this->paginatedPoints;
        if (!empty($points['data']) && count($points['data']) > 0) {
            $kpCode = $points['data'][0]['kp_code'];
            $this->selectedPointData = $this->getKnowledgeService()->getFullGraphData($kpCode);
        }

        return $this->selectedPointData;
    }

    public function getCurrentPhaseProperty(): ?string
    {
        return request()->query('phase');
    }

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

        return $this->knowledgeService;
    }

    public function selectPoint(string $kpCode): void
    {
        $this->selectedPoint = $this->getKnowledgeService()->getKnowledgePointDetail($kpCode);
    }

    public function getStatsProperty(): array
    {
        $all = $this->getKnowledgeService()->listKnowledgePoints();

        $phases = $all->groupBy('phase')->map->count()->sortDesc()->map(fn ($count, $phase) => "{$phase}·{$count}");
        $categories = $all->groupBy('category')->map->count()->sortDesc()->take(3)->map(fn ($count, $category) => "{$category}·{$count}");

        return [
            ['label' => '知识点数量', 'value' => number_format($all->count()), 'hint' => '当前版本节点'],
            ['label' => '学段覆盖', 'value' => $phases->implode(' | ') ?: '未配置', 'hint' => 'phase 字段'],
            ['label' => 'Top 类别', 'value' => $categories->implode(' | ') ?: '未配置', 'hint' => 'category 字段'],
            ['label' => '平均重要度', 'value' => number_format($all->avg('importance') ?? 0, 1), 'hint' => 'importance'],
        ];
    }

    public function getPhaseOptionsProperty(): array
    {
        return $this->getKnowledgeService()
            ->listKnowledgePoints()
            ->pluck('phase')
            ->filter()
            ->unique()
            ->sort()
            ->mapWithKeys(fn ($phase) => [$phase => $phase])
            ->all();
    }

    public function getCategoryOptionsProperty(): array
    {
        return $this->getKnowledgeService()
            ->listKnowledgePoints()
            ->pluck('category')
            ->filter()
            ->unique()
            ->sort()
            ->mapWithKeys(fn ($category) => [$category => $category])
            ->all();
    }

    public function getPaginatedPointsProperty(): array
    {
        // Get filters from URL
        $request = request();
        $phaseFilter = $request->query('phase');
        $categoryFilter = $request->query('category');
        $searchTerm = trim((string) $request->query('search'));

        // Get all points
        $filters = array_filter([
            'phase' => $phaseFilter,
            'category' => $categoryFilter,
        ]);

        $allPoints = $this->getKnowledgeService()->listKnowledgePoints(
            perPage: 200,
            filters: $filters
        );

        // Apply search filter on the client side
        if ($searchTerm !== '') {
            $allPoints = $allPoints->filter(function (array $record) use ($searchTerm): bool {
                return Str::contains(Str::lower($record['cn_name'] ?? ''), Str::lower($searchTerm))
                    || Str::contains(Str::lower($record['kp_code'] ?? ''), Str::lower($searchTerm))
                    || Str::contains(Str::lower($record['description'] ?? ''), Str::lower($searchTerm));
            });
        }

        // Paginate the results
        $total = $allPoints->count();
        $totalPages = (int) ceil($total / $this->perPage);
        $offset = ($this->page - 1) * $this->perPage;
        $records = $allPoints->slice($offset, $this->perPage)->values();

        return [
            'data' => $records,
            'total' => $total,
            'page' => $this->page,
            'total_pages' => $totalPages,
            'has_prev' => $this->page > 1,
            'has_next' => $this->page < $totalPages,
        ];
    }

    public function getSelectedSkillsProperty(): Collection
    {
        $selectedPoint = $this->selectedPointData;
        return collect($selectedPoint['skills'] ?? []);
    }

    public function getRelatedNodesProperty(): array
    {
        $point = $this->selectedPointData;

        if (! $point) {
            return ['parents' => [], 'children' => []];
        }

        $parents = collect($point['parents'] ?? [])
            ->map(fn ($name, $index) => [
                'id' => "parent-{$index}",
                'label' => $name,
                'relation' => 'parent',
            ])->values()->all();

        $children = collect($point['children'] ?? [])
            ->map(fn ($name, $index) => [
                'id' => "child-{$index}",
                'label' => $name,
                'relation' => 'child',
            ])->values()->all();

        return ['parents' => $parents, 'children' => $children];
    }

}
