<?php

namespace App\Services;

use App\Models\RPublication;
use App\Models\RReviewFeedback;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Notification;

/**
 * Service: ReviewWorkflowService
 * 
 * Manages the review workflow for research publications.
 * Handles review queue, feedback processing, and notifications.
 * 
 * @author SSHIA Development Team
 * @version 1.0.0
 */
class ReviewWorkflowService
{
    /**
     * Get review queue for managers.
     */
    public function getReviewQueue(array $filters = [])
    {
        $query = RPublication::underReview()
                           ->with(['user', 'files'])
                           ->latest('submitted_at');

        // Apply filters
        if (!empty($filters['category'])) {
            $query->where('category', $filters['category']);
        }

        if (!empty($filters['submitted_from'])) {
            $query->whereDate('submitted_at', '>=', $filters['submitted_from']);
        }

        if (!empty($filters['submitted_to'])) {
            $query->whereDate('submitted_at', '<=', $filters['submitted_to']);
        }

        return $query->paginate($filters['per_page'] ?? 15);
    }

    /**
     * Submit review feedback.
     */
    public function submitReview(RPublication $publication, int $reviewerId, array $data): RReviewFeedback
    {
        if (!$publication->canReview()) {
            throw new \Exception('Publication cannot be reviewed in its current status.');
        }

        return DB::transaction(function () use ($publication, $reviewerId, $data) {
            // Create review feedback
            $feedback = RReviewFeedback::create([
                'publication_id' => $publication->id,
                'reviewer_id' => $reviewerId,
                'decision' => $data['decision'],
                'comments' => $data['comments'],
                'criteria_evaluation' => $data['criteria_evaluation'] ?? null,
                'reviewed_at' => now(),
            ]);

            // Process the decision
            $this->processDecision($publication, $data['decision'], $reviewerId);

            // Notify author
            $this->notifyAuthor($publication, $feedback);

            return $feedback;
        });
    }

    /**
     * Process review decision.
     */
    protected function processDecision(RPublication $publication, string $decision, int $reviewerId): void
    {
        switch ($decision) {
            case RReviewFeedback::DECISION_APPROVE:
                $this->approvePublication($publication, $reviewerId);
                break;

            case RReviewFeedback::DECISION_REQUEST_REVISION:
                $this->requestRevision($publication);
                break;

            case RReviewFeedback::DECISION_REJECT:
                $this->rejectPublication($publication);
                break;
        }
    }

    /**
     * Approve publication.
     */
    public function approvePublication(RPublication $publication, int $approverId): void
    {
        $publication->update([
            'status' => RPublication::STATUS_APPROVED,
            'approved_at' => now(),
            'approved_by' => $approverId,
        ]);
    }

    /**
     * Feature a publication.
     */
    public function featurePublication(RPublication $publication, int $userId): void
    {
        if (!in_array($publication->status, [RPublication::STATUS_APPROVED, RPublication::STATUS_FEATURED])) {
            throw new \Exception('Only approved publications can be featured.');
        }

        $publication->update([
            'status' => RPublication::STATUS_FEATURED,
            'is_featured' => true,
        ]);
    }

    /**
     * Remove featured status.
     */
    public function unfeaturePublication(RPublication $publication): void
    {
        $publication->update([
            'status' => RPublication::STATUS_APPROVED,
            'is_featured' => false,
        ]);
    }

    /**
     * Request revision.
     */
    public function requestRevision(RPublication $publication): void
    {
        $publication->update([
            'status' => RPublication::STATUS_REVISION_REQUIRED,
        ]);
    }

    /**
     * Reject publication.
     */
    public function rejectPublication(RPublication $publication): void
    {
        $publication->update([
            'status' => 'rejected',
        ]);
    }

    /**
     * Notify author of review decision.
     */
    protected function notifyAuthor(RPublication $publication, RReviewFeedback $feedback): void
    {
        $author = $publication->user;

        if (!$author) {
            return;
        }

        // TODO: Implement notification
        // Notification::send($author, new ReviewDecisionNotification($publication, $feedback));
    }

    /**
     * Get review statistics for dashboard.
     */
    public function getReviewStats(int $reviewerId = null): array
    {
        $query = RReviewFeedback::query();

        if ($reviewerId) {
            $query->where('reviewer_id', $reviewerId);
        }

        return [
            'total_reviews' => $query->count(),
            'approved' => $query->approved()->count(),
            'rejected' => $query->rejected()->count(),
            'revision_requested' => $query->where('decision', RReviewFeedback::DECISION_REQUEST_REVISION)->count(),
            'pending_in_queue' => RPublication::underReview()->count(),
        ];
    }

    /**
     * Get publications pending review for specific reviewer.
     */
    public function getPendingForReviewer(int $reviewerId)
    {
        // Get publications that the reviewer hasn't reviewed yet
        $reviewedIds = RReviewFeedback::where('reviewer_id', $reviewerId)
                                      ->pluck('publication_id')
                                      ->toArray();

        return RPublication::underReview()
                          ->whereNotIn('id', $reviewedIds)
                          ->with(['user', 'files'])
                          ->latest('submitted_at')
                          ->get();
    }

    /**
     * Check if reviewer has already reviewed publication.
     */
    public function hasReviewed(int $publicationId, int $reviewerId): bool
    {
        return RReviewFeedback::where('publication_id', $publicationId)
                             ->where('reviewer_id', $reviewerId)
                             ->exists();
    }

    /**
     * Get review history for publication.
     */
    public function getReviewHistory(RPublication $publication)
    {
        return $publication->reviews()
                          ->with('reviewer')
                          ->latest()
                          ->get();
    }

    /**
     * Calculate average scores from criteria evaluations.
     */
    public function calculateAverageScores(RPublication $publication): array
    {
        $reviews = $publication->reviews;
        $scores = [];

        foreach (RReviewFeedback::CRITERIA as $key => $label) {
            $total = 0;
            $count = 0;

            foreach ($reviews as $review) {
                if (isset($review->criteria_evaluation[$key])) {
                    $total += $review->criteria_evaluation[$key];
                    $count++;
                }
            }

            $scores[$key] = [
                'label' => $label,
                'average' => $count > 0 ? round($total / $count, 2) : null,
                'count' => $count,
            ];
        }

        return $scores;
    }
}
