<?php
declare(strict_types=1);

namespace App\Modules\Coaches\Services;

use App\Core\App;
use App\Core\EventBus;
use App\Core\Logger;
use App\Modules\Coaches\Models\CoachRating;
use App\Modules\Coaches\Models\Coach;

final class CoachRatingService
{
    /**
     * Submit a rating for a coach.
     */
    public static function submitRating(array $data): CoachRating
    {
        $playerId = (int) ($data['player_id'] ?? 0);
        $coachId = (int) ($data['coach_id'] ?? 0);
        $sessionId = !empty($data['session_id']) ? (int) $data['session_id'] : null;

        // Validate one rating per player per session
        if (CoachRating::hasRated($playerId, $coachId, $sessionId)) {
            throw new \RuntimeException('لقد قمت بتقييم هذا المدرب بالفعل لهذه الحصة');
        }

        // Calculate overall rating from dimension scores
        $scores = [
            (int) ($data['punctuality_score'] ?? 0),
            (int) ($data['communication_score'] ?? 0),
            (int) ($data['technique_score'] ?? 0),
            (int) ($data['motivation_score'] ?? 0),
        ];
        $validScores = array_filter($scores, fn($s) => $s > 0);
        $avgRating = !empty($validScores) ? (int) round(array_sum($validScores) / count($validScores)) : (int) ($data['rating'] ?? 3);

        $ratingData = [
            'coach_id'            => $coachId,
            'player_id'           => $playerId,
            'member_id'           => !empty($data['member_id']) ? (int) $data['member_id'] : null,
            'session_id'          => $sessionId,
            'rating'              => $avgRating,
            'punctuality_score'   => (int) ($data['punctuality_score'] ?? 0),
            'communication_score' => (int) ($data['communication_score'] ?? 0),
            'technique_score'     => (int) ($data['technique_score'] ?? 0),
            'motivation_score'    => (int) ($data['motivation_score'] ?? 0),
            'feedback_ar'         => trim((string) ($data['feedback_ar'] ?? '')) ?: null,
            'is_anonymous'        => (int) ($data['is_anonymous'] ?? 0),
            'status'              => 'published',
        ];

        $rating = CoachRating::create($ratingData);

        // Dispatch event
        EventBus::dispatch('coach.rated', [
            'rating_id' => (int) $rating->id,
            'coach_id'  => $coachId,
            'player_id' => $playerId,
            'rating'    => $avgRating,
        ]);

        Logger::info("Coach #{$coachId} rated {$avgRating}/5 by player #{$playerId}");

        return $rating;
    }

    /**
     * Get full coach profile with ratings and averages.
     */
    public static function getCoachProfile(int $coachId): array
    {
        $coach = Coach::findOrFail($coachId);
        $averages = CoachRating::getAverages($coachId);
        $recentRatings = CoachRating::getForCoach($coachId, 20);

        $db = App::getInstance()->db();

        // Rating distribution (1-5 stars)
        $distribution = $db->select(
            "SELECT rating, COUNT(*) AS cnt FROM coach_ratings
             WHERE coach_id = ? AND status = 'published'
             GROUP BY rating ORDER BY rating DESC",
            [$coachId]
        );

        $ratingDist = [5 => 0, 4 => 0, 3 => 0, 2 => 0, 1 => 0];
        foreach ($distribution as $d) {
            $ratingDist[(int) $d['rating']] = (int) $d['cnt'];
        }

        return [
            'coach'          => $coach,
            'averages'       => $averages,
            'recent_ratings' => $recentRatings,
            'distribution'   => $ratingDist,
        ];
    }

    /**
     * Flag a rating as inappropriate.
     */
    public static function flagRating(int $ratingId, string $reason): bool
    {
        $rating = CoachRating::findOrFail($ratingId);
        $rating->update(['status' => 'flagged']);

        Logger::info("Rating #{$ratingId} flagged: {$reason}");

        return true;
    }

    /**
     * Admin responds to a rating.
     */
    public static function respondToRating(int $ratingId, string $response): bool
    {
        $rating = CoachRating::findOrFail($ratingId);
        $rating->update(['admin_response_ar' => $response]);

        Logger::info("Admin responded to rating #{$ratingId}");

        return true;
    }
}
