<?php

namespace App\Services;

use Illuminate\Support\Facades\Log;

class ScoringEngine
{
    /**
     * Calculate composite score for keyword recommendation
     */
    public function calculateScore(array $keyword, bool $hasSearchData = true): float
    {
        if ($hasSearchData) {
            return $this->calculateWithSearchData($keyword);
        }

        return $this->calculateWithoutSearchData($keyword);
    }

    /**
     * Calculate score with search volume data
     */
    private function calculateWithSearchData(array $keyword): float
    {
        // Weights (balanced profile)
        $weights = [
            'ai_relevance' => 0.40,
            'search_volume' => 0.25,
            'competition' => 0.15,
            'intent_alignment' => 0.15,
            'keyword_specificity' => 0.05,
        ];

        $scores = [
            'ai_relevance' => $this->normalizeRelevanceScore($keyword['relevance_score'] ?? 0),
            'search_volume' => $this->normalizeSearchVolume($keyword['search_volume'] ?? 0),
            'competition' => $this->normalizeCompetition($keyword['competition_index'] ?? 50),
            'intent_alignment' => $this->calculateIntentAlignment($keyword),
            'keyword_specificity' => $this->calculateKeywordSpecificity($keyword['keyword'] ?? ''),
        ];

        $compositeScore = 0;
        foreach ($scores as $key => $score) {
            $compositeScore += $score * $weights[$key];
        }

        return round($compositeScore, 2);
    }

    /**
     * Calculate score without search volume data
     */
    private function calculateWithoutSearchData(array $keyword): float
    {
        $weights = [
            'ai_relevance' => 0.60,
            'intent_alignment' => 0.25,
            'keyword_specificity' => 0.15,
        ];

        $scores = [
            'ai_relevance' => $this->normalizeRelevanceScore($keyword['relevance_score'] ?? 0),
            'intent_alignment' => $this->calculateIntentAlignment($keyword),
            'keyword_specificity' => $this->calculateKeywordSpecificity($keyword['keyword'] ?? ''),
        ];

        $compositeScore = 0;
        foreach ($scores as $key => $score) {
            $compositeScore += $score * $weights[$key];
        }

        return round($compositeScore, 2);
    }

    /**
     * Normalize relevance score (0-100) to 0-100
     */
    private function normalizeRelevanceScore(float $score): float
    {
        return min(100, max(0, $score));
    }

    /**
     * Normalize search volume using logarithmic scale
     */
    private function normalizeSearchVolume(int $volume): float
    {
        if ($volume <= 0) return 0;

        $minSearchVolume = config('services.seo.min_search_volume', 50);
        if ($volume < $minSearchVolume) return 20;

        // Logarithmic scale: log10 of volume
        // 100 = 40, 1000 = 60, 10000 = 80, 100000 = 100
        $logScore = log10($volume) * 20;

        return min(100, max(0, $logScore));
    }

    /**
     * Normalize competition (inverted - lower is better)
     */
    private function normalizeCompetition(int $competitionIndex): float
    {
        // Invert: 0 = 100, 100 = 0
        return 100 - $competitionIndex;
    }

    /**
     * Calculate intent alignment score
     */
    private function calculateIntentAlignment(array $keyword): float
    {
        $intent = $keyword['search_intent'] ?? 'unknown';

        // Perfect alignment scores
        $alignmentScores = [
            'transactional' => 100,
            'commercial' => 90,
            'informational' => 70,
            'navigational' => 60,
            'unknown' => 50,
        ];

        return $alignmentScores[$intent] ?? 50;
    }

    /**
     * Calculate keyword specificity score (prefer 2-4 words)
     */
    private function calculateKeywordSpecificity(string $keyword): float
    {
        $wordCount = str_word_count($keyword);

        if ($wordCount >= 2 && $wordCount <= 4) {
            return 100;
        } elseif ($wordCount == 1) {
            return 50;
        } elseif ($wordCount >= 5 && $wordCount <= 6) {
            return 80;
        }

        return 40;
    }

    /**
     * Select primary keyword from recommendations
     */
    public function selectPrimaryKeyword(array $keywords): ?array
    {
        if (empty($keywords)) {
            return null;
        }

        // Sort by composite score descending
        usort($keywords, function($a, $b) {
            return ($b['composite_score'] ?? 0) <=> ($a['composite_score'] ?? 0);
        });

        return $keywords[0];
    }
}
