<?php

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

// Check if the class already exists to avoid redeclaration.
if (!class_exists('IAFWZC_Zoho_CRM')) {
    class IAFWZC_Zoho_CRM
    {
        private $refresh_token;
        private $access_token;
        private $data_center;
        private $account_id;
        public function __construct($account_details = [], $access_token = null)
        {
            $this->refresh_token = $account_details['refresh_token'] ?? null;
            $this->data_center = $account_details['data_center'] ?? null;
            $this->account_id = $account_details['account_id'] ?? null;
            $this->access_token = $access_token;
        }

        // Function to get access token using refresh token
        private function get_access_token()
        {
            $url = "https://accounts.zoho." . $this->data_center . "/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'])) {
                // Corrected account_id reference and updating the access token
                IAFWZC_Zoho_Util::updateAccessToken($this->account_id, $data['access_token']);
                $this->access_token = $data['access_token']; // Update the current access token
                return true;
            }

            return false;
        }

        // Function to get all modules from Zoho CRM
        public function get_modules($retry = true)
        {
            $url = "https://www.zohoapis." . $this->data_center . "/crm/v2/settings/modules";

            $response = wp_remote_get($url, [
                'headers' => [
                    'Authorization' => 'Zoho-oauthtoken ' . $this->access_token
                ],
                'timeout' => 60 // Timeout set to 20 seconds
            ]);

            // Check for HTTP response errors
            if (is_wp_error($response)) {
                // Handle network-related issues
                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"];
            }

            // Retrieve the response status code and body
            $status_code = wp_remote_retrieve_response_code($response);
            $body = json_decode(wp_remote_retrieve_body($response), true);

            // Handle 401 Unauthorized error - indicating an authentication failure
            if ($status_code === 401 && isset($body['code']) && in_array($body['code'], ['AUTHENTICATION_FAILURE', 'INVALID_TOKEN'])) {
                if ($retry && $this->get_access_token()) {
                    // Retry the request with the new access token once
                    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.'];
            }

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

            // Check if 'modules' is empty or not present, return an error message if so
            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 the modules if no authentication issues
            return $body['modules'];
        }



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

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


            // Check for HTTP response errors
            if (is_wp_error($response)) {
                // Handle network-related issues
                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"];
            }

            // Retrieve the response status code and body
            $status_code = wp_remote_retrieve_response_code($response);
            $body = json_decode(wp_remote_retrieve_body($response), true);

            // Handle 401 Unauthorized error, indicating an authentication failure
            if ($status_code === 401 && isset($body['code']) && in_array($body['code'], ['AUTHENTICATION_FAILURE', 'INVALID_TOKEN'])) {
                if ($retry && $this->get_access_token()) {
                    // Retry the request with the new access token once
                    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.'];
            }

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

            // Check if 'fields' is empty or not present, return an error message if so
            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 the fields if no issues are encountered
            return $body;
        }

        // Function to search records in a specific module by field name and value
        public function search_records_by_field($module_name, $field_name, $field_value, $retry = true)
        {
            try {
                // Construct the API endpoint URL
                $url = "https://www.zohoapis." . $this->data_center . "/crm/v2/" . urlencode($module_name) . "/search?"
                    . "criteria=(" . urlencode($field_name) . ":equals:" . urlencode($field_value) . ")"
                    . "&sort_by=Modified_Time&sort_order=desc";
                // Make the API request
                $response = wp_remote_get($url, [
                    'headers' => [
                        'Authorization' => 'Zoho-oauthtoken ' . $this->access_token
                    ],
                    'timeout' => 60 // Sets timeout to 60 seconds
                ]);

                // Check for HTTP response errors
                if (is_wp_error($response)) {
                    // Handle network-related issues
                    return $this->create_error_response('NETWORK_ISSUE');
                }

                // Retrieve the response status code and body
                $status_code = wp_remote_retrieve_response_code($response);
                $body = json_decode(wp_remote_retrieve_body($response), true);
                // Ensure the body is valid and has required keys
                if (!is_array($body)) {
                    return $this->create_error_response('INVALID_RESPONSE');
                }
                // Handle 401 Unauthorized error, indicating an authentication failure
                if ($status_code === 401 && isset($body['code']) && in_array($body['code'], ['AUTHENTICATION_FAILURE', 'INVALID_TOKEN'])) {
                    if ($retry && $this->get_access_token()) {
                        // Retry the request with the new access token once
                        return $this->search_records_by_field($module_name, $field_name, $field_value, false);
                    }
                    return $this->create_error_response('AUTHENTICATION_FAILURE');
                }

                // Return the retrieved records
                return $body;
            } catch (Throwable $e) {
                return $this->create_error_response('UNEXPECTED_ERROR');
            }
        }
        /**
         * Helper function to create a standardized error response.
         */
        private function create_error_response($error_code)
        {
            return [
                'data' => [
                    [
                        'status' => 'error',
                        'code' => $error_code,
                    ],
                ],
            ];
        }
        /**
         * Helper function to check if the error code is authentication-related.
         */
        private function is_authentication_error($code)
        {
            $auth_errors = ['AUTHENTICATION_FAILURE', 'INVALID_TOKEN'];
            return in_array($code, $auth_errors, true);
        }
        /**
         * Adds a record to a specific module in Zoho CRM.
         */
        public function add_module_record($module_id, $record_data, $retry = true)
        {

            try {
                $url = "https://www.zohoapis." . $this->data_center . "/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 // Sets timeout to 60 seconds
                ]);

                // Check for HTTP response errors
                if (is_wp_error($response)) {
                    return $this->create_error_response('NETWORK_ISSUE');
                }
                // Retrieve the response status code and body
                $status_code = wp_remote_retrieve_response_code($response);
                $body = json_decode(wp_remote_retrieve_body($response), true);
                // Ensure the body is valid and has required keys
                if (!is_array($body)) {
                    return $this->create_error_response('INVALID_RESPONSE');
                }

                // Handle 401 Unauthorized error, indicating an authentication failure
                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 $this->create_error_response('AUTHENTICATION_FAILURE');
                }

                return $body;
            } catch (Throwable $e) {
                return $this->create_error_response('UNEXPECTED_ERROR');
            }
        }


        public function update_module_record($module_id, $record_id, $record_data, $retry = true)
        {
            try {
                $url = "https://www.zohoapis." . $this->data_center . "/crm/v2/" . urlencode($module_id) . "/" . urlencode($record_id);

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

                // Check for HTTP response errors
                if (is_wp_error($response)) {
                    return $this->create_error_response('NETWORK_ISSUE');
                }

                // Retrieve the response status code and body
                $status_code = wp_remote_retrieve_response_code($response);
                $body = json_decode(wp_remote_retrieve_body($response), true);

                // Ensure the body is valid and has required keys
                if (!is_array($body)) {
                    return $this->create_error_response('INVALID_RESPONSE');
                }

                // Handle 401 Unauthorized error, indicating an authentication failure
                if ($status_code === 401 && isset($body['code']) && $this->is_authentication_error($body['code'])) {
                    if ($retry && $this->get_access_token()) {
                        return $this->update_module_record($module_id, $record_id, $record_data, false);
                    }
                    return $this->create_error_response('AUTHENTICATION_FAILURE');
                }

                return $body;
            } catch (Throwable $e) {
                return $this->create_error_response('UNEXPECTED_ERROR');
            }
        }
        public function add_note_to_record($module_id, $record_id, $note_content, $retry = true)
        {
            try {
                $url = "https://www.zohoapis." . $this->data_center . "/crm/v2/" . urlencode($module_id) . "/" . urlencode($record_id) . "/Notes";

                $note_data = [
                    'data' => [
                        [
                            // 'Note_Title' => 'New Note', // Optional title for the note
                            'Note_Content' => $note_content, // The actual note content
                        ]
                    ]
                ];

                $response = wp_remote_request($url, [
                    'method' => 'POST',
                    'headers' => [
                        'Authorization' => 'Zoho-oauthtoken ' . $this->access_token,
                        'Content-Type' => 'application/json',
                    ],
                    'body' => wp_json_encode($note_data),
                    'timeout' => 60, // Sets timeout to 60 seconds
                ]);

                // Check for HTTP response errors
                if (is_wp_error($response)) {
                    return $this->create_error_response('NETWORK_ISSUE');
                }

                // Retrieve the response status code and body
                $status_code = wp_remote_retrieve_response_code($response);
                $body = json_decode(wp_remote_retrieve_body($response), true);

                // Ensure the body is valid and has required keys
                if (!is_array($body)) {
                    return $this->create_error_response('INVALID_RESPONSE');
                }

                // Handle 401 Unauthorized error, indicating an authentication failure
                if ($status_code === 401 && isset($body['code']) && $this->is_authentication_error($body['code'])) {
                    if ($retry && $this->get_access_token()) {
                        return $this->add_note_to_record($module_id, $record_id, $note_content, false);
                    }
                    return $this->create_error_response('AUTHENTICATION_FAILURE');
                }

                return $body;
            } catch (Throwable $e) {
                return $this->create_error_response('UNEXPECTED_ERROR');
            }
        }

        public function add_record_tag($module_id, $record_id, $tags, $retry = true)
        {
            try {
                // Ensure tags are in the correct format as an array of objects
                $tags = is_array($tags) ? array_map(function ($tag) {
                    return ['name' => $tag];
                }, (array)$tags) : [['name' => $tags]];

                // Construct the API endpoint URL for adding a tag
                $url = "https://www.zohoapis." . $this->data_center . "/crm/v7/" . urlencode($module_id) . "/" . urlencode($record_id) . "/actions/add_tags";

                // Set up the request parameters
                $response = wp_remote_post($url, [
                    'headers' => [
                        'Authorization' => 'Zoho-oauthtoken ' . $this->access_token,
                        'Content-Type' => 'application/json',
                    ],
                    'body' => wp_json_encode(['tags' => $tags]), // Use 'tags' as per Zoho API documentation
                    'timeout' => 60 // Sets timeout to 60 seconds
                ]);

                // Check for HTTP response errors
                if (is_wp_error($response)) {
                    return $this->create_error_response('NETWORK_ISSUE');
                }

                // Retrieve the response status code and body
                $status_code = wp_remote_retrieve_response_code($response);
                $body = json_decode(wp_remote_retrieve_body($response), true);

                // Ensure the body is valid and has required keys
                if (!is_array($body)) {
                    return $this->create_error_response('INVALID_RESPONSE');
                }

                // Handle 401 Unauthorized error, indicating an authentication failure
                if ($status_code === 401 && isset($body['code']) && $this->is_authentication_error($body['code'])) {
                    if ($retry && $this->get_access_token()) {
                        return $this->add_record_tag($module_id, $record_id, $tags, false);
                    }
                    return $this->create_error_response('AUTHENTICATION_FAILURE');
                }
                // Return the response data if the tag is added successfully
                return $body;
            } catch (Throwable $e) {
                return $this->create_error_response('UNEXPECTED_ERROR');
            }
        }

        public function upload_attachment($module_id, $record_id, $file_path, $retry = true)
        {
            try {
                $url = "https://www.zohoapis." . $this->data_center . "/crm/v2/" . urlencode($module_id) . "/" . urlencode($record_id) . "/Attachments";

                // Ensure the file exists
                // if (!file_exists($file_path)) {
                //     return ['error' => "File not found: $file_path"];
                // }
                // Use WP_Filesystem to handle the file content
                global $wp_filesystem;
                if (!function_exists('WP_Filesystem')) {
                    require_once ABSPATH . 'wp-admin/includes/file.php';
                }
                WP_Filesystem();

                $file_content = $wp_filesystem->get_contents($file_path);
                if ($file_content === false) {
                    return ['error' => "Unable to read file: $file_path"];
                }
                // Use cURL to handle multipart form-data correctly
                $boundary = wp_generate_uuid4(); // Generate a unique boundary
                $body = "--{$boundary}\r\n";
                $body .= "Content-Disposition: form-data; name=\"file\"; filename=\"" . basename($file_path) . "\"\r\n";
                $body .= "Content-Type: application/octet-stream\r\n\r\n";
                $body .= $file_content . "\r\n";
                $body .= "--{$boundary}--";

                $headers = [
                    'Authorization' => 'Zoho-oauthtoken ' . $this->access_token,
                    'Content-Type' => 'multipart/form-data; boundary=' . $boundary,
                ];

                $response = wp_remote_post($url, [
                    'headers' => $headers,
                    'body' => $body,
                    'timeout' => 60, // Sets timeout to 60 seconds
                ]);

                // Check for HTTP response errors
                if (is_wp_error($response)) {
                    return $this->create_error_response('NETWORK_ISSUE');
                }

                // Retrieve the response status code and body
                $status_code = wp_remote_retrieve_response_code($response);
                $body = json_decode(wp_remote_retrieve_body($response), true);
                // Ensure the body is valid and has required keys
                if (!is_array($body)) {
                    return $this->create_error_response('INVALID_RESPONSE');
                }
                // Handle 401 Unauthorized error, indicating an authentication failure
                if ($status_code === 401 && isset($body['code']) && $this->is_authentication_error($body['code'])) {
                    if ($retry && $this->get_access_token()) {
                        return $this->upload_attachment($module_id, $record_id, $file_path, false);
                    }
                    return $this->create_error_response('AUTHENTICATION_FAILURE');
                }

                return $body;
            } catch (Throwable $e) {
                return $this->create_error_response('UNEXPECTED_ERROR');
            }
        }


        /**
         * Uploads a file to Zoho and maps it to a specified record and custom field in Zoho CRM.
         *
         */
        public function upload_and_map_file($module_id, $record_id, $file_upload_field_api_name, $file_path, $retry = true)
        {
            global $wp_filesystem;

            // Initialize the WordPress filesystem API
            if (empty($wp_filesystem)) {
                require_once ABSPATH . '/wp-admin/includes/file.php';
                WP_Filesystem();
            }

            try {
                // Step 1: Read file contents using $wp_filesystem
                // if (!$wp_filesystem->exists($file_path)) {
                // return $this->create_error_response('FILE_NOT_FOUND');
                // }

                $file_data = $wp_filesystem->get_contents($file_path);

                if ($file_data === false) {
                    return $this->create_error_response('FILE_READ_ERROR');
                }

                // Step 2: Upload the file to Zoho Files
                $upload_url = "https://www.zohoapis." . $this->data_center . "/crm/v2/files";

                $boundary = uniqid();
                $delimiter = '-------------' . $boundary;

                $post_data = "--$delimiter\r\n"
                    . "Content-Disposition: form-data; name=\"file\"; filename=\"" . basename($file_path) . "\"\r\n"
                    . "Content-Type: application/octet-stream\r\n\r\n"
                    . $file_data . "\r\n"
                    . "--$delimiter--\r\n";

                $upload_response = wp_remote_post($upload_url, [
                    'method' => 'POST',
                    'headers' => [
                        "Authorization" => "Zoho-oauthtoken " . $this->access_token,
                        "Content-Type" => "multipart/form-data; boundary=$delimiter",
                    ],
                    'body' => $post_data,
                    'timeout' => 15,
                ]);

                if (is_wp_error($upload_response)) {
                    return $this->create_error_response('FILE_UPLOAD_FAILED');
                }

                $upload_status_code = wp_remote_retrieve_response_code($upload_response);
                $upload_response_body = wp_remote_retrieve_body($upload_response);

                // Handle 401 Unauthorized error for file upload
                if ($upload_status_code === 401 && $this->is_authentication_error(json_decode($upload_response_body, true)['code'] ?? '')) {
                    if ($retry && $this->get_access_token()) {
                        return $this->upload_and_map_file($module_id, $record_id, $file_upload_field_api_name, $file_path, false);
                    }
                    return $this->create_error_response('AUTHENTICATION_FAILURE');
                }

                if ($upload_status_code !== 200) {
                    return $this->create_error_response('FILE_UPLOAD_FAILED');
                }

                $upload_response_data = json_decode($upload_response_body, true);

                if (!isset($upload_response_data['data'][0]['details']['id']) || $upload_response_data['data'][0]['status'] !== 'success') {
                    return $this->create_error_response('FILE_UPLOAD_ERROR');
                }

                $file_id = $upload_response_data['data'][0]['details']['id'];

                // Step 3: Map the uploaded file to the custom field in Zoho CRM
                $map_url = "https://www.zohoapis." . $this->data_center . "/crm/v2/" . urlencode($module_id) . "/" . urlencode($record_id);

                $file_data_payload = [
                    'data' => [
                        [
                            'id' => $record_id,
                            $file_upload_field_api_name => [
                                ['file_id' => $file_id]
                            ]
                        ]
                    ]
                ];

                $map_response = wp_remote_post($map_url, [
                    'method' => 'PUT',
                    'headers' => [
                        "Authorization" => "Zoho-oauthtoken " . $this->access_token,
                        "Content-Type" => "application/json",
                    ],
                    'body' => wp_json_encode($file_data_payload),
                    'timeout' => 15,
                ]);

                if (is_wp_error($map_response)) {
                    return $this->create_error_response('RECORD_UPDATE_FAILED');
                }

                $map_status_code = wp_remote_retrieve_response_code($map_response);
                $map_response_body = wp_remote_retrieve_body($map_response);

                // Handle 401 Unauthorized error for record mapping
                if ($map_status_code === 401 && $this->is_authentication_error(json_decode($map_response_body, true)['code'] ?? '')) {
                    if ($retry && $this->get_access_token()) {
                        return $this->upload_and_map_file($module_id, $record_id, $file_upload_field_api_name, $file_path, false);
                    }
                    return $this->create_error_response('AUTHENTICATION_FAILURE');
                }

                if ($map_status_code !== 200) {
                    return $this->create_error_response('RECORD_UPDATE_FAILED');
                }

                $map_response_data = json_decode($map_response_body, true);

                return $map_response_data;
            } catch (Throwable $e) {
                // Log the exception for debugging
                return $this->create_error_response('UNEXPECTED_ERROR');
            }
        }



        /**
         * Helper function to retrieve HTTP status code from headers.
         */
        private function get_status_code($headers)
        {
            $status_line = $headers[0] ?? 'HTTP/1.1 500';
            preg_match('/\d{3}/', $status_line, $matches);
            return $matches[0] ?? '500';
        }

        public function upload_record_image($module_id, $record_id, $file_path, $retry = true)
        {
            global $wp_filesystem;

            // Initialize the WordPress filesystem API
            if (empty($wp_filesystem)) {
                require_once ABSPATH . '/wp-admin/includes/file.php';
                WP_Filesystem();
            }

            try {
                $url = "https://www.zohoapis." . $this->data_center . "/crm/v2/" . urlencode($module_id) . "/" . urlencode($record_id) . "/photo";

                // Ensure the file exists using WordPress filesystem API
                // if (!$wp_filesystem->exists($file_path)) {
                //     return ['error' => "File not found: $file_path"];
                // }

                // Read file contents securely using the WordPress filesystem API
                $file_contents = $wp_filesystem->get_contents($file_path);
                if ($file_contents === false) {
                    return $this->create_error_response('FILE_READ_ERROR');
                }

                // Use cURL to handle multipart form-data correctly
                $boundary = wp_generate_uuid4(); // Generate a unique boundary
                $body = "--{$boundary}\r\n";
                $body .= "Content-Disposition: form-data; name=\"file\"; filename=\"" . basename($file_path) . "\"\r\n";
                $body .= "Content-Type: image/jpeg\r\n\r\n"; // Update MIME type as needed (e.g., image/png)
                $body .= $file_contents . "\r\n";
                $body .= "--{$boundary}--";

                $headers = [
                    'Authorization' => 'Zoho-oauthtoken ' . $this->access_token,
                    'Content-Type' => 'multipart/form-data; boundary=' . $boundary,
                ];

                $response = wp_remote_post($url, [
                    'headers' => $headers,
                    'body' => $body,
                    'timeout' => 60, // Sets timeout to 60 seconds
                ]);

                // Check for HTTP response errors
                if (is_wp_error($response)) {
                    return $this->create_error_response('NETWORK_ISSUE');
                }

                // Retrieve the response status code and body
                $status_code = wp_remote_retrieve_response_code($response);
                $response_body = json_decode(wp_remote_retrieve_body($response), true);

                // Ensure the body is valid and has required keys
                if (!is_array($response_body)) {
                    return $this->create_error_response('INVALID_RESPONSE');
                }

                // Handle 401 Unauthorized error, indicating an authentication failure
                if ($status_code === 401 && isset($response_body['code']) && $this->is_authentication_error($response_body['code'])) {
                    if ($retry && $this->get_access_token()) {
                        return $this->upload_record_image($module_id, $record_id, $file_path, false);
                    }
                    return $this->create_error_response('AUTHENTICATION_FAILURE');
                }

                return $response_body;
            } catch (Throwable $e) {
                return $this->create_error_response('UNEXPECTED_ERROR');
            }
        }
    }
    $iafwzc_zohoCRMInstance = new IAFWZC_Zoho_CRM();
}
