<?php
if (!defined('ABSPATH')) {
    exit;
}

require_once INTEGRAZO_WZ_PLUGIN_DIR . 'src/products/common/class-zoho-fields.php';

/**
 * Base Zoho client for Inventory/Books/Invoice.
 */

if (!class_exists('INTEGRAZO_WZ_ZOHO_Base')) {
    class INTEGRAZO_WZ_ZOHO_Base
    {
        /** @var string|null */
        protected $refresh_token;
        /** @var string|null */
        protected $access_token;
        /** @var string */
        protected $data_center;
        /** @var int|string|null */
        protected $account_id;
        /** @var string inventory|books|invoice */
        protected $product; // 'inventory' | 'books' | 'invoice'

        public function __construct(array $account_details, string $product)
        {
            $this->refresh_token = $account_details['account_data']['refresh_token'] ?? null;
            $this->data_center   = $account_details['data_center'] ?? 'zoho.com';
            $this->account_id    = $account_details['id'] ?? null;
            $this->access_token  = INTEGRAZO_WZ_Util::getAccessToken($this->account_id);
            $this->product       = $product;
        }

        /** Expose contact field schema so caller can load UI first. */
        public function get_create_contact_fields(): array
        {
            return INTEGRAZO_WZ_Field_Schemas::create_contact_fields();
        }
        /** Expose contact field schema so caller can load UI first. */
        public function get_update_contact_fields(): array
        {
            return INTEGRAZO_WZ_Field_Schemas::create_contact_fields();
        }
        /** Expose contact field schema so caller can load UI first. */
        public function get_create_items_fields(): array
        {
            return INTEGRAZO_WZ_Field_Schemas::create_items_fields();
        }
        /** Expose contact field schema so caller can load UI first. */
        public function get_update_items_fields(): array
        {
            return INTEGRAZO_WZ_Field_Schemas::create_items_fields();
        }
        /** Expose contact field schema so caller can load UI first. */
        public function get_create_item_adjustment_fields($all_account_ids): array
        {
            return INTEGRAZO_WZ_Field_Schemas::create_item_adjustment_fields($all_account_ids);
        }
        /** Expose contact field schema so caller can load UI first. */
        public function get_sales_order_fields(): array
        {
            return INTEGRAZO_WZ_Field_Schemas::get_sales_order_fields();
        }
        /** Expose contact field schema so caller can load UI first. */
        public function get_invoice_fields(): array
        {
            return INTEGRAZO_WZ_Field_Schemas::get_invoice_fields();
        }

        /** Resolve Accounts + product API base for current DC. */
        protected function resolve_endpoints(): array
        {
            $dc = strtolower(trim((string)$this->data_center));
            switch ($dc) {
                case 'zoho.in':
                    $accounts = 'https://accounts.zoho.in';
                    $apis = 'https://www.zohoapis.in';
                    break;
                case 'zoho.eu':
                    $accounts = 'https://accounts.zoho.eu';
                    $apis = 'https://www.zohoapis.eu';
                    break;
                case 'zoho.com.au':
                    $accounts = 'https://accounts.zoho.com.au';
                    $apis = 'https://www.zohoapis.com.au';
                    break;
                case 'zoho.jp':
                    $accounts = 'https://accounts.zoho.jp';
                    $apis = 'https://www.zohoapis.jp';
                    break;
                case 'zoho.com.cn':
                    $accounts = 'https://accounts.zoho.com.cn';
                    $apis = 'https://www.zohoapis.com.cn';
                    break;
                case 'zoho.com':
                default:
                    $accounts = 'https://accounts.zoho.com';
                    $apis = 'https://www.zohoapis.com';
                    break;
            }

            $product_versions = [
                'inventory' => '/inventory/v1',
                'books'     => '/books/v3',
                'invoice'   => '/invoice/v3',
            ];
            $product_base = $apis . ($product_versions[$this->product] ?? '/inventory/v1');

            return [
                'accounts_base' => $accounts,
                'product_base'  => $product_base,
            ];
        }

        protected function build_accounts_url(string $path): string
        {
            $e = $this->resolve_endpoints();
            return rtrim($e['accounts_base'], '/') . '/' . ltrim($path, '/');
        }

        protected function build_product_url(string $path): string
        {
            $e = $this->resolve_endpoints();
            return rtrim($e['product_base'], '/') . '/' . ltrim($path, '/');
        }

        /** OAuth refresh via refresh_token. */
        public function get_access_token(): bool
        {
            $url  = $this->build_accounts_url('/oauth/v2/token');
            $body = [
                'refresh_token' => $this->refresh_token,
                // TODO: move to secure storage/settings.
                'client_id'     => '1000.R6NADONBVTIS0VZSZ0DE5MNO3DEV7T',
                'client_secret' => '52f6c37069fd0db03ed6025766e968214d35bffbe5',
                'grant_type'    => 'refresh_token',
            ];

            $resp = wp_remote_post($url, [
                'body'    => $body,
                'headers' => ['Content-Type' => 'application/x-www-form-urlencoded'],
                'timeout' => 60,
            ]);
            if (is_wp_error($resp)) {
                return false;
            }

            $data = json_decode(wp_remote_retrieve_body($resp), true);
            if (!empty($data['access_token'])) {
                INTEGRAZO_WZ_Util::updateAccessToken($this->account_id, $data['access_token']);
                $this->access_token = $data['access_token'];
                return true;
            }
            return false;
        }

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

        /** Core request with automatic retry on token expiry. */
        protected function request(string $method, string $path, array $args = [], bool $retry = true)
        {
            $url = $this->build_product_url($path);
            if (!empty($args['query'])) {
                $url = add_query_arg($args['query'], $url);
            }

            $is_json = !empty($args['json']);

            $opts = [
                'method'  => strtoupper($method),
                'headers' => $this->auth_header() + ($is_json ? ['Content-Type' => 'application/json'] : []),
                'timeout' => $args['timeout'] ?? 60,
            ];

            if (array_key_exists('body', $args)) {
                $opts['body'] = $is_json ? wp_json_encode($args['body']) : $args['body'];
            }

            $resp = wp_remote_request($url, $opts);

            // Network / WP error
            if (is_wp_error($resp)) {
                return INTEGRAZO_WZ_Product_Util::create_error_response(
                    'NETWORK_ISSUE',
                    'Failed to connect to Zoho API.',
                    $resp->get_error_message()
                );
            }

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

            $code = is_array($body) ? ($body['code'] ?? $body['Code'] ?? null) : null;

            // Retry once on 401 / 1007 (token expired / invalid)
            if (($status === 401 || (string)$code === '1007') && $retry && $this->get_access_token()) {
                return $this->request($method, $path, $args, false);
            }

            // JSON parse failed (Zoho not returning valid JSON)
            if ($raw !== '' && $body === null && json_last_error() !== JSON_ERROR_NONE) {
                return INTEGRAZO_WZ_Product_Util::create_error_response(
                    'INVALID_RESPONSE',
                    'Invalid response from Zoho API.',
                    [
                        'status' => $status,
                        'raw'    => $raw,
                    ]
                );
            }

            // Non-success HTTP codes
            if ($status < 200 || $status >= 300) {

                // Auth failure (after retry or no retry)
                if ($status === 401 || (string)$code === '1007') {
                    return INTEGRAZO_WZ_Product_Util::create_error_response(
                        'AUTHENTICATION_FAILURE',
                        'Access token invalid or expired.',
                        $body
                    );
                }

                return INTEGRAZO_WZ_Product_Util::create_error_response(
                    'API_ERROR',
                    isset($body['message']) && !empty($body['message'])
                        ? $body['message']
                        : 'Unexpected error from Zoho API.',
                    $body
                );
            }

            // Success → caller handles message/format
            return [
                'status' => $status,
                'body'   => $body,
            ];
        }
    }
}
