<?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 ActiveCampaign related API calls.
 * Handles fetching tags, lists, and custom fields for dynamic field loading.
 */
final class ActiveCampaignController
{
    /**
     * Get tags from ActiveCampaign.
     */
    public function tags(Request $request): Response
    {
        $connectionId = (int) $request->get('connection_id');

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

        [$apiUrl, $apiKey] = $this->getCredentials($connectionId);
        if (!$apiUrl || !$apiKey) {
            return Response::error('Invalid connection or missing credentials', 401);
        }

        $response = wp_remote_get($apiUrl . '/api/3/tags?limit=100', [
            'headers' => ['Api-Token' => $apiKey],
            'timeout' => 30,
        ]);

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

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

        if ($statusCode !== 200) {
            return Response::error('ActiveCampaign API error (HTTP ' . $statusCode . ')', $statusCode);
        }

        $tags = [];
        foreach ($body['tags'] ?? [] as $tag) {
            $tags[] = [
                'value' => $tag['id'],
                'label' => $tag['tag'],
            ];
        }

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

    /**
     * Get lists from ActiveCampaign.
     */
    public function lists(Request $request): Response
    {
        $connectionId = (int) $request->get('connection_id');

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

        [$apiUrl, $apiKey] = $this->getCredentials($connectionId);
        if (!$apiUrl || !$apiKey) {
            return Response::error('Invalid connection or missing credentials', 401);
        }

        $response = wp_remote_get($apiUrl . '/api/3/lists?limit=100', [
            'headers' => ['Api-Token' => $apiKey],
            'timeout' => 30,
        ]);

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

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

        if ($statusCode !== 200) {
            return Response::error('ActiveCampaign API error (HTTP ' . $statusCode . ')', $statusCode);
        }

        $lists = [];
        foreach ($body['lists'] ?? [] as $list) {
            $lists[] = [
                'value' => $list['id'],
                'label' => $list['name'],
            ];
        }

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

    /**
     * Get contact fields from ActiveCampaign.
     *
     * Returns standard contact fields (email, first name, etc.) as required/optional
     * columns, followed by any custom fields fetched from the API.
     */
    public function contactFields(Request $request): Response
    {
        $connectionId = (int) $request->get('connection_id');

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

        [$apiUrl, $apiKey] = $this->getCredentials($connectionId);
        if (!$apiUrl || !$apiKey) {
            return Response::error('Invalid connection or missing credentials', 401);
        }

        // Standard contact fields first
        $columns = [
            ['value' => 'email',      'label' => 'Email',      'required' => true],
            ['value' => 'firstName',   'label' => 'First Name'],
            ['value' => 'lastName',    'label' => 'Last Name'],
            ['value' => 'phone',       'label' => 'Phone'],
        ];

        // Fetch custom fields from API
        $response = wp_remote_get($apiUrl . '/api/3/fields?limit=100', [
            'headers' => ['Api-Token' => $apiKey],
            'timeout' => 30,
        ]);

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

            if ($statusCode === 200) {
                foreach ($body['fields'] ?? [] as $field) {
                    $columns[] = [
                        'value' => 'custom_' . $field['id'],
                        'label' => $field['title'],
                    ];
                }
            }
        }

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

    /**
     * Get account fields from ActiveCampaign.
     *
     * Returns standard account fields (name, URL) as required/optional
     * columns, followed by any custom fields fetched from the API.
     */
    public function accountFields(Request $request): Response
    {
        $connectionId = (int) $request->get('connection_id');

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

        [$apiUrl, $apiKey] = $this->getCredentials($connectionId);
        if (!$apiUrl || !$apiKey) {
            return Response::error('Invalid connection or missing credentials', 401);
        }

        // Standard account fields first
        $columns = [
            ['value' => 'name',       'label' => 'Account Name', 'required' => true],
            ['value' => 'accountUrl',  'label' => 'Account URL'],
        ];

        // Fetch custom fields from API
        $response = wp_remote_get($apiUrl . '/api/3/accountCustomFieldMeta?limit=100', [
            'headers' => ['Api-Token' => $apiKey],
            'timeout' => 30,
        ]);

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

            if ($statusCode === 200) {
                foreach ($body['accountCustomFieldMeta'] ?? [] as $field) {
                    $columns[] = [
                        'value' => 'custom_' . $field['id'],
                        'label' => $field['fieldLabel'],
                    ];
                }
            }
        }

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

    /**
     * Get contacts from ActiveCampaign.
     */
    public function contacts(Request $request): Response
    {
        $connectionId = (int) $request->get('connection_id');

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

        [$apiUrl, $apiKey] = $this->getCredentials($connectionId);
        if (!$apiUrl || !$apiKey) {
            return Response::error('Invalid connection or missing credentials', 401);
        }

        $response = wp_remote_get($apiUrl . '/api/3/contacts?limit=100&orders[email]=ASC', [
            'headers' => ['Api-Token' => $apiKey],
            'timeout' => 30,
        ]);

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

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

        if ($statusCode !== 200) {
            return Response::error('ActiveCampaign API error (HTTP ' . $statusCode . ')', $statusCode);
        }

        $contacts = [];
        foreach ($body['contacts'] ?? [] as $contact) {
            $firstName = trim($contact['firstName'] ?? '');
            $lastName  = trim($contact['lastName'] ?? '');
            $email     = trim($contact['email'] ?? '');
            $name      = trim($firstName . ' ' . $lastName);

            $contacts[] = [
                'value' => $contact['id'],
                'label' => $name !== '' ? "{$name} ({$email})" : $email,
            ];
        }

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

    /**
     * Get accounts from ActiveCampaign.
     */
    public function accounts(Request $request): Response
    {
        $connectionId = (int) $request->get('connection_id');

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

        [$apiUrl, $apiKey] = $this->getCredentials($connectionId);
        if (!$apiUrl || !$apiKey) {
            return Response::error('Invalid connection or missing credentials', 401);
        }

        $response = wp_remote_get($apiUrl . '/api/3/accounts?limit=100', [
            'headers' => ['Api-Token' => $apiKey],
            'timeout' => 30,
        ]);

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

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

        if ($statusCode !== 200) {
            return Response::error('ActiveCampaign API error (HTTP ' . $statusCode . ')', $statusCode);
        }

        $accounts = [];
        foreach ($body['accounts'] ?? [] as $account) {
            $accounts[] = [
                'value' => $account['id'],
                'label' => $account['name'],
            ];
        }

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

    /**
     * Get deals from ActiveCampaign.
     */
    public function deals(Request $request): Response
    {
        $connectionId = (int) $request->get('connection_id');

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

        [$apiUrl, $apiKey] = $this->getCredentials($connectionId);
        if (!$apiUrl || !$apiKey) {
            return Response::error('Invalid connection or missing credentials', 401);
        }

        $response = wp_remote_get($apiUrl . '/api/3/deals?limit=100', [
            'headers' => ['Api-Token' => $apiKey],
            'timeout' => 30,
        ]);

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

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

        if ($statusCode !== 200) {
            return Response::error('ActiveCampaign API error (HTTP ' . $statusCode . ')', $statusCode);
        }

        $deals = [];
        foreach ($body['deals'] ?? [] as $deal) {
            $deals[] = [
                'value' => $deal['id'],
                'label' => $deal['title'],
            ];
        }

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

    /**
     * Get API URL and API key from a connection's credentials.
     *
     * @return array{0: string, 1: string} [apiUrl, apiKey]
     */
    private function getCredentials(int $connectionId): array
    {
        $connection = Connection::find($connectionId);
        if (!$connection) {
            return ['', ''];
        }

        $creds = Connection::getCredentials($connection);

        return [
            rtrim($creds['api_url'] ?? '', '/'),
            $creds['api_key'] ?? '',
        ];
    }
}
