<?php

declare(strict_types=1);

namespace Bot\Infrastructure\Repository;

use Bot\Domain\Repository\LogRepositoryInterface;

/**
 * پیاده‌سازی in-memory برای لاگ‌ها (فقط برای تست)
 */
final class InMemoryLogRepository implements LogRepositoryInterface
{
    /** @var array<array<string, mixed>> */
    private array $logs = [];

    public function log(
        string $level,
        string $message,
        array $context = [],
        ?string $file = null,
        ?int $line = null,
        ?int $telegramId = null,
        ?int $userId = null,
        ?int $adminId = null,
        ?int $mediaId = null,
        ?\Throwable $exception = null,
    ): void {
        $this->logs[] = [
            'level' => $level,
            'message' => $message,
            'context' => $context,
            'file' => $file,
            'line' => $line,
            'telegram_id' => $telegramId,
            'user_id' => $userId,
            'admin_id' => $adminId,
            'media_id' => $mediaId,
            'exception_type' => $exception !== null ? get_class($exception) : null,
            'exception_message' => $exception?->getMessage(),
            'exception_trace' => $exception !== null ? $exception->getTraceAsString() : null,
            'created_at' => date('Y-m-d H:i:s'),
        ];
    }

    public function findLogs(
        ?string $level = null,
        ?\DateTimeImmutable $startDate = null,
        ?\DateTimeImmutable $endDate = null,
        ?int $telegramId = null,
        int $limit = 100,
        int $offset = 0,
    ): array {
        $filtered = $this->logs;

        if ($level !== null) {
            $filtered = array_filter($filtered, fn($log) => $log['level'] === $level);
        }

        if ($telegramId !== null) {
            $filtered = array_filter($filtered, fn($log) => $log['telegram_id'] === $telegramId);
        }

        if ($startDate !== null) {
            $filtered = array_filter($filtered, function($log) use ($startDate) {
                return strtotime($log['created_at']) >= $startDate->getTimestamp();
            });
        }

        if ($endDate !== null) {
            $filtered = array_filter($filtered, function($log) use ($endDate) {
                return strtotime($log['created_at']) <= $endDate->getTimestamp();
            });
        }

        $filtered = array_reverse($filtered);
        return array_slice($filtered, $offset, $limit);
    }

    public function countLogs(
        ?string $level = null,
        ?\DateTimeImmutable $startDate = null,
        ?\DateTimeImmutable $endDate = null,
        ?int $telegramId = null,
    ): int {
        return count($this->findLogs($level, $startDate, $endDate, $telegramId, PHP_INT_MAX, 0));
    }

    public function deleteOldLogs(\DateTimeImmutable $beforeDate): int {
        $count = 0;
        $this->logs = array_filter($this->logs, function($log) use ($beforeDate, &$count) {
            $shouldKeep = strtotime($log['created_at']) >= $beforeDate->getTimestamp();
            if (!$shouldKeep) {
                $count++;
            }
            return $shouldKeep;
        });
        return $count;
    }
}

