<?php

namespace WPUltimateSecurity\UltimateSecurity\Modules\Authentication\LoginNotifications;

use WPUltimateSecurity\UltimateSecurity\Support\Helpers\Utils;
use WPUltimateSecurity\UltimateSecurity\Support\Helpers\DateHelper;
use WPUltimateSecurity\UltimateSecurity\Modules\Authentication\LoginNotifications;

/**
 * Digest Service for Login Notifications
 *
 * Compiles login event data into statistics for daily and weekly digest emails.
 */
class DigestService
{
    /**
     * Compile daily statistics from events
     *
     * @param array $events Array of logged events
     * @return array Compiled statistics
     */
    public static function compile_daily_stats(array $events): array
    {
        $stats = [
            'total_attempts' => 0,
            'successful_logins' => 0,
            'failed_attempts' => 0,
            'lockouts' => 0,
            'unique_ips' => [],
            'unique_users' => [],
            'top_attacking_ips' => [],
            'targeted_usernames' => [],
            'locked_accounts' => [],
            'new_ip_logins' => 0,
        ];

        $ip_attempts = [];
        $username_attempts = [];

        foreach ($events as $event) {
            $type = $event['type'] ?? '';
            $data = $event['data'] ?? [];

            switch ($type) {
                case 'failed_login':
                    $stats['failed_attempts']++;
                    $stats['total_attempts']++;

                    $ip = $data['ip'] ?? '';
                    $username = $data['username'] ?? '';

                    if ($ip) {
                        $stats['unique_ips'][$ip] = true;
                        $ip_attempts[$ip] = ($ip_attempts[$ip] ?? 0) + 1;
                    }

                    if ($username) {
                        $username_attempts[$username] = ($username_attempts[$username] ?? 0) + 1;
                    }
                    break;

                case 'successful_login':
                    $stats['successful_logins']++;
                    $stats['total_attempts']++;

                    $ip = $data['ip'] ?? '';
                    $user_id = $data['user_id'] ?? 0;

                    if ($ip) {
                        $stats['unique_ips'][$ip] = true;
                    }

                    if ($user_id) {
                        $stats['unique_users'][$user_id] = true;
                    }
                    break;

                case 'lockout':
                    $stats['lockouts']++;
                    $username = $data['username'] ?? '';
                    if ($username && !in_array($username, $stats['locked_accounts'], true)) {
                        $stats['locked_accounts'][] = $username;
                    }
                    break;

                case 'new_ip_login':
                    $stats['new_ip_logins']++;
                    break;
            }
        }

        // Sort attacking IPs by count
        arsort($ip_attempts);
        $stats['top_attacking_ips'] = array_slice(
            array_map(function ($ip, $count) {
                return [
                    'ip' => $ip,
                    'count' => $count,
                    'location' => self::get_ip_location($ip),
                ];
            }, array_keys($ip_attempts), array_values($ip_attempts)),
            0,
            10
        );

        // Sort targeted usernames by count
        arsort($username_attempts);
        $stats['targeted_usernames'] = array_slice(
            array_map(function ($username, $count) {
                return [
                    'username' => $username,
                    'count' => $count,
                ];
            }, array_keys($username_attempts), array_values($username_attempts)),
            0,
            10
        );

        // Convert unique arrays to counts
        $stats['unique_ips'] = count($stats['unique_ips']);
        $stats['unique_users'] = count($stats['unique_users']);

        return $stats;
    }

