<?php
declare(strict_types=1);

namespace App\Support;

final class ReportBuilder
{
    private RecommendationStore $recommendationStore;
    private AreaContentStore $areaContentStore;

    public function __construct()
    {
        $this->recommendationStore = new RecommendationStore();
        $this->areaContentStore = new AreaContentStore();
    }

    public function build(array $participant, array $questions, array $answers): array
    {
        $areas = (array) config('riasec_areas', []);
        $languageCode = (string) ($participant['language'] ?? config('default_language', 'en'));
        $scores = [];
        $maximumScore = [];

        foreach ($areas as $code => $area) {
            $scores[$code] = 0;
            $maximumScore[$code] = 0;
        }

        foreach ($questions as $question) {
            $areaCode = $question['area_code'];
            $maximumScore[$areaCode]++;
            $scores[$areaCode] += (int) ($answers[$question['id']] ?? 0);
        }

        $rankedAreas = array_keys($scores);
        usort($rankedAreas, static function (string $left, string $right) use ($scores): int {
            return $scores[$right] <=> $scores[$left];
        });

        $rankings = [];

        foreach ($rankedAreas as $position => $areaCode) {
            $area = $areas[$areaCode];
            $rankings[] = [
                'rank' => $position + 1,
                'code' => $areaCode,
                'name' => \area_name($areaCode, $languageCode),
                'score' => $scores[$areaCode],
                'max_score' => $maximumScore[$areaCode],
                'color' => $area['color'],
                'description' => $this->areaContentStore->descriptionForArea($areaCode, $languageCode),
                'career_opportunities' => $this->recommendationStore->careersForArea($areaCode, $languageCode),
                'suitable_programmes' => $this->recommendationStore->programmesForArea($areaCode, $languageCode),
            ];
        }

        return [
            'reference' => $this->reference(),
            'participant' => $participant,
            'scores' => $scores,
            'maximum_scores' => $maximumScore,
            'rankings' => $rankings,
            'primary_area' => $rankings[0] ?? null,
            'generated_at' => date('Y-m-d H:i:s'),
            'question_count' => count($questions),
        ];
    }

    public function localize(array $report, string $languageCode): array
    {
        $localizedReport = $report;
        $localizedRankings = [];
        $areas = (array) config('riasec_areas', []);

        foreach ((array) ($report['rankings'] ?? []) as $ranking) {
            $areaCode = (string) ($ranking['code'] ?? '');

            if ($areaCode === '' || !array_key_exists($areaCode, $areas)) {
                $localizedRankings[] = $ranking;
                continue;
            }

            $localizedRanking = $ranking;
            $localizedRanking['name'] = \area_name($areaCode, $languageCode);
            $localizedRanking['description'] = $this->areaContentStore->descriptionForArea($areaCode, $languageCode);
            $localizedRanking['career_opportunities'] = $this->recommendationStore->careersForArea($areaCode, $languageCode);
            $localizedRanking['suitable_programmes'] = $this->recommendationStore->programmesForArea($areaCode, $languageCode);
            $localizedRankings[] = $localizedRanking;
        }

        $localizedReport['rankings'] = $localizedRankings;
        $primaryAreaCode = (string) ($report['primary_area']['code'] ?? ($localizedRankings[0]['code'] ?? ''));

        foreach ($localizedRankings as $ranking) {
            if ((string) ($ranking['code'] ?? '') === $primaryAreaCode) {
                $localizedReport['primary_area'] = $ranking;
                break;
            }
        }

        return $localizedReport;
    }

    private function reference(): string
    {
        return 'RIASEC-' . date('Ymd-His') . '-' . strtoupper(substr(bin2hex(random_bytes(3)), 0, 6));
    }
}