<?php
// Exit if accessed directly.
if (!defined('ABSPATH')) {
    exit; // Prevent direct access to the file.
}

require_once INTEGRAZO_WZ_PLUGIN_DIR . 'src/products/zoho_crm/util.php';

// Check if the class already exists to avoid redeclaration.
if (!class_exists('INTEGRAZO_WZ_Zoho_CRM')) {
    class INTEGRAZO_WZ_Zoho_CRM
    {
        public $refresh_token;
        public $access_token;
        public $data_center; // expected values: 'zoho.com','zoho.in','zoho.eu','zoho.uk','zoho.jp','zoho.sa','zoho.cn','zoho.au','zohocloud.ca'
        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 if missing
            $this->account_id    = $account_details['id'] ?? null;
            $this->access_token  = INTEGRAZO_WZ_Util::getAccessToken($this->account_id);
        }

        /**
         * Resolve endpoints (Accounts + API) for the current data center.
         * Keeps all DC mapping logic in one place.
         *
         * @return array{accounts_base:string, api_base:string}
         */
        private function resolve_endpoints()
        {
            // Normalize DC value (defensive)
            $dc = strtolower(trim((string) $this->data_center));

            // Map of DC -> [accounts_base, api_base]
            // NOTE:
            // - Canada uses zohocloud.ca
            // - China’s real domains are *.zoho.com.cn / *.zohoapis.com.cn (we derive correctly from 'zoho.cn' key)
            switch ($dc) {
                case 'zoho.in':
                    return [
                        'accounts_base' => 'https://accounts.zoho.in',
                        'api_base'      => 'https://www.zohoapis.in',
                    ];
                case 'zoho.eu':
                    return [
                        'accounts_base' => 'https://accounts.zoho.eu',
                        'api_base'      => 'https://www.zohoapis.eu',
                    ];
                case 'zoho.uk':
                    return [
                        'accounts_base' => 'https://accounts.zoho.uk',
                        'api_base'      => 'https://www.zohoapis.uk',
                    ];
                case 'zoho.jp':
                    return [
                        'accounts_base' => 'https://accounts.zoho.jp',
                        'api_base'      => 'https://www.zohoapis.jp',
                    ];
                case 'zoho.sa':
                    return [
                        'accounts_base' => 'https://accounts.zoho.sa',
                        'api_base'      => 'https://www.zohoapis.sa',
                    ];
                case 'zoho.com.au':
                    return [
                        'accounts_base' => 'https://accounts.zoho.com.au',
                        'api_base'      => 'https://www.zohoapis.com.au',
                    ];
                case 'zoho.com.cn':
                    // China uses *.zoho.com.cn and *.zohoapis.com.cn
                    return [
                        'accounts_base' => 'https://accounts.zoho.com.cn',
                        'api_base'      => 'https://www.zohoapis.com.cn',
                    ];
                case 'zohocloud.ca':
                    return [
                        'accounts_base' => 'https://accounts.zohocloud.ca',
                        'api_base'      => 'https://www.zohoapis.ca',
                    ];
                case 'zoho.com':
                default:
                    // US (default)
                    return [
                        'accounts_base' => 'https://accounts.zoho.com',
                        'api_base'      => 'https://www.zohoapis.com',
                    ];
            }
        }
        /**
         * Record action options for radio buttons.
         * Returns an ordered list of [ 'value' => string, 'label' => string, 'disabled' => bool, 'default' => bool ].
         */
        function record_action_options()
        {
            return array(
                array(
                    'value'    => 'add',
                    'label'    => 'Add New Record',
                    'disabled' => false,
                    'default'  => true   // This one will be selected by default
                ),
                array(
                    'value'    => 'add_or_update',
                    'label'    => 'Add or Update Existing Record',
                    'disabled' => true,
                    'default'  => false
                )
            );
        }
        public function common_note(): string
        {
            return 'Note: The Attachment, Tag, and Note fields are available on the right-side dropdown under the ‘Premium Fields’ section (scroll to the bottom to view them).';
        }
        /**
         * Build a full Accounts URL.
         */
        private function build_accounts_url(string $path): string
        {
            $endpoints = $this->resolve_endpoints();
            return rtrim($endpoints['accounts_base'], '/') . '/' . ltrim($path, '/');
        }

        /**
         * Build a full API URL (CRM).
         */
        public function build_api_url(string $path): string
        {
            $endpoints = $this->resolve_endpoints();
            return rtrim($endpoints['api_base'], '/') . '/' . ltrim($path, '/');
        }

        // -------- ACCESS TOKEN --------

        // Function to get access token using refresh token
        public function get_access_token()
        {
            $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;
            }

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

            if (isset($data['access_token'])) {
                // Update the stored token
                INTEGRAZO_WZ_Util::updateAccessToken($this->account_id, $data['access_token']);
                $this->access_token = $data['access_token'];
                return true;
            }

            return false;
        }

        // -------- CRM: MODULES --------

        // Function to get all modules from Zoho CRM
        public function get_modules($retry = true)
        {
            $url = $this->build_api_url('crm/v2/settings/modules');

            $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 the Zoho server may not be responding right now. Try again, and if the issue continues, contact support"];
            }

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

            if ($status_code === 401 && isset($body['code']) && in_array($body['code'], ['AUTHENTICATION_FAILURE', 'INVALID_TOKEN'], true)) {
                if ($retry && $this->get_access_token()) {
                    return $this->get_modules(false);
                }
                return ['error' => 'Authentication failed. Your session may have expired or your token may be invalid. Please reauthenticate and try again.'];
            }

            if ($status_code !== 200) {
                return ['error' => "An unexpected error occurred while fetching modules. Please try again later or contact support if the issue persists."];
            }

            if (empty($body['modules'])) {
                return ['error' => "No modules found. This may be due to access restrictions or an empty configuration. Please check your account settings or contact support."];
            }

            return $body['modules'];
        }

        // -------- CRM: FIELDS --------

        // Function to get fields of a specific module
        public function get_module_fields($module_id, $retry = true)
        {
            $url = $this->build_api_url('crm/v2/settings/fields?module=' . urlencode($module_id));

            $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 the Zoho server may not be responding right now. Try again, and if the issue continues, contact support"];
            }

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

            if ($status_code === 401 && isset($body['code']) && in_array($body['code'], ['AUTHENTICATION_FAILURE', 'INVALID_TOKEN'], true)) {
                if ($retry && $this->get_access_token()) {
                    return $this->get_module_fields($module_id, false);
                }
                return ['error' => 'Authentication failed. Your session may have expired or your token may be invalid. Please reauthenticate and try again.'];
            }

            if ($status_code !== 200) {
                return ['error' => "An unexpected error occurred while fetching fields. Please try again later or contact support if the issue persists."];
            }

            if (empty($body)) {
                return ['error' => "No fields were found for the specified module. This module may not contain fields or there may be a configuration issue. Please check your module setup or contact support."];
            }

            return $body;
        }

        // -------- CRM: ADD RECORD --------

        /**
         * Adds a record to a specific module in Zoho CRM.
         */
        public function add_module_record($module_id, $record_data, $retry = true)
        {
            try {
                $url = $this->build_api_url('crm/v2/' . urlencode($module_id));

                $response = wp_remote_post($url, [
                    'headers' => [
                        'Authorization' => 'Zoho-oauthtoken ' . $this->access_token,
                        'Content-Type'  => 'application/json',
                    ],
                    'body'    => wp_json_encode(['data' => [$record_data]]),
                    'timeout' => 60
                ]);

                if (is_wp_error($response)) {
                    return INTEGRAZO_WZ_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_WZ_Product_Util::create_error_response('INVALID_RESPONSE', 'Invalid response from API.', $body);
                }

                if ($status_code === 401 && isset($body['code']) && $this->is_authentication_error($body['code'])) {
                    if ($retry && $this->get_access_token()) {
                        return $this->add_module_record($module_id, $record_data, false);
                    }
                    return INTEGRAZO_WZ_Product_Util::create_error_response('AUTHENTICATION_FAILURE', 'Authentication failed.', $body);
                }

                return $body;
            } catch (Throwable $e) {
                return INTEGRAZO_WZ_Product_Util::create_error_response('EXCEPTION_THROWN', $e->getMessage(), null);
            }
        }

        /**
         * Helper function to check if the error code is authentication-related.
         */
        public function is_authentication_error($code)
        {
            $auth_errors = ['AUTHENTICATION_FAILURE', 'INVALID_TOKEN'];
            return in_array($code, $auth_errors, true);
        }
    }
}
