<?php
// Exit if accessed directly.
if (! defined('ABSPATH')) {
    exit;
}

require_once INTEGRAZO_WCZO_PLUGIN_DIR . 'src/products/zoho_campaign/util.php';

if (! class_exists('INTEGRAZO_WCZO_Zoho_Campaigns')) {
    /**
     * Minimal Zoho Campaigns API v1.1 client for WP.
     * Mirrors your CRM client style: token refresh + retry on 401, WP HTTP, DC-aware.
     */
    class INTEGRAZO_WCZO_Zoho_Campaigns
    {

        /** @var string|null */
        public $refresh_token;

        /** @var string|null */
        public $access_token;

        /**
         * Expected values (normalized internally): 'zoho.com','zoho.in','zoho.eu','zoho.com.au','zoho.jp','zoho.com.cn'
         * Anything else falls back to 'zoho.com'.
         * @var string
         */
        public $data_center;

        /** @var int|string|null */
        public $account_id;

        public function __construct($account_details = [])
        {
            $this->refresh_token = $account_details['account_data']['refresh_token'] ?? null;
            $this->data_center   = $account_details['data_center'] ?? 'zoho.com'; // default to US
            $this->account_id    = $account_details['id'] ?? null;
            $this->access_token  = INTEGRAZO_WCZO_Util::getAccessToken($this->account_id);
        }

        /**
         * Resolve Accounts (OAuth) + Campaigns API hosts for current DC.
         *
         * @return array{accounts_base:string, campaigns_base:string}
         */
        private function resolve_endpoints(): array
        {
            $dc = strtolower(trim((string) $this->data_center));

            switch ($dc) {
                case 'zoho.in':
                    return [
                        'accounts_base'  => 'https://accounts.zoho.in',
                        'campaigns_base' => 'https://campaigns.zoho.in',
                    ];
                case 'zoho.eu':
                    return [
                        'accounts_base'  => 'https://accounts.zoho.eu',
                        'campaigns_base' => 'https://campaigns.zoho.eu',
                    ];
                case 'zoho.com.au':
                    return [
                        'accounts_base'  => 'https://accounts.zoho.com.au',
                        'campaigns_base' => 'https://campaigns.zoho.com.au',
                    ];
                case 'zoho.jp':
                    return [
                        'accounts_base'  => 'https://accounts.zoho.jp',
                        'campaigns_base' => 'https://campaigns.zoho.jp',
                    ];
                case 'zoho.com.cn':
                    return [
                        'accounts_base'  => 'https://accounts.zoho.com.cn',
                        'campaigns_base' => 'https://campaigns.zoho.com.cn',
                    ];
                case 'zoho.com':
                default:
                    return [
                        'accounts_base'  => 'https://accounts.zoho.com',
                        'campaigns_base' => 'https://campaigns.zoho.com',
                    ];
            }
        }
        public function record_action_options(): array
        {
            return array();
        }
        public function common_note(): string
        {
            return 'Note: If Double Opt-in is enabled, Zoho Campaigns will send a confirmation email to the user. The contact will be added to the list only after they confirm. To add contacts directly without confirmation, disable Double Opt-in under Settings > General > Manage Opt-in.';
        }
        /** Build Accounts URL (OAuth). */
        private function build_accounts_url(string $path): string
        {
            $endpoints = $this->resolve_endpoints();
            return rtrim($endpoints['accounts_base'], '/') . '/' . ltrim($path, '/');
        }

        /** Build Campaigns API v1.1 URL. Pass either:
         *  - an absolute v1.1 path like 'getmailinglists'
         *  - or paths that include 'json/' or 'xml/' for endpoints that require it (e.g. 'json/listsubscribe').
         */
        private function build_campaigns_url(string $path): string
        {
            $endpoints = $this->resolve_endpoints();
            $base      = rtrim($endpoints['campaigns_base'], '/') . '/api/v1.1/';
            return $base . ltrim($path, '/');
        }

        // -------- ACCESS TOKEN (OAuth) --------

        /**
         * Get/refresh access token using refresh token.
         * Replace CLIENT_ID / CLIENT_SECRET with stored config (do not hardcode secrets in code).
         */
        public function get_access_token(): bool
        {
            $url  = $this->build_accounts_url('/oauth/v2/token');
            $body = [
                'refresh_token' => $this->refresh_token,
                'client_id'     => '1000.R6NADONBVTIS0VZSZ0DE5MNO3DEV7T',
                'client_secret' => '52f6c37069fd0db03ed6025766e968214d35bffbe5',
                'grant_type'    => 'refresh_token',
            ];

            $response = wp_remote_post(
                $url,
                [
                    'body'    => $body,
                    'headers' => ['Content-Type' => 'application/x-www-form-urlencoded'],
                    'timeout' => 60,
                ]
            );

            if (is_wp_error($response)) {
                return false;
            }

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

            if (isset($data['access_token'])) {
                INTEGRAZO_WCZO_Util::updateAccessToken($this->account_id, $data['access_token']);
                $this->access_token = $data['access_token'];
                return true;
            }

            return false;
        }

        // -------- COMMON HELPERS --------

        private function auth_header(): array
        {
            return ['Authorization' => 'Zoho-oauthtoken ' . $this->access_token];
        }

        private function is_authentication_error_code($code): bool
        {
            // Zoho returns AUTHENTICATION_FAILURE / INVALID_TOKEN on 401 in many products.
            return in_array($code, ['AUTHENTICATION_FAILURE', 'INVALID_TOKEN'], true);
        }

        // -------- CAMPAIGNS: LISTS --------

        /**
         * Get mailing lists.
         * @param array $args { 'sort' => 'asc|desc', 'fromindex' => int, 'range' => int }
         * @return array
         */
        public function get_mailing_lists(bool $retry = true): array
        {
            $url = add_query_arg(
                ['resfmt' => 'JSON'],
                $this->build_campaigns_url('getmailinglists')
            );

            $response = wp_remote_get(
                $url,
                [
                    'headers' => $this->auth_header(),
                    'timeout' => 60,
                ]
            );

            if (is_wp_error($response)) {
                return ['error' => 'Connection failed. Please check connectivity or try again later.'];
            }

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

            if (isset($body['Code']) && $body['Code'] == 1007) {
                if ($retry && $this->get_access_token()) {
                    return $this->get_mailing_lists(false);
                }
                return ['error' => 'Authentication failed. Please reauthenticate.'];
            }

            if (200 !== $status) {
                return ['error' => 'Unexpected error while fetching mailing lists.'];
            }

            return $body;
        }
        // Get all Zoho Campaigns contact fields
        public function get_all_fields(bool $retry = true): array
        {
            // https://campaigns.zoho.{tld}/api/v1.1/contact/allfields?type=json
            $url = add_query_arg(
                ['type' => 'json'],
                $this->build_campaigns_url('contact/allfields')
            );

            $response = wp_remote_get($url, [
                'headers' => ['Authorization' => 'Zoho-oauthtoken ' . $this->access_token],
                'timeout' => 60,
            ]);

            if (is_wp_error($response)) {
                return ['error' => 'Connection failed: Please verify your internet connection, or try again later.'];
            }

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

            if (isset($body['Code']) && $body['Code'] == 1007) {
                if ($retry && $this->get_access_token()) {
                    return $this->get_all_fields(false);
                }
                return ['error' => 'Authentication failed. Please reauthenticate and try again.'];
            }

            if (200 !== $status || !isset($body['response'])) {
                return ['error' => 'Unexpected error while fetching fields.'];
            }

            $resp = $body['response'];

            if (isset($resp['fieldnames']) && isset($resp['fieldnames']['fieldname']) && is_array($resp['fieldnames']['fieldname'])) {
                return $resp['fieldnames']['fieldname'];
            }

            if (isset($resp['fieldname']) && is_array($resp['fieldname'])) {
                return $resp['fieldname'];
            }

            return ['error' => 'No fields found.'];
        }


        public function add_contact($record_data, $list_key, $retry = true)
        {
            try {
                // Build API URL
                $url = $this->build_campaigns_url('json/listsubscribe');

                // Prepare body
                $body = [
                    'resfmt'      => 'JSON',
                    'listkey'     => $list_key,
                    'contactinfo' => wp_json_encode($record_data),
                ];

                // API Request (POST with form-encoded body)
                $response = wp_remote_post($url, [
                    'headers' => [
                        'Authorization' => 'Zoho-oauthtoken ' . $this->access_token,
                        'Content-Type'  => 'application/x-www-form-urlencoded',
                    ],
                    'body'    => $body,
                    'timeout' => 60,
                ]);

                if (is_wp_error($response)) {
                    return INTEGRAZO_WCZO_Product_Util::create_error_response(
                        'NETWORK_ISSUE',
                        $response->get_error_message(),
                        null
                    );
                }

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

                if (!is_array($body)) {
                    return INTEGRAZO_WCZO_Product_Util::create_error_response('INVALID_RESPONSE', 'Invalid response from API.', null);
                }

                // Token expired
                if (isset($body['Code']) && $body['Code'] == 1007) {
                    if ($retry && $this->get_access_token()) {
                        return $this->add_contact($record_data, $list_key, false);
                    }
                    return INTEGRAZO_WCZO_Product_Util::create_error_response('AUTHENTICATION_FAILURE', 'Authentication failed.', $body);
                }

                // API failure
                if (isset($body['status']) && $body['status'] !== 'success') {
                    return INTEGRAZO_WCZO_Product_Util::create_error_response('RECORD_FAILED', 'Failed to add contact.', $body);
                }

                return INTEGRAZO_WCZO_Product_Util::create_error_response('SUCCESS', 'Contact added successfully.', $body);
            } catch (Throwable $e) {
                return INTEGRAZO_WCZO_Product_Util::create_error_response('UNEXPECTED_ERROR', $e->getMessage(), null);
            }
        }
    }
}