    /**
     * Compile weekly statistics from events
     *
     * @param array $events Array of logged events
     * @return array Compiled statistics
     */
    public static function compile_weekly_stats(array $events): array
    {
        $stats = [
            'total_attempts' => 0,
            'successful_logins' => 0,
            'failed_attempts' => 0,
            'lockouts' => 0,
            'unique_ips' => [],
            'unique_users' => [],
            'top_attacking_ips' => [],
            'targeted_usernames' => [],
            'locked_accounts' => [],
            'new_ip_logins' => 0,
            'ips_blocked' => 0,
            'daily_breakdown' => [],
        ];

        $ip_attempts = [];
        $username_attempts = [];
        $daily_stats = [];

        // Initialize daily breakdown for the past 7 days
        for ($i = 6; $i >= 0; $i--) {
            $date = DateHelper::subtract(time(), "{$i} days", DateHelper::DATE_FORMAT);
            $daily_stats[$date] = [
                'success' => 0,
                'failed' => 0,
            ];
        }

        foreach ($events as $event) {
            $type = $event['type'] ?? '';
            $data = $event['data'] ?? [];
            $timestamp = $event['timestamp'] ?? time();
            $date = DateHelper::format($timestamp, DateHelper::DATE_FORMAT);

            switch ($type) {
                case 'failed_login':
                    $stats['failed_attempts']++;
                    $stats['total_attempts']++;

                    if (isset($daily_stats[$date])) {
                        $daily_stats[$date]['failed']++;
                    }

                    $ip = $data['ip'] ?? '';
                    $username = $data['username'] ?? '';

                    if ($ip) {
                        $stats['unique_ips'][$ip] = true;
                        $ip_attempts[$ip] = ($ip_attempts[$ip] ?? 0) + 1;
                    }

                    if ($username) {
                        $username_attempts[$username] = ($username_attempts[$username] ?? 0) + 1;
                    }
                    break;

                case 'successful_login':
                    $stats['successful_logins']++;
                    $stats['total_attempts']++;

                    if (isset($daily_stats[$date])) {
                        $daily_stats[$date]['success']++;
                    }

                    $ip = $data['ip'] ?? '';
                    $user_id = $data['user_id'] ?? 0;

                    if ($ip) {
                        $stats['unique_ips'][$ip] = true;
                    }

                    if ($user_id) {
                        $stats['unique_users'][$user_id] = true;
                    }
                    break;

                case 'lockout':
                    $stats['lockouts']++;
                    $username = $data['username'] ?? '';
                    if ($username && !in_array($username, $stats['locked_accounts'], true)) {
                        $stats['locked_accounts'][] = $username;
                    }
                    break;

                case 'new_ip_login':
                    $stats['new_ip_logins']++;
                    break;

                case 'ip_blocked':
                    $stats['ips_blocked']++;
                    break;
            }
        }

        // Sort attacking IPs by count
        arsort($ip_attempts);
        $stats['top_attacking_ips'] = array_map(function ($ip, $count) {
            return [
                'ip' => $ip,
                'count' => $count,
                'location' => self::get_ip_location($ip),
            ];
        }, array_keys($ip_attempts), array_values($ip_attempts));

        // Sort targeted usernames by count
        arsort($username_attempts);
        $stats['targeted_usernames'] = array_slice(
            array_map(function ($username, $count) {
                return [
                    'username' => $username,
                    'count' => $count,
                ];
            }, array_keys($username_attempts), array_values($username_attempts)),
            0,
            10
        );

        // Convert unique arrays to counts
        $stats['unique_ips'] = count($stats['unique_ips']);
        $stats['unique_users'] = count($stats['unique_users']);

        // Format daily breakdown with day names
        $stats['daily_breakdown'] = [];
        foreach ($daily_stats as $date => $day_stats) {
            $day_name = DateHelper::format($date, 'l, M j');
            $stats['daily_breakdown'][$day_name] = $day_stats;
        }

        return $stats;
    }

    /**
     * Get location string for an IP
     *
     * @param string $ip IP address
     * @return string Location string
     */
    protected static function get_ip_location(string $ip): string
    {
        $geo = LoginNotifications::get_geolocation($ip);

        if (empty($geo)) {
            return '';
        }

        $parts = array_filter([
            $geo['city'] ?? '',
            $geo['country'] ?? '',
        ]);

        return implode(', ', $parts);
    }

