<?php

namespace GriffinForms\Includes\Onboarding;

use GriffinForms\Traits\Singleton;

class ContentClassifier extends \GriffinForms\Format
{
    use Singleton;

    protected $detectors;

    protected function setDetectors()
    {
        $detectors = [
            \GriffinForms\Includes\Onboarding\Builderdetectors\Elementor::getInstance(),
            \GriffinForms\Includes\Onboarding\Builderdetectors\Gutenberg::getInstance(),
            \GriffinForms\Includes\Onboarding\Builderdetectors\Classiccontent::getInstance(),
        ];

        if (function_exists('apply_filters')) {
            $detectors = apply_filters('griffinforms_onboarding_builder_detectors', $detectors);
        }

        $this->detectors = is_array($detectors) ? array_values($detectors) : [];
    }

    public function classifyPost($post): array
    {
        if (is_numeric($post)) {
            $post = get_post((int) $post);
        }

        if (!$post instanceof \WP_Post) {
            return $this->getDefaultResult([
                'classification' => 'unsupported',
                'builder_key' => 'unknown_builder',
                'confidence' => 'high',
                'reasons' => [
                    'Target post could not be loaded for builder classification.',
                ],
            ]);
        }

        $best_result = $this->getDefaultResult();

        foreach ($this->detectors as $detector) {
            if (!is_object($detector) || !method_exists($detector, 'detect')) {
                continue;
            }

            $result = $detector->detect($post);
            if (!is_array($result)) {
                continue;
            }

            $result = $this->normalizeResult($result);
            if ($this->shouldReplaceResult($best_result, $result)) {
                $best_result = $result;
            }
        }

        if (function_exists('apply_filters')) {
            $best_result = apply_filters('griffinforms_onboarding_content_classification', $best_result, $post);
        }

        return $this->normalizeResult(is_array($best_result) ? $best_result : []);
    }

    protected function shouldReplaceResult(array $current, array $candidate): bool
    {
        $current_classification_rank = $this->getClassificationRank((string) ($current['classification'] ?? 'safe'));
        $candidate_classification_rank = $this->getClassificationRank((string) ($candidate['classification'] ?? 'safe'));

        if ($candidate_classification_rank !== $current_classification_rank) {
            return $candidate_classification_rank > $current_classification_rank;
        }

        $current_confidence_rank = $this->getConfidenceRank((string) ($current['confidence'] ?? 'low'));
        $candidate_confidence_rank = $this->getConfidenceRank((string) ($candidate['confidence'] ?? 'low'));

        return $candidate_confidence_rank > $current_confidence_rank;
    }

    protected function getClassificationRank(string $classification): int
    {
        $ranks = [
            'safe' => 1,
            'caution' => 2,
            'unsupported' => 3,
        ];

        return $ranks[$classification] ?? 0;
    }

    protected function getConfidenceRank(string $confidence): int
    {
        $ranks = [
            'low' => 1,
            'medium' => 2,
            'high' => 3,
        ];

        return $ranks[$confidence] ?? 0;
    }

    protected function normalizeResult(array $result): array
    {
        $default = $this->getDefaultResult();
        $normalized = array_merge($default, $result);

        $allowed_classifications = ['safe', 'caution', 'unsupported'];
        if (!in_array($normalized['classification'], $allowed_classifications, true)) {
            $normalized['classification'] = $default['classification'];
        }

        $allowed_confidence = ['low', 'medium', 'high'];
        if (!in_array($normalized['confidence'], $allowed_confidence, true)) {
            $normalized['confidence'] = $default['confidence'];
        }

        $normalized['builder_key'] = sanitize_key((string) $normalized['builder_key']);
        if ($normalized['builder_key'] === '') {
            $normalized['builder_key'] = $default['builder_key'];
        }

        $normalized['reasons'] = is_array($normalized['reasons']) ? array_values(array_filter(array_map('strval', $normalized['reasons']))) : [];

        return $normalized;
    }

    protected function getDefaultResult(array $overrides = []): array
    {
        return array_merge([
            'classification' => 'safe',
            'builder_key' => 'none',
            'confidence' => 'low',
            'reasons' => [],
        ], $overrides);
    }
}
