<?php

namespace App\Services;

use App\Models\Device;
use App\Models\Outbox;

class DeviceRotationService
{
    /**
     * Get the next device from the rotation pool
     *
     * @param array $deviceSenders Array of device sender IDs
     * @param string|null $lastUsedSender The last used sender ID
     * @return string|null The next sender ID to use
     */
    public static function getNextDevice($deviceSenders, $lastUsedSender = null)
    {
        if (empty($deviceSenders) || !is_array($deviceSenders)) {
            return null;
        }

        // If no last used sender, return the first one
        if (empty($lastUsedSender)) {
            return $deviceSenders[0];
        }

        // Find the index of the last used sender
        $currentIndex = array_search($lastUsedSender, $deviceSenders);

        // If not found or last in array, start from beginning
        if ($currentIndex === false || $currentIndex >= count($deviceSenders) - 1) {
            return $deviceSenders[0];
        }

        // Return next device
        return $deviceSenders[$currentIndex + 1];
    }

    /**
     * Get available online devices for rotation
     *
     * @param int $userId
     * @param array|null $specificDevices Optional array of specific device senders to use
     * @return array Array of device sender IDs
     */
    public static function getAvailableDevices($userId, $specificDevices = null)
    {
        $query = Device::where('user_id', $userId)
            ->where('status', 'ONLINE');

        if (!empty($specificDevices) && is_array($specificDevices)) {
            $query->whereIn('sender', $specificDevices);
        }

        return $query->pluck('sender')->toArray();
    }

    /**
     * Distribute messages across multiple devices
     *
     * @param array $receivers Array of receiver phone numbers
     * @param array $deviceSenders Array of device sender IDs to rotate
     * @return array Grouped receivers by device
     */
    public static function distributeMessages($receivers, $deviceSenders)
    {
        if (empty($deviceSenders)) {
            return [];
        }

        $distribution = [];
        $deviceCount = count($deviceSenders);
        
        foreach ($receivers as $index => $receiver) {
            $deviceIndex = $index % $deviceCount;
            $device = $deviceSenders[$deviceIndex];
            
            if (!isset($distribution[$device])) {
                $distribution[$device] = [];
            }
            
            $distribution[$device][] = $receiver;
        }

        return $distribution;
    }

    /**
     * Get device rotation statistics
     *
     * @param int $userId
     * @param string $jobId
     * @return array Statistics about device usage
     */
    public static function getRotationStats($userId, $jobId)
    {
        $outboxes = Outbox::where('user_id', $userId)
            ->where('job_id', $jobId)
            ->where('use_device_rotation', true)
            ->get();

        $stats = [];
        foreach ($outboxes as $outbox) {
            $device = $outbox->current_rotation_device ?? $outbox->sender;
            
            if (!isset($stats[$device])) {
                $stats[$device] = [
                    'total' => 0,
                    'sent' => 0,
                    'failed' => 0,
                    'pending' => 0,
                ];
            }

            $stats[$device]['total']++;
            
            if ($outbox->status === 'SENT') {
                $stats[$device]['sent']++;
            } elseif (str_starts_with($outbox->status, 'FAILED')) {
                $stats[$device]['failed']++;
            } else {
                $stats[$device]['pending']++;
            }
        }

        return $stats;
    }

    /**
     * Check device health and availability
     *
     * @param string $sender Device sender ID
     * @return bool Whether device is healthy and available
     */
    public static function isDeviceHealthy($sender)
    {
        $device = Device::where('sender', $sender)->first();

        if (!$device) {
            return false;
        }

        // Check if device is online
        if ($device->status !== 'ONLINE') {
            return false;
        }

        // Check if device is not busy
        if (!empty($device->busy) && $device->busy) {
            return false;
        }

        return true;
    }

    /**
     * Balance load across devices by checking their current workload
     *
     * @param array $deviceSenders
     * @return string Device with lowest workload
     */
    public static function getLeastBusyDevice($deviceSenders)
    {
        if (empty($deviceSenders)) {
            return null;
        }

        $workloads = [];
        
        foreach ($deviceSenders as $sender) {
            $pendingCount = Outbox::where('sender', $sender)
                ->where('status', 'PENDING')
                ->count();
                
            $workloads[$sender] = $pendingCount;
        }

        // Return device with minimum workload
        asort($workloads);
        return array_key_first($workloads);
    }
}
