<?php

namespace EasyLinkAutomations\Actions\MicrosoftTeams;

if (!defined('ABSPATH')) {
    exit;
}

use EasyLinkAutomations\Models\Connection;

final class MicrosoftTeamsRequestHelper
{
    private const BASE_URL = 'https://graph.microsoft.com';

    public static function request(
        int $connectionId,
        string $method,
        string $path,
        array $body = [],
        array $query = [],
        array $headers = []
    ): array {
        $connection = Connection::find($connectionId);
        if (!$connection || ($connection['platform'] ?? '') !== 'microsoft_teams') {
            return ['success' => false, 'message' => 'Invalid Microsoft Teams connection', 'data' => []];
        }

        $authHeaders = Connection::getAuthHeaders($connectionId);
        if (empty($authHeaders['Authorization']) || $authHeaders['Authorization'] === 'Bearer ') {
            return ['success' => false, 'message' => 'Missing or expired Microsoft Teams access token', 'data' => []];
        }

        $url = self::url($path);
        if ($url === '') {
            return ['success' => false, 'message' => 'Invalid Microsoft Graph request URL', 'data' => []];
        }
        if ($query) {
            $url .= (str_contains($url, '?') ? '&' : '?') . http_build_query($query);
        }

        $args = [
            'method' => strtoupper($method),
            'headers' => array_merge(
                $authHeaders,
                ['Accept' => 'application/json', 'Content-Type' => 'application/json'],
                $headers
            ),
            'timeout' => 30,
        ];
        if ($body) {
            $args['body'] = wp_json_encode($body);
        }

        $response = wp_remote_request($url, $args);
        if (is_wp_error($response)) {
            return ['success' => false, 'message' => 'Microsoft Graph request failed: ' . $response->get_error_message(), 'data' => []];
        }

        $code = (int) wp_remote_retrieve_response_code($response);
        $raw = wp_remote_retrieve_body($response);
        $decoded = $raw === '' ? [] : json_decode($raw, true);
        $data = json_last_error() === JSON_ERROR_NONE ? $decoded : $raw;
        if ($code < 200 || $code >= 300) {
            return ['success' => false, 'message' => self::failureMessage($code, $data), 'data' => $data];
        }

        return ['success' => true, 'message' => 'Microsoft Teams request completed successfully', 'data' => $data];
    }

    public static function listAll(int $connectionId, string $path, array $query = [], int $limit = 0): array
    {
        $items = [];
        $next = $path;
        $nextQuery = $query;

        while ($next !== '') {
            $result = self::request($connectionId, 'GET', $next, [], $nextQuery);
            if (!$result['success']) {
                return $result;
            }

            $payload = is_array($result['data']) ? $result['data'] : [];
            foreach (is_array($payload['value'] ?? null) ? $payload['value'] : [] as $item) {
                $items[] = $item;
                if ($limit > 0 && count($items) >= $limit) {
                    return ['success' => true, 'message' => $result['message'], 'data' => array_slice($items, 0, $limit)];
                }
            }

            $next = is_string($payload['@odata.nextLink'] ?? null) ? $payload['@odata.nextLink'] : '';
            $nextQuery = [];
        }

        return ['success' => true, 'message' => 'Microsoft Teams request completed successfully', 'data' => $items];
    }

    public static function id(mixed $value): string
    {
        return rawurlencode(trim((string) $value));
    }

    public static function positiveLimit(mixed $value, int $maximum = 1000): int
    {
        return max(1, min($maximum, (int) $value));
    }

    private static function url(string $path): string
    {
        if (str_starts_with($path, self::BASE_URL . '/')) {
            return $path;
        }
        if (!str_starts_with($path, '/')) {
            $path = '/' . $path;
        }

        return self::BASE_URL . $path;
    }

    private static function failureMessage(int $code, mixed $data): string
    {
        $message = '';
        $errorCode = '';
        if (is_array($data)) {
            $error = $data['error'] ?? [];
            if (is_array($error)) {
                $message = (string) ($error['message'] ?? '');
                $errorCode = (string) ($error['code'] ?? '');
            } elseif (is_string($error)) {
                $message = $error;
            }
        } elseif (is_string($data)) {
            $message = $data;
        }

        $details = $errorCode !== '' ? $errorCode : '';
        if ($message !== '') {
            $details .= ($details !== '' ? ': ' : '') . $message;
        }

        return 'Microsoft Graph API error (HTTP ' . $code . ')' . ($details !== '' ? ': ' . $details : '');
    }
}
