<?php

namespace EasyLinkAutomations\HTTP\Controllers\Actions;

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

use EasyLinkAutomations\HTTP\Request\Request;
use EasyLinkAutomations\HTTP\Response;
use EasyLinkAutomations\Models\Connection;

/**
 * Controller for Slack related API calls.
 * Handles fetching channels and users for dynamic field loading.
 */
final class SlackController
{
    private const API_BASE = 'https://slack.com/api';

    /**
     * Get list of channels accessible by the connection.
     */
    public function channels(Request $request): Response
    {
        $connectionId = (int) $request->get('connection_id');

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

        $token = Connection::getAccessToken($connectionId);
        if (empty($token)) {
            return Response::error('Invalid connection or token expired', 401);
        }

        $result = $this->fetchPaginatedCollection($token, 'conversations.list', [
            'types'            => 'public_channel,private_channel',
            'exclude_archived' => 'true',
            'limit'            => 200,
        ], 'channels');
        if (empty($result['ok'])) {
            return Response::error($result['message']);
        }

        $channels = [];
        foreach ($result['items'] as $channel) {
            $prefix = !empty($channel['is_private']) ? '#' : '#';
            $channels[] = [
                'value' => $channel['id'],
                'label' => $prefix . ($channel['name'] ?? $channel['id']),
            ];
        }

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

    /**
     * Get profile fields available for updating a Slack user profile.
     *
     * Returns standard Slack profile fields plus any custom fields
     * from the workspace via team.profile.get API.
     */
    public function profileFields(Request $request): Response
    {
        $connectionId = (int) $request->get('connection_id');

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

        $token = Connection::getAccessToken($connectionId);
        if (empty($token)) {
            return Response::error('Invalid connection or token expired', 401);
        }

        // Standard Slack profile fields
        $columns = [
            ['value' => 'first_name',   'label' => 'First Name'],
            ['value' => 'last_name',    'label' => 'Last Name'],
            ['value' => 'email',        'label' => 'Email',        'required' => true],
            ['value' => 'display_name', 'label' => 'Display Name'],
            ['value' => 'status_text',  'label' => 'Status Text'],
            ['value' => 'status_emoji', 'label' => 'Status Emoji'],
            ['value' => 'title',        'label' => 'Title'],
            ['value' => 'phone',        'label' => 'Phone'],
        ];

        // Try to fetch custom profile fields from team.profile.get
        $url = self::API_BASE . '/team.profile.get';
        $response = wp_remote_get($url, [
            'headers' => ['Authorization' => 'Bearer ' . $token],
            'timeout' => 15,
        ]);

        if (!is_wp_error($response)) {
            $body = json_decode(wp_remote_retrieve_body($response), true);

            if (!empty($body['ok']) && !empty($body['profile']['fields'])) {
                foreach ($body['profile']['fields'] as $field) {
                    $fieldId    = $field['id'] ?? '';
                    $fieldLabel = $field['label'] ?? '';

                    if (empty($fieldId) || empty($fieldLabel)) {
                        continue;
                    }

                    // Custom fields use Xf-prefixed IDs
                    if (strpos($fieldId, 'Xf') === 0) {
                        $columns[] = [
                            'value' => $fieldId,
                            'label' => $fieldLabel,
                        ];
                    }
                }
            }
        }

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

    /**
     * Get list of users in the workspace.
     */
    public function users(Request $request): Response
    {
        $connectionId = (int) $request->get('connection_id');

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

        $token = Connection::getAccessToken($connectionId);
        if (empty($token)) {
            return Response::error('Invalid connection or token expired', 401);
        }

        $result = $this->fetchPaginatedCollection($token, 'users.list', [
            'limit' => 200,
        ], 'members');
        if (empty($result['ok'])) {
            return Response::error($result['message']);
        }

        $users = [];
        foreach ($result['items'] as $member) {
            if (!empty($member['deleted']) || !empty($member['is_bot']) || ($member['id'] ?? '') === 'USLACKBOT') {
                continue;
            }

            $displayName = $member['profile']['real_name'] ?? $member['name'] ?? $member['id'];
            $users[] = [
                'value' => $member['id'],
                'label' => $displayName . ' (@' . ($member['name'] ?? '') . ')',
            ];
        }

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

    /**
     * Get list of user groups in the workspace.
     */
    public function usergroups(Request $request): Response
    {
        $connectionId = (int) $request->get('connection_id');

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

        $token = Connection::getAccessToken($connectionId);
        if (empty($token)) {
            return Response::error('Invalid connection or token expired', 401);
        }

        $url = self::API_BASE . '/usergroups.list?' . http_build_query([
            'include_disabled' => 'false',
        ]);

        $response = wp_remote_get($url, [
            'headers' => ['Authorization' => 'Bearer ' . $token],
            'timeout' => 30,
        ]);

        if (is_wp_error($response)) {
            return Response::error('Failed to fetch user groups: ' . $response->get_error_message());
        }

        $body = json_decode(wp_remote_retrieve_body($response), true);

        if (empty($body['ok'])) {
            return Response::error('Slack API error: ' . ($body['error'] ?? 'Unknown error'));
        }

        $usergroups = [];
        foreach ($body['usergroups'] ?? [] as $group) {
            $usergroups[] = [
                'value' => $group['id'],
                'label' => ($group['name'] ?? $group['id']) . ' (@' . ($group['handle'] ?? '') . ')',
            ];
        }

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

    /**
     * Fetch all pages for Slack endpoints that use response_metadata.next_cursor.
     */
    private function fetchPaginatedCollection(string $token, string $method, array $query, string $itemsKey): array
    {
        $items  = [];
        $cursor = '';

        do {
            if ($cursor !== '') {
                $query['cursor'] = $cursor;
            } else {
                unset($query['cursor']);
            }

            $url = self::API_BASE . '/' . $method . '?' . http_build_query($query);
            $response = wp_remote_get($url, [
                'headers' => ['Authorization' => 'Bearer ' . $token],
                'timeout' => 30,
            ]);

            if (is_wp_error($response)) {
                return ['ok' => false, 'message' => 'Failed to fetch Slack data: ' . $response->get_error_message()];
            }

            $body = json_decode(wp_remote_retrieve_body($response), true);
            if (empty($body['ok'])) {
                return ['ok' => false, 'message' => 'Slack API error: ' . ($body['error'] ?? 'Unknown error')];
            }

            $items = array_merge($items, $body[$itemsKey] ?? []);
            $cursor = (string) ($body['response_metadata']['next_cursor'] ?? '');
        } while ($cursor !== '');

        return ['ok' => true, 'items' => $items];
    }
}
