<?php

namespace adrienpayet\notifications;

use Kirby\Cms\Page;
use Kirby\Cms\User;

/**
 * Collecteur de notifications qui agrège tous les providers.
 *
 * Permet de :
 * - Enregistrer des providers de notifications
 * - Collecter toutes les notifications de tous les providers
 * - Déléguer le markAsRead au bon provider
 */
class NotificationCollector
{
    /** @var NotificationProvider[] */
    private array $providers = [];

    /**
     * Enregistre un nouveau provider.
     */
    public function register(NotificationProvider $provider): void
    {
        $this->providers[$provider->getType()] = $provider;
    }

    /**
     * Collecte toutes les notifications de tous les providers pour un projet.
     *
     * @param Page $project Le projet à scanner
     * @param User $user L'utilisateur courant
     * @return array Liste triée par date décroissante
     */
    public function collect(Page $project, User $user): array
    {
        $all = [];

        foreach ($this->providers as $provider) {
            try {
                $notifications = $provider->collect($project, $user);
                $all = array_merge($all, $notifications);
            } catch (\Throwable $e) {
                // Log l'erreur mais continue avec les autres providers
                error_log("NotificationCollector: Error in {$provider->getType()}: " . $e->getMessage());
            }
        }

        // Trier par date décroissante
        usort($all, function ($a, $b) {
            $dateA = strtotime($a['date'] ?? '0');
            $dateB = strtotime($b['date'] ?? '0');
            return $dateB - $dateA;
        });

        return $all;
    }

    /**
     * Collecte uniquement les données minimales des notifications (version allégée pour listing).
     * Retourne les champs nécessaires à l'affichage mais sans les détails lourds.
     *
     * @param Page $project Le projet à scanner
     * @param User $user L'utilisateur courant
     * @return array Liste triée par date décroissante
     */
    public function collectLight(Page $project, User $user): array
    {
        $all = [];

        foreach ($this->providers as $provider) {
            try {
                $notifications = $provider->collect($project, $user);
                // Garder les champs nécessaires au frontend
                foreach ($notifications as $notification) {
                    $light = [
                        'id' => $notification['id'] ?? null,
                        'type' => $notification['type'] ?? null,
                        'isRead' => $notification['isRead'] ?? false,
                        'date' => $notification['date'] ?? null,
                        'text' => $notification['text'] ?? null,
                        'author' => $notification['author'] ?? null,
                        'location' => $notification['location'] ?? []
                    ];

                    // Garder les champs optionnels s'ils existent
                    if (isset($notification['dialogUri'])) {
                        $light['dialogUri'] = $notification['dialogUri'];
                    }
                    if (isset($notification['_briefUri'])) {
                        $light['_briefUri'] = $notification['_briefUri'];
                    }
                    if (isset($notification['_file'])) {
                        $light['_file'] = $notification['_file'];
                    }
                    if (isset($notification['_projectUri'])) {
                        $light['_projectUri'] = $notification['_projectUri'];
                    }

                    $all[] = $light;
                }
            } catch (\Throwable $e) {
                error_log("NotificationCollector: Error in {$provider->getType()}: " . $e->getMessage());
            }
        }

        // Trier par date décroissante
        usort($all, function ($a, $b) {
            $dateA = strtotime($a['date'] ?? '0');
            $dateB = strtotime($b['date'] ?? '0');
            return $dateB - $dateA;
        });

        return $all;
    }

    /**
     * Marque une notification comme lue en déléguant au bon provider.
     *
     * @param string $type Le type de notification
     * @param string $id L'identifiant de la notification
     * @param array $location Informations de localisation
     * @param User $user L'utilisateur qui marque comme lu
     * @return bool True si succès
     */
    public function markAsRead(string $type, string $id, array $location, User $user): bool
    {
        if (!isset($this->providers[$type])) {
            error_log("NotificationCollector: Unknown notification type: $type");
            return false;
        }

        try {
            return $this->providers[$type]->markAsRead($id, $location, $user);
        } catch (\Throwable $e) {
            error_log("NotificationCollector: Error marking as read: " . $e->getMessage());
            return false;
        }
    }

    /**
     * Marque toutes les notifications comme lues pour un utilisateur.
     *
     * @param Page[] $projects Liste des projets
     * @param User $user L'utilisateur
     * @return int Nombre de notifications marquées comme lues
     */
    public function markAllAsRead(array $projects, User $user): int
    {
        $count = 0;

        foreach ($projects as $project) {
            $notifications = $this->collect($project, $user);

            foreach ($notifications as $notification) {
                if (!($notification['isRead'] ?? false)) {
                    $success = $this->markAsRead(
                        $notification['type'],
                        $notification['id'],
                        $notification,
                        $user
                    );
                    if ($success) {
                        $count++;
                    }
                }
            }
        }

        return $count;
    }

    /**
     * Retourne la liste des types de notifications enregistrés.
     */
    public function getRegisteredTypes(): array
    {
        return array_keys($this->providers);
    }
}
