<?php

declare(strict_types=1);

namespace EasyChat\Library\Android;

use EasyChat\Model\AppSession;
use EasyChat\Model\ManagerNoticeState;

final class AndroidUpdateNoticeService
{
    private const NOTICE_KEY = 'android_update';

    private $registry;
    private AndroidReleaseCatalog $catalog;
    private AndroidUpdatePolicy $policy;

    public function __construct($registry, AndroidReleaseCatalog $catalog, ?AndroidUpdatePolicy $policy = null)
    {
        $this->registry = $registry;
        $this->catalog = $catalog;
        $this->policy = $policy ?: new AndroidUpdatePolicy();
    }

     
    public function status(int $manager_id, bool $is_admin): array
    {
        $release = $this->catalog->latest();
        if ($release === []) {
            return ['success' => true, 'available' => false, 'reason' => 'catalog_unavailable'];
        }

        $sessions = new AppSession($this->registry);
        $personal = $this->policy->evaluate($release, $sessions->listDeviceVersionsForManager($manager_id));
        $subject = (string)$release['version_code'];
        $state = (new ManagerNoticeState($this->registry))->get($manager_id, self::NOTICE_KEY);
        $sameRelease = (string)($state['subject'] ?? '') === $subject;
        $suppressed = !$personal['critical'] && $sameRelease
            && (!empty($state['is_snoozed']) || !empty($state['dismissed_at']));

        $payload = [
            'success' => true,
            'available' => count($personal['outdated']) > 0,
            'visible' => count($personal['outdated']) > 0 && !$suppressed,
            'release' => $release,
            'devices' => $personal['outdated'],
            'known_total' => (int)$personal['known_total'],
            'outdated_total' => count($personal['outdated']),
            'critical' => (bool)$personal['critical'],
            'can_dismiss' => !(bool)$personal['critical'],
        ];

        if ($is_admin) {
            $aggregate = $this->policy->evaluate($release, $sessions->getDeviceVersionSummary());
            $payload['admin_summary'] = [
                'known_total' => (int)$aggregate['known_total'],
                'outdated_total' => count($aggregate['outdated']),
                'critical' => (bool)$aggregate['critical'],
            ];
        }

        return $payload;
    }

    public function defer(int $manager_id, string $action, int $target_version_code): array
    {
        $release = $this->catalog->latest();
        if ($release === [] || (int)$release['version_code'] !== $target_version_code) {
            return ['success' => false, 'error' => 'release_changed'];
        }

        $sessions = new AppSession($this->registry);
        $personal = $this->policy->evaluate($release, $sessions->listDeviceVersionsForManager($manager_id));
        if (count($personal['outdated']) === 0) {
            return ['success' => true, 'visible' => false];
        }

        $state = new ManagerNoticeState($this->registry);
        if ($action === 'snooze') {
            $state->snooze($manager_id, self::NOTICE_KEY, (string)$target_version_code, 7);
            return ['success' => true, 'visible' => false, 'message' => 'Напомним через 7 дней.'];
        }
        if ($action === 'dismiss' && empty($personal['critical'])) {
            $state->dismissRelease($manager_id, self::NOTICE_KEY, (string)$target_version_code);
            return ['success' => true, 'visible' => false, 'message' => 'Карточка скрыта до следующей версии.'];
        }

        return ['success' => false, 'error' => $action === 'dismiss' ? 'critical_update' : 'invalid_action'];
    }
}