    /**
     * Get summary statistics for a time period
     *
     * @param int $since Timestamp to start from
     * @return array Summary statistics
     */
    public static function get_summary_stats(int $since): array
    {
        $events = LoginNotifications::get_events_since($since);

        if (empty($events)) {
            return [
                'total_events' => 0,
                'failed_logins' => 0,
                'successful_logins' => 0,
                'lockouts' => 0,
                'unique_ips' => 0,
            ];
        }

        $failed = 0;
        $success = 0;
        $lockouts = 0;
        $ips = [];

        foreach ($events as $event) {
            $type = $event['type'] ?? '';
            $data = $event['data'] ?? [];

            switch ($type) {
                case 'failed_login':
                    $failed++;
                    if (!empty($data['ip'])) {
                        $ips[$data['ip']] = true;
                    }
                    break;

                case 'successful_login':
                    $success++;
                    if (!empty($data['ip'])) {
                        $ips[$data['ip']] = true;
                    }
                    break;

                case 'lockout':
                    $lockouts++;
                    break;
            }
        }

        return [
            'total_events' => count($events),
            'failed_logins' => $failed,
            'successful_logins' => $success,
            'lockouts' => $lockouts,
            'unique_ips' => count($ips),
        ];
    }

    /**
     * Get recent activity for the dashboard
     *
     * @param int $limit Maximum number of events to return
     * @return array Recent events formatted for display
     */
    public static function get_recent_activity(int $limit = 20): array
    {
        $events = LoginNotifications::get_recent_notifications($limit);
        $formatted = [];

        foreach ($events as $event) {
            $type = $event['type'] ?? '';
            $data = $event['data'] ?? [];
            $timestamp = $event['timestamp'] ?? time();

            $formatted[] = [
                'type' => $type,
                'type_label' => self::get_event_type_label($type),
                'icon' => self::get_event_icon($type),
                'severity' => self::get_event_severity($type),
                'ip' => $data['ip'] ?? '',
                'username' => $data['username'] ?? '',
                'user_id' => $data['user_id'] ?? 0,
                'timestamp' => $timestamp,
                'time_ago' => DateHelper::humanDiff($timestamp),
                'formatted_time' => DateHelper::format($timestamp),
            ];
        }

        return $formatted;
    }

    /**
     * Get human-readable label for event type
     *
     * @param string $type Event type
     * @return string Human-readable label
     */
    protected static function get_event_type_label(string $type): string
    {
        $labels = [
            'failed_login' => __('Failed Login', 'ultimate-security'),
            'successful_login' => __('Successful Login', 'ultimate-security'),
            'lockout' => __('Account Lockout', 'ultimate-security'),
            'new_ip_login' => __('New IP Login', 'ultimate-security'),
            'new_device_login' => __('New Device Login', 'ultimate-security'),
            'ip_blocked' => __('IP Blocked', 'ultimate-security'),
        ];

        return $labels[$type] ?? ucfirst(str_replace('_', ' ', $type));
    }

    /**
     * Get icon class for event type
     *
     * @param string $type Event type
     * @return string Icon identifier
     */
    protected static function get_event_icon(string $type): string
    {
        $icons = [
            'failed_login' => 'warning',
            'successful_login' => 'success',
            'lockout' => 'error',
            'new_ip_login' => 'info',
            'new_device_login' => 'info',
            'ip_blocked' => 'error',
        ];

        return $icons[$type] ?? 'info';
    }

    /**
     * Get severity for event type
     *
     * @param string $type Event type
     * @return string Severity level
     */
    protected static function get_event_severity(string $type): string
    {
        $severities = [
            'failed_login' => 'warning',
            'successful_login' => 'low',
            'lockout' => 'high',
            'new_ip_login' => 'medium',
            'new_device_login' => 'medium',
            'ip_blocked' => 'high',
        ];

        return $severities[$type] ?? 'low';
    }

    /**
     * Get human-readable time ago string
     *
     * @param int $timestamp Unix timestamp
     * @return string Time ago string
     * @deprecated Use DateHelper::humanDiff() instead
     */
    protected static function get_time_ago(int $timestamp): string
    {
        return DateHelper::humanDiff($timestamp);
    }
}
