<?php
namespace EasyChat\Library\Messenger;

 
final class WhatsAppPersonalPresenter {
    private $registry;

    public function __construct($registry) {
        $this->registry = $registry;
    }

    public function build(array $channel): array {
        $settings = json_decode((string)($channel['settings_json'] ?? '{}'), true);
        $settings = is_array($settings) ? $settings : [];
        $auth = (new WhatsAppPersonalAuthService($this->registry))->state($channel);
        $cron = $this->cronState(is_array($settings['worker'] ?? null) ? $settings['worker'] : []);
        $connected = (string)($auth['status'] ?? '') === 'connected';
        $enabled = $connected && (string)($channel['status'] ?? '') === 'active';
        $profile = is_array($settings['account_profile'] ?? null) ? $settings['account_profile'] : [];
        $worker = is_array($settings['worker'] ?? null) ? $settings['worker'] : [];
        $attention = $this->attention($connected, $enabled, $cron, $worker, $channel);

        return [
            'channel_id' => (int)($channel['channel_id'] ?? 0),
            'ui_state' => $connected ? 'dashboard' : 'wizard',
            'step' => $cron['ready'] ? 2 : 1,
            'connected' => $connected,
            'enabled' => $enabled,
            'account' => [
                'display_name' => (string)($profile['display_name'] ?? $channel['bot_name'] ?? 'Личный WhatsApp'),
                'phone' => $this->maskedPhone((string)($profile['pn_jid'] ?? '')),
            ],
            'auth' => $auth,
            'cron' => $cron,
            'attention' => $attention,
            'worker' => [
                'status' => (string)($worker['status'] ?? ''),
                'last_success_at' => max(0, (int)($worker['last_success_at'] ?? 0)),
                'last_error_code' => (string)($worker['last_error_code'] ?? $channel['last_error'] ?? ''),
            ],
        ];
    }

    private function cronState(array $worker): array {
        $now = time();
        $last = max(0, (int)($worker['cron_last_seen_at'] ?? 0));
        $raw = is_array($worker['cron_recent_runs'] ?? null) ? $worker['cron_recent_runs'] : [];
        $runs = array_values(array_unique(array_filter(array_map('intval', $raw), static function (int $value) use ($now): bool {
            return $value > 0 && $value <= $now + 60 && $value >= $now - 21600;
        })));
        sort($runs);
        $history = [];
        foreach ($runs as $index => $timestamp) {
            $history[] = [
                'run_id' => 'wa' . $index,
                'started_at' => $timestamp,
                'finished_at' => $timestamp,
                'status' => 'success',
                'exit_code' => 0,
            ];
        }
        $analyzed = (new CronCadenceAnalyzer())->analyze($history, $now, [
            'first_seen_at' => max(0, (int)($worker['cron_first_seen_at'] ?? ($runs[0] ?? 0))),
            'quarters' => $this->cadenceBuckets($worker['cron_quarter_runs'] ?? []),
            'hours' => $this->cadenceBuckets($worker['cron_hourly_runs'] ?? []),
        ]);
        $state = (string)($analyzed['state'] ?? 'missing');
        $diagnosis = (string)($analyzed['diagnosis'] ?? '');

        if (!empty($analyzed['confirmed'])) {
             
             
             
            $analyzed['requires_attention'] = false;
            return $this->cronPayload('ready', true, 'Расписание подтверждено', 'Запуски идут каждую минуту.', $analyzed, $last);
        }
        if (in_array($state, ['observed_once', 'verifying', 'running'], true)) {
            $title = $state === 'verifying' ? 'Почти готово' : 'Видим первый запуск';
            $detail = $state === 'verifying'
                ? 'Следующий минутный запуск подтвердит расписание.'
                : 'Подождите ещё до двух минут — EasyChat подтвердит частоту.';
            return $this->cronPayload('observing', false, $title, $detail, $analyzed, $last);
        }
        if ($state === 'missing') {
            return $this->cronPayload('missing', false, 'Проверим после запуска', 'Добавьте задачу и подождите до двух минут.', $analyzed, $last);
        }
        if ($state === 'stale') {
            return $this->cronPayload('stale', false, 'Cron перестал запускаться', 'Проверьте, что задача включена и выполняется каждую минуту.', $analyzed, $last);
        }

        $detail = 'Поставьте выполнение каждую минуту: * * * * *.';
        if ($diagnosis === 'fixed_interval') {
            $minutes = max(2, (int)round(max(0, (int)($analyzed['observed_interval_seconds'] ?? 0)) / 60));
            $detail = 'Похоже, задача запускается каждые ' . $minutes . ' мин. Укажите * * * * *.';
        } elseif ($state === 'limited_hours') {
            $detail = 'Запуски идут только в отдельные часы. Проверьте расписание * * * * *.';
        } elseif ($state === 'low_coverage') {
            $detail = 'Cron часто пропускает запуски. Проверьте расписание * * * * *.';
        } elseif ($state === 'too_frequent') {
            $detail = 'Используйте расписание ровно один раз в минуту.';
        }
        return $this->cronPayload('wrong_schedule', false, 'Неверное расписание', $detail, $analyzed, $last);
    }

    private function cronPayload(string $state, bool $ready, string $title, string $detail, array $analyzed, int $last): array {
        return [
            'state' => $state,
            'ready' => $ready,
            'title' => $title,
            'detail' => $detail,
            'observed_runs' => min(3, max(0, (int)($analyzed['observed_runs'] ?? 0))),
            'last_seen_at' => $last,
            'requires_attention' => !empty($analyzed['requires_attention']),
            'diagnosis' => (string)($analyzed['diagnosis'] ?? ''),
        ];
    }

    private function attention(bool $connected, bool $enabled, array $cron, array $worker, array $channel): array {
        if ($connected && (string)($worker['status'] ?? '') === 'authorization_required') {
            return [
                'visible' => true,
                'level' => 'danger',
                'title' => 'Нужно войти снова',
                'detail' => 'WhatsApp отозвал companion-сессию.',
                'source' => 'authorization',
            ];
        }
        if ($connected && $enabled && (
            !empty($cron['requires_attention'])
            || in_array((string)($cron['state'] ?? ''), ['missing', 'stale', 'wrong_schedule'], true)
        )) {
            return ['visible' => true, 'level' => 'warning', 'title' => $cron['title'], 'detail' => $cron['detail'], 'source' => 'cron'];
        }
        if ($enabled && trim((string)($channel['last_error'] ?? '')) !== '') {
            return ['visible' => true, 'level' => 'warning', 'title' => 'Доставка восстанавливается', 'detail' => 'EasyChat повторит обработку автоматически.'];
        }
        return ['visible' => false, 'level' => 'none', 'title' => '', 'detail' => ''];
    }

    private function cadenceBuckets($buckets): array {
        if (!is_array($buckets)) {
            return [];
        }
        $result = [];
        foreach ($buckets as $bucket) {
            if (!is_array($bucket) || max(0, (int)($bucket[0] ?? 0)) <= 0) {
                continue;
            }
            $runs = max(0, (int)($bucket[1] ?? 0));
            $result[] = [max(0, (int)$bucket[0]), $runs, $runs, 0];
        }
        return $result;
    }

    private function maskedPhone(string $jid): string {
        if (preg_match('/^([1-9][0-9]{5,19})@s\.whatsapp\.net$/D', strtolower(trim($jid)), $match) !== 1) {
            return '';
        }
        $digits = $match[1];
        return '+' . substr($digits, 0, min(3, max(1, strlen($digits) - 6))) . ' ••• ••-' . substr($digits, -4);
    }
}
