<?php

declare(strict_types=1);

namespace App\Services\Upload;

use App\Services\TagNormalizer;

final class TagAnalysisService
{
    public function __construct(private readonly TagNormalizer $normalizer)
    {
    }

    /**
     * @return array<int, array{tag:string,confidence:float,source:string}>
     */
    public function analyze(string $filename, ?string $previewPath, ?string $categoryContext): array
    {
        $results = [];

        foreach ($this->extractFilenameTags($filename) as $tag) {
            $results[] = [
                'tag' => $tag,
                'confidence' => 0.72,
                'source' => 'filename',
            ];
        }

        if ($previewPath !== null && $previewPath !== '') {
            // Stub AI output for now (real model integration can replace this later)
            $results[] = [
                'tag' => 'ai-detected',
                'confidence' => 0.66,
                'source' => 'ai',
            ];
            $results[] = [
                'tag' => 'visual-content',
                'confidence' => 0.61,
                'source' => 'ai',
            ];
        }

        if ($categoryContext !== null && $categoryContext !== '') {
            $normalized = $this->normalizer->normalize($categoryContext);
            if ($normalized !== '') {
                $results[] = [
                    'tag' => $normalized,
                    'confidence' => 0.60,
                    'source' => 'manual',
                ];
            }
        }

        return $this->dedupe($results);
    }

    /**
     * @return array<int, string>
     */
    private function extractFilenameTags(string $filename): array
    {
        $base = pathinfo($filename, PATHINFO_FILENAME) ?: $filename;
        $parts = preg_split('/[\s._\-]+/', mb_strtolower($base, 'UTF-8')) ?: [];

        $tags = [];
        foreach ($parts as $part) {
            $normalized = $this->normalizer->normalize((string) $part);
            if ($normalized !== '' && mb_strlen($normalized, 'UTF-8') >= 3) {
                $tags[] = $normalized;
            }
        }

        return array_values(array_unique($tags));
    }

    /**
     * @param array<int, array{tag:string,confidence:float,source:string}> $rows
     * @return array<int, array{tag:string,confidence:float,source:string}>
     */
    private function dedupe(array $rows): array
    {
        $best = [];

        foreach ($rows as $row) {
            $tag = $this->normalizer->normalize((string) ($row['tag'] ?? ''));
            if ($tag === '') {
                continue;
            }

            $confidence = (float) ($row['confidence'] ?? 0.0);
            $source = (string) ($row['source'] ?? 'manual');

            if (! isset($best[$tag]) || $best[$tag]['confidence'] < $confidence) {
                $best[$tag] = [
                    'tag' => $tag,
                    'confidence' => max(0.0, min(1.0, $confidence)),
                    'source' => in_array($source, ['ai', 'filename', 'manual'], true) ? $source : 'manual',
                ];
            }
        }

        return array_values($best);
    }
}
