<?php

namespace EasyLinkAutomations\HTTP\Controllers\Actions;

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


use EasyLinkAutomations\Actions\Discord\DiscordRequestHelper;
use EasyLinkAutomations\HTTP\Request\Request;
use EasyLinkAutomations\HTTP\Response;
use EasyLinkAutomations\Models\Connection;

/**
 * Controller for Discord remote_select endpoints.
 *
 * Provides guilds, channels, text-only channels, and roles for action config dropdowns.
 */
final class DiscordController
{
    /**
     * Returns the list of guilds (servers) the bot belongs to.
     *
     * Route: discord/guilds
     */
    public function guilds(Request $request): Response
    {
        $connectionId = $request->get('connection_id');
        if (!$connectionId) {
            return Response::error('Connection ID required', 400);
        }

        $authHeaders = Connection::getAuthHeaders((int) $connectionId);
        if (empty($authHeaders)) {
            return Response::error('Invalid connection', 401);
        }

        $response = wp_remote_get(DiscordRequestHelper::url('users/@me/guilds'), [
            'headers' => $authHeaders,
            'timeout' => 30,
        ]);

        if (is_wp_error($response)) {
            return Response::error($response->get_error_message(), 500);
        }

        $code = wp_remote_retrieve_response_code($response);
        $data = DiscordRequestHelper::responseBody($response);

        if ($code !== 200 || !is_array($data)) {
            return Response::error('Failed to fetch guilds: ' . DiscordRequestHelper::failureMessage($code, $data), $code ?: 500);
        }

        $guilds = [];
        foreach ($data as $guild) {
            $guilds[] = [
                'value' => (string) $guild['id'],
                'label' => $guild['name'],
            ];
        }

        return Response::success(['guilds' => $guilds]);
    }

    /**
     * Returns all channels in a guild (all types).
     *
     * Route: discord/channels
     */
    public function channels(Request $request): Response
    {
        $connectionId = $request->get('connection_id');
        $guildId      = $request->get('guild_id');

        if (!$connectionId) {
            return Response::error('Connection ID required', 400);
        }
        if (!$guildId) {
            return Response::error('Guild ID required', 400);
        }

        $authHeaders = Connection::getAuthHeaders((int) $connectionId);
        if (empty($authHeaders)) {
            return Response::error('Invalid connection', 401);
        }

        $response = wp_remote_get(DiscordRequestHelper::url(DiscordRequestHelper::idPath('guilds', (string) $guildId, 'channels')), [
            'headers' => $authHeaders,
            'timeout' => 30,
        ]);

        if (is_wp_error($response)) {
            return Response::error($response->get_error_message(), 500);
        }

        $code = wp_remote_retrieve_response_code($response);
        $data = DiscordRequestHelper::responseBody($response);

        if ($code !== 200 || !is_array($data)) {
            return Response::error('Failed to fetch channels: ' . DiscordRequestHelper::failureMessage($code, $data), $code ?: 500);
        }

        $channels = [];
        foreach ($data as $channel) {
            $channels[] = [
                'value' => (string) $channel['id'],
                'label' => '#' . $channel['name'] . ' (' . $this->channelTypeName((int) $channel['type']) . ')',
            ];
        }

        usort($channels, fn ($a, $b) => strcmp($a['label'], $b['label']));

        return Response::success(['channels' => $channels]);
    }

    /**
     * Returns message-capable guild channels.
     *
     * Route: discord/text-channels
     */
    public function textChannels(Request $request): Response
    {
        $connectionId = $request->get('connection_id');
        $guildId      = $request->get('guild_id');

        if (!$connectionId) {
            return Response::error('Connection ID required', 400);
        }
        if (!$guildId) {
            return Response::error('Guild ID required', 400);
        }

        $authHeaders = Connection::getAuthHeaders((int) $connectionId);
        if (empty($authHeaders)) {
            return Response::error('Invalid connection', 401);
        }

        $response = wp_remote_get(DiscordRequestHelper::url(DiscordRequestHelper::idPath('guilds', (string) $guildId, 'channels')), [
            'headers' => $authHeaders,
            'timeout' => 30,
        ]);

        if (is_wp_error($response)) {
            return Response::error($response->get_error_message(), 500);
        }

        $code = wp_remote_retrieve_response_code($response);
        $data = DiscordRequestHelper::responseBody($response);

        if ($code !== 200 || !is_array($data)) {
            return Response::error('Failed to fetch channels: ' . DiscordRequestHelper::failureMessage($code, $data), $code ?: 500);
        }

        $channels = [];
        foreach ($data as $channel) {
            // Type 0 = text, type 5 = announcement.
            if (in_array((int) $channel['type'], [0, 5], true)) {
                $channels[] = [
                    'value' => (string) $channel['id'],
                    'label' => '#' . $channel['name'],
                ];
            }
        }

        usort($channels, fn ($a, $b) => strcmp($a['label'], $b['label']));

        return Response::success(['channels' => $channels]);
    }

    /**
     * Returns all roles in a guild (excluding @everyone and managed roles).
     *
     * Route: discord/roles
     */
    public function roles(Request $request): Response
    {
        $connectionId = $request->get('connection_id');
        $guildId      = $request->get('guild_id');

        if (!$connectionId) {
            return Response::error('Connection ID required', 400);
        }
        if (!$guildId) {
            return Response::error('Guild ID required', 400);
        }

        $authHeaders = Connection::getAuthHeaders((int) $connectionId);
        if (empty($authHeaders)) {
            return Response::error('Invalid connection', 401);
        }

        $response = wp_remote_get(DiscordRequestHelper::url(DiscordRequestHelper::idPath('guilds', (string) $guildId, 'roles')), [
            'headers' => $authHeaders,
            'timeout' => 30,
        ]);

        if (is_wp_error($response)) {
            return Response::error($response->get_error_message(), 500);
        }

        $code = wp_remote_retrieve_response_code($response);
        $data = DiscordRequestHelper::responseBody($response);

        if ($code !== 200 || !is_array($data)) {
            return Response::error('Failed to fetch roles: ' . DiscordRequestHelper::failureMessage($code, $data), $code ?: 500);
        }

        $roles = [];
        foreach ($data as $role) {
            // Skip @everyone (managed=false check) and bot-managed roles
            if ($role['name'] === '@everyone' || !empty($role['managed'])) {
                continue;
            }
            $roles[] = [
                'value' => (string) $role['id'],
                'label' => $role['name'],
            ];
        }

        usort($roles, fn ($a, $b) => strcmp($a['label'], $b['label']));

        return Response::success(['roles' => $roles]);
    }

    /**
     * Returns a human-readable name for a Discord channel type integer.
     */
    private function channelTypeName(int $type): string
    {
        return match ($type) {
            0       => 'text',
            2       => 'voice',
            4       => 'category',
            5       => 'announcement',
            13      => 'stage',
            15      => 'forum',
            default => 'channel',
        };
    }
}
