<?php

namespace App\Services;

use App\Models\KnowledgePoint;
use Illuminate\Support\Facades\Cache;

class AiKnowledgeService
{
    public function matchKnowledgePoints(string $questionText, array $candidates = []): array
    {
        $matched = [];

        $pool = $candidates;
        if (empty($pool)) {
            $pool = KnowledgePoint::query()->select(['kp_code', 'name'])->limit(200)->get()->toArray();
        }

        foreach ($pool as $item) {
            $name = is_array($item) ? ($item['name'] ?? '') : ($item->name ?? '');
            $kpCode = is_array($item) ? ($item['kp_code'] ?? '') : ($item->kp_code ?? '');
            if ($name !== '' && mb_strpos($questionText, $name) !== false) {
                $matched[] = [
                    'kp_code' => $kpCode,
                    'weight' => 1,
                ];
            }
        }

        return $matched;
    }

    public function matchKnowledgePointsByAi(string $questionText, array $candidates = [], ?string $context = null): array
    {
        if (empty($candidates)) {
            $candidates = $this->getCandidateKnowledgePoints();
        }

        $prompt = app(QuestionPromptService::class)->buildKnowledgeMatchPrompt($questionText, $candidates, $context);

        try {
            $result = app(AiClientService::class)->callJson($prompt);
        } catch (\Throwable $e) {
            return [];
        }

        $items = $result['knowledge_points'] ?? [];
        $matches = [];
        foreach ($items as $item) {
            $kpCode = $item['kp_code'] ?? null;
            if (!$kpCode) {
                continue;
            }
            $matches[] = [
                'kp_code' => $kpCode,
                'weight' => $item['weight'] ?? 1,
            ];
        }

        return $matches;
    }

    public function isValidKnowledgePoint(?string $kpCode): bool
    {
        if (!$kpCode) {
            return false;
        }

        $cacheKey = "kp-valid-{$kpCode}";
        return Cache::remember($cacheKey, now()->addMinutes(30), function () use ($kpCode) {
            return KnowledgePoint::query()->where('kp_code', $kpCode)->exists();
        });
    }

    public function getCandidateKnowledgePoints(int $limit = 300): array
    {
        return KnowledgePoint::query()
            ->select(['kp_code', 'name'])
            ->orderBy('kp_code')
            ->limit($limit)
            ->get()
            ->toArray();
    }

    public function inferKnowledgeWeights(array $questionStruct): array
    {
        $kps = $questionStruct['knowledge_points'] ?? [];
        return array_map(function ($kp) {
            return [
                'kp_code' => $kp,
                'weight' => 1,
            ];
        }, $kps);
    }
}
