<?php

declare(strict_types=1);

namespace Tests\Framework\Waf\Feedback;

use App\Framework\Core\ValueObjects\Timestamp;
use App\Framework\Waf\DetectionCategory;
use App\Framework\Waf\Feedback\DetectionFeedback;
use App\Framework\Waf\Feedback\FeedbackRepositoryInterface;
use App\Framework\Waf\Feedback\FeedbackType;

/**
 * In-memory implementation of FeedbackRepositoryInterface for testing
 */
class InMemoryFeedbackRepository implements FeedbackRepositoryInterface
{
    /** @var DetectionFeedback[] */
    private array $feedback = [];

    /**
     * {@inheritdoc}
     */
    public function saveFeedback(DetectionFeedback $feedback): void
    {
        $this->feedback[] = $feedback;
    }

    /**
     * {@inheritdoc}
     */
    public function getFeedbackForDetection(string $detectionId): array
    {
        return array_filter(
            $this->feedback,
            fn (DetectionFeedback $feedback) => $feedback->detectionId === $detectionId
        );
    }

    /**
     * {@inheritdoc}
     */
    public function getFeedbackByCategory(DetectionCategory $category, ?Timestamp $since = null): array
    {
        return array_filter(
            $this->feedback,
            function (DetectionFeedback $feedback) use ($category, $since) {
                if ($feedback->category !== $category) {
                    return false;
                }

                if ($since !== null && $feedback->timestamp->getTimestamp() < $since->getTimestamp()) {
                    return false;
                }

                return true;
            }
        );
    }

    /**
     * {@inheritdoc}
     */
    public function getFeedbackByFeedbackType(FeedbackType $feedbackType, ?Timestamp $since = null): array
    {
        return array_filter(
            $this->feedback,
            function (DetectionFeedback $feedback) use ($feedbackType, $since) {
                if ($feedback->feedbackType !== $feedbackType) {
                    return false;
                }

                if ($since !== null && $feedback->timestamp->getTimestamp() < $since->getTimestamp()) {
                    return false;
                }

                return true;
            }
        );
    }

    /**
     * {@inheritdoc}
     */
    public function getFeedbackStats(): array
    {
        $totalCount = count($this->feedback);

        // Count by feedback type
        $byFeedbackType = [];
        foreach (FeedbackType::cases() as $type) {
            $byFeedbackType[$type->value] = count($this->getFeedbackByFeedbackType($type));
        }

        // Count by category
        $byCategory = [];
        foreach (DetectionCategory::cases() as $category) {
            $count = count($this->getFeedbackByCategory($category));
            if ($count > 0) {
                $byCategory[$category->value] = $count;
            }
        }

        // Generate trend data (simplified for testing)
        $trendData = [];
        $today = date('Y-m-d');

        foreach (FeedbackType::cases() as $type) {
            if (! isset($trendData[$today])) {
                $trendData[$today] = [];
            }

            $trendData[$today][$type->value] = count($this->getFeedbackByFeedbackType($type));
        }

        return [
            'total_count' => $totalCount,
            'by_feedback_type' => $byFeedbackType,
            'by_category' => $byCategory,
            'trend_data' => $trendData,
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function getRecentFeedback(int $limit = 10): array
    {
        $feedback = $this->feedback;

        // Sort by timestamp (newest first)
        usort($feedback, function (DetectionFeedback $a, DetectionFeedback $b) {
            return $b->timestamp->getTimestamp() <=> $a->timestamp->getTimestamp();
        });

        // Limit the results
        return array_slice($feedback, 0, $limit);
    }

    /**
     * Get all feedback stored in the repository
     *
     * @return DetectionFeedback[] All feedback
     */
    public function getAllFeedback(): array
    {
        return $this->feedback;
    }

    /**
     * Clear all feedback from the repository
     */
    public function clear(): void
    {
        $this->feedback = [];
    }
}
