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

/**
 * =========================
 *  GLOBAL ZOHO CONSTANTS
 *  (Same for all services + default DC)
 * =========================
 * NOTE: Consider moving CLIENT_ID/SECRET to wp-config.php or a secure option.
 */
if (!defined('INTEGRAZO_WZ_ZOHO_CLIENT_ID')) {
    define('INTEGRAZO_WZ_ZOHO_CLIENT_ID', '1000.R6NADONBVTIS0VZSZ0DE5MNO3DEV7T'); // <-- your value
}
if (!defined('INTEGRAZO_WZ_ZOHO_CLIENT_SECRET')) {
    define('INTEGRAZO_WZ_ZOHO_CLIENT_SECRET', '52f6c37069fd0db03ed6025766e968214d35bffbe5'); // <-- your value
}
if (!defined('INTEGRAZO_WZ_ZOHO_REDIRECT_URI')) {
    define('INTEGRAZO_WZ_ZOHO_REDIRECT_URI', 'https://integrazo.com/zoho_callback'); // <-- your value
}
if (!defined('INTEGRAZO_WZ_ZOHO_DC')) {
    define('INTEGRAZO_WZ_ZOHO_DC', 'zoho.com'); // default fallback. Your <select> sends values like "zoho.com", "zoho.in", etc.
}

/** PHP 7.x compatibility for str_ends_with */
if (!function_exists('str_ends_with')) {
    function str_ends_with($haystack, $needle)
    {
        $len = strlen($needle);
        if ($len === 0) return true;
        return substr($haystack, -$len) === $needle;
    }
}

/** Service => label + scopes (tune scopes per service if needed) */
function integrazo_wz_zoho_service_map()
{
    return [
        'zoho_crm' => [
            'label' => 'Zoho CRM',
            'scope' => 'ZohoCRM.modules.ALL,ZohoCRM.settings.ALL,ZohoCRM.users.ALL,ZohoCRM.org.ALL,ZohoCRM.coql.READ,ZohoCRM.files.CREATE',
        ],
        'zoho_bigin' => [
            'label' => 'Zoho Bigin',
            'scope' => 'ZohoBigin.modules.ALL,ZohoBigin.users.READ,ZohoBigin.settings.ALL',
        ],
        'zoho_desk' => [
            'label' => 'Zoho Desk',
            'scope' => 'Desk.settings.READ,Desk.basic.READ,Desk.tickets.ALL,Desk.search.READ,Desk.contacts.ALL',
        ],
        'zoho_campaign' => [
            'label' => 'Zoho Campaigns',
            'scope' => 'ZohoCampaigns.contact.CREATE,ZohoCampaigns.contact.READ,ZohoCampaigns.contact.UPDATE',
        ],
        'zoho_inventory' => [
            'label' => 'Zoho Inventory',
            'scope' => 'ZohoInventory.FullAccess.all',
        ],
        'zoho_books' => [
            'label' => 'Zoho Books',
            'scope' => 'ZohoBooks.fullaccess.all',
        ],
        'zoho_invoice' => [
            'label' => 'Zoho Invoice',
            'scope' => 'ZohoInvoice.fullaccess.all',
        ],
        'zoho_sheet' => [
            'label' => 'Zoho Sheet',
            'scope' => 'ZohoSheet.dataapi.READ ZohoSheet.dataapi.UPDATE',
        ],
    ];
}

/** Map WP action => Zoho service (auth + update both go to same handler) */
function integrazo_wz_zoho_action_service_map()
{
    return [
        // Connect
        'admin_post_integrazo_wz_zoho_crm_account_authentication'        => 'zoho_crm',
        'admin_post_integrazo_wz_zoho_desk_account_authentication'       => 'zoho_desk',
        'admin_post_integrazo_wz_zoho_campaigns_account_authentication'  => 'zoho_campaign',
        'admin_post_integrazo_wz_zoho_inventory_account_authentication'  => 'zoho_inventory',
        'admin_post_integrazo_wz_zoho_bigin_account_authentication'      => 'zoho_bigin',
        'admin_post_integrazo_wz_zoho_sheet_account_authentication'      => 'zoho_sheet',
        'admin_post_integrazo_wz_zoho_books_account_authentication'      => 'zoho_books',
        'admin_post_integrazo_wz_zoho_invoice_account_authentication'    => 'zoho_invoice',

        // Reconnect (update)
        'admin_post_integrazo_wz_zoho_crm_account_update'        => 'zoho_crm',
        'admin_post_integrazo_wz_zoho_desk_account_update'       => 'zoho_desk',
        'admin_post_integrazo_wz_zoho_campaigns_account_update'  => 'zoho_campaign',
        'admin_post_integrazo_wz_zoho_inventory_account_update'  => 'zoho_inventory',
        'admin_post_integrazo_wz_zoho_bigin_account_update'      => 'zoho_bigin',
        'admin_post_integrazo_wz_zoho_sheet_account_update'      => 'zoho_sheet',
        'admin_post_integrazo_wz_zoho_books_account_update'      => 'zoho_books',
        'admin_post_integrazo_wz_zoho_invoice_account_update'    => 'zoho_invoice',
    ];
}

/** Register all actions to one handler */
foreach (array_keys(integrazo_wz_zoho_action_service_map()) as $integrazo_wz_hook) {
    add_action($integrazo_wz_hook, 'integrazo_wz_zoho_account_auth_handler');
}

/** Helpers: notices + redirect (uses global transient keys + referer) */
function integrazo_wz_zoho_fail_and_redirect($message, $redirect = '')
{
    // Global keys (no user ID)
    set_transient('integrazo_wz_fail', $message, 30);
    // Prefer provided $redirect, else referer, else safe admin fallback
    $to = $redirect ?: esc_url_raw(admin_url('admin.php?page=integrazo-integration-for-zoho-apps'));
    wp_safe_redirect($to);
    exit;
}
function integrazo_wz_zoho_success_and_redirect($message, $redirect = '')
{
    // Global keys (no user ID)
    set_transient('integrazo_wz_success', $message, 30);
    // Prefer provided $redirect, else safe admin fallback
    $to = $redirect ?: esc_url_raw(admin_url('admin.php?page=integrazo-integration-for-zoho-apps'));
    wp_safe_redirect($to);
    exit;
}

/** Single handler for add + update for any zoho_* service */
function integrazo_wz_zoho_account_auth_handler()
{

    $current   = current_action(); // e.g. admin_post_integrazo_wz_zoho_crm_account_authentication
    $is_update = str_ends_with($current, '_update');

    $map     = integrazo_wz_zoho_action_service_map();
    $service = $map[$current] ?? '';
    if (!$service) {
        integrazo_wz_zoho_fail_and_redirect(__('Invalid service/action.', 'integrazo-integration-for-zoho-apps'));
    }

    // Nonce check
    $nonce_key  = $is_update ? 'integrazo_wz_auth_update_nonce' : 'integrazo_wz_auth_nonce';
    $nonce_name = $is_update ? 'integrazo_wz_auth_update_action' : 'integrazo_wz_auth_action';
    if (!isset($_POST[$nonce_key]) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST[$nonce_key])), $nonce_name)) {
        integrazo_wz_zoho_fail_and_redirect(__('Security check failed.', 'integrazo-integration-for-zoho-apps'));
    }
    if (! current_user_can('manage_options')) {
        integrazo_wz_zoho_fail_and_redirect(__('Insufficient permissions.', 'integrazo-integration-for-zoho-apps'));
    }
    $account_name   = sanitize_text_field(wp_unslash($_POST['integrazo_wz_account_name'] ?? ''));
    $account_id     = absint($_POST['account_id'] ?? 0);
    $integration_id = sanitize_text_field(wp_unslash($_POST['integration_id'] ?? ''));
    $to_product     = sanitize_text_field(wp_unslash($_POST['to_product'] ?? $service));
    $clicked_button = sanitize_text_field(wp_unslash($_POST['integrazo_wz_step2_button_action'] ?? ''));
    // DC comes like "zoho.com", "zoho.in", "zohocloud.ca", etc.
    $dc             = strtolower(sanitize_text_field(wp_unslash($_POST['dc'] ?? INTEGRAZO_WZ_ZOHO_DC)));
    $dc             = preg_replace('/[^a-z0-9\.\-]/', '', $dc); // minimal hardening
    $allowed_dc = ['zoho.com', 'zoho.in', 'zoho.eu', 'zoho.com.au', 'zoho.jp', 'zohocloud.ca'];
    if (!in_array($dc, $allowed_dc, true)) {
        wp_die(esc_html__('Invalid data center.', 'integrazo-integration-for-zoho-apps'));
    }

    $integration_instance  = new INTEGRAZO_WZ_Integration_Model();
    $step2_url = esc_url_raw(admin_url('admin.php?page=integrazo-integration-for-zoho-apps&tab=setup&integration_id=' . urlencode($integration_id) . '&step=2'));
    $step3_url = esc_url_raw(admin_url('admin.php?page=integrazo-integration-for-zoho-apps&tab=setup&integration_id=' . urlencode($integration_id) . '&step=3'));

    // Save-only flows (no OAuth)
    if ($clicked_button === 'save') {
        $updated = $integration_instance->update_account_id_by_integration_id($integration_id, $account_id);
        if ($updated) {
            integrazo_wz_zoho_success_and_redirect(__('Account mapping changed successfully!', 'integrazo-integration-for-zoho-apps'), $step2_url);
        }
        integrazo_wz_zoho_fail_and_redirect(__('Failed to update account mapping.', 'integrazo-integration-for-zoho-apps'), $step2_url);
    } elseif ($clicked_button === 'save_and_next') {
        $integration_instance->update_account_id_by_integration_id($integration_id, $account_id);
        wp_safe_redirect($step3_url);
        exit;
    }

    // --- Begin OAuth ---
    if (INTEGRAZO_WZ_ZOHO_CLIENT_ID === '' || INTEGRAZO_WZ_ZOHO_CLIENT_SECRET === '') {
        integrazo_wz_zoho_fail_and_redirect(__('Zoho client credentials are missing. Please configure CLIENT_ID/SECRET.', 'integrazo-integration-for-zoho-apps'), $step2_url);
    }

    $scope_map = integrazo_wz_zoho_service_map();
    if (empty($scope_map[$service]['scope'])) {
        integrazo_wz_zoho_fail_and_redirect(__('Scopes not configured for this Zoho service.', 'integrazo-integration-for-zoho-apps'), $step2_url);
    }

    // Build accounts base directly from DC (as provided)
    $accounts = 'https://accounts.' . $dc;

    // Persist context for callback (also store where to return)
    $csrf_token = bin2hex(random_bytes(16));

    set_transient('integrazo_wz_zoho_auth_data', [
        'action'         => $current,
        'service'        => $service,
        'account_name'   => $account_name,
        'account_id'     => $account_id,
        'integration_id' => $integration_id,
        'is_update'      => $is_update,
        'dc'             => $dc,
        'state_token'    => $csrf_token,
    ], 10 * MINUTE_IN_SECONDS);

    // State with page + service + CSRF token to prevent replay/CSRF on callback
    $state = urlencode(add_query_arg([
        'page'    => 'integrazo-integration-for-zoho-apps',
        'service' => $service,
        'token'   => $csrf_token,
    ], admin_url('admin.php')));

    // Build Zoho auth URL
    $oauth_url = sprintf(
        '%s/oauth/v2/auth?response_type=code&client_id=%s&redirect_uri=%s&scope=%s&access_type=offline&prompt=consent&state=%s',
        $accounts,
        rawurlencode(INTEGRAZO_WZ_ZOHO_CLIENT_ID),
        rawurlencode(INTEGRAZO_WZ_ZOHO_REDIRECT_URI),
        rawurlencode($scope_map[$service]['scope']),
        $state
    );

    // IMPORTANT: external redirect must use wp_redirect (not wp_safe_redirect)
    // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect
    wp_redirect($oauth_url);
    exit;
}

/**
 * Shared Zoho OAuth callback with robust validation.
 * Uses `state` to ensure request belongs to our flow and correct service/action.
 */
add_action('init', function () {
    if (
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        isset($_GET['code'], $_GET['service'], $_GET['page']) && $_GET['page'] === 'integrazo-integration-for-zoho-apps' && in_array($_GET['service'], ['zoho_crm', 'zoho_bigin', 'zoho_desk', 'zoho_sheet', 'zoho_campaign', 'zoho_inventory','zoho_books','zoho_invoice'], true)
    ) {


        $auth_data = get_transient('integrazo_wz_zoho_auth_data');
        if (!$auth_data) {
            // No context — return to a safe place
            set_transient('integrazo_wz_fail', __('Authentication session expired. Please restart the process.', 'integrazo-integration-for-zoho-apps'), 30);
            wp_safe_redirect(esc_url_raw(admin_url('admin.php?page=integrazo-integration-for-zoho-apps')));
            exit;
        }
        if (! current_user_can('manage_options')) {
            wp_die(esc_html__('Insufficient permissions.', 'integrazo-integration-for-zoho-apps'));
        }

        // Restore everything we saved earlier
        $account_name   = $auth_data['account_name'] ?? '';
        $account_id     = isset($auth_data['account_id']) ? (int) $auth_data['account_id'] : 0;
        $integration_id = $auth_data['integration_id'] ?? '';
        $dc             = $auth_data['dc'] ?? INTEGRAZO_WZ_ZOHO_DC;
        $to_product     = $auth_data['service'] ?? '';
        $service        = $auth_data['service'] ?? '';
        $service_from_action = $auth_data['action'] ?? '';
        $is_update      = !empty($auth_data['is_update']);

        // Build redirect targets
        $accounts_url   = esc_url_raw(admin_url('admin.php?page=integrazo-integration-for-zoho-apps&tab=settings&subtab=accounts')); // update success/fail
        $step2_url      = esc_url_raw(admin_url('admin.php?page=integrazo-integration-for-zoho-apps&tab=setup&integration_id=' . urlencode($integration_id) . '&step=2')); // add fail
        $step3_url      = esc_url_raw(admin_url('admin.php?page=integrazo-integration-for-zoho-apps&tab=setup&integration_id=' . urlencode($integration_id) . '&step=3')); // add success

        // For any errors, choose target by flow:
        $err_target = $is_update ? $accounts_url : $step2_url;

        // Verify OAuth state token to prevent CSRF
        $received_token = '';
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        if (!empty($_GET['state'])) {
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $state_query = wp_parse_url(urldecode(sanitize_text_field(wp_unslash($_GET['state']))), PHP_URL_QUERY) ?? '';
            parse_str($state_query, $state_params);
            $received_token = $state_params['token'] ?? '';
        }
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        if (empty($received_token) && !empty($_GET['token'])) {
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $received_token = sanitize_text_field(wp_unslash($_GET['token']));
        }
        $stored_token   = $auth_data['state_token'] ?? '';
        if (empty($stored_token) || empty($received_token) || !hash_equals($stored_token, $received_token)) {
            integrazo_wz_zoho_fail_and_redirect(__('State mismatch. Please restart the authentication process.', 'integrazo-integration-for-zoho-apps'), $err_target);
        }

        // Extra cross-check: service in state must match the action's service
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        if (sanitize_key(wp_unslash($_GET['service'])) !== $to_product) {
            integrazo_wz_zoho_fail_and_redirect(__('Service mismatch. Please try again.', 'integrazo-integration-for-zoho-apps'), $err_target);
        }

        // Clear auth context after restoring what we need
        delete_transient('integrazo_wz_zoho_auth_data');

        // Build accounts base directly from DC in state
        $accounts = 'https://accounts.' . $dc;

        // Token exchange
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        $code     = sanitize_text_field(wp_unslash($_GET['code']));
        $response = wp_remote_post($accounts . '/oauth/v2/token', [
            'timeout' => 60,
            'headers' => ['Content-Type' => 'application/x-www-form-urlencoded'],
            'body'    => [
                'grant_type'    => 'authorization_code',
                'client_id'     => INTEGRAZO_WZ_ZOHO_CLIENT_ID,
                'client_secret' => INTEGRAZO_WZ_ZOHO_CLIENT_SECRET,
                'redirect_uri'  => INTEGRAZO_WZ_ZOHO_REDIRECT_URI,
                'code'          => $code,
            ],
        ]);
        if (is_wp_error($response)) {
            $message = __('Connection failed: ', 'integrazo-integration-for-zoho-apps') . $response->get_error_message();
            integrazo_wz_zoho_fail_and_redirect($message, $err_target);
        }

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

        if ($body === null && json_last_error() !== JSON_ERROR_NONE) {
            integrazo_wz_zoho_fail_and_redirect(__('Invalid JSON from Zoho. Please try again.', 'integrazo-integration-for-zoho-apps'), $err_target);
        }
        if ($status !== 200 || empty($body['access_token'])) {
            // Prefer Zoho's error_description, fall back to error or HTTP code
            $err_code = $body['error'] ?? '';
            $err_desc = $body['error_description'] ?? '';

            if ($err_code === 'invalid_code') {
                $err = __('Invalid authorization code. Please select the correct Zoho Data Center and try again.', 'integrazo-integration-for-zoho-apps');
            } else {
                $err = $err_desc ?: __('Unexpected HTTP from Zoho: ', 'integrazo-integration-for-zoho-apps') . $status;
            }

            integrazo_wz_zoho_fail_and_redirect($err, $err_target);
        }

        // Store tokens (same data model as your Google flow)
        $account_instance = new INTEGRAZO_WZ_Account_Model();
        $input_data = [
            'dc' => $dc,
        ];

        if ($is_update) {
            // UPDATE FLOW → on success go to Accounts page
            $account_instance->update_account_by_id($account_id, $account_name, $body, $input_data, $dc);
            integrazo_wz_zoho_success_and_redirect(
                integrazo_wz_zoho_service_map()[$service]['label'] . __(' account updated successfully!', 'integrazo-integration-for-zoho-apps'),
                $accounts_url
            );
        } else {
            // ADD (CONNECT) FLOW
            $new_account_id = $account_instance->add_account($account_name, $to_product, $body, $input_data, $dc);
            if ($new_account_id) {
                (new INTEGRAZO_WZ_Integration_Model())->update_account_id_by_integration_id($integration_id, $new_account_id);
                // Success → step 3
                integrazo_wz_zoho_success_and_redirect(
                    integrazo_wz_zoho_service_map()[$service]['label'] . __(' account connected successfully!', 'integrazo-integration-for-zoho-apps'),
                    $step3_url
                );
            }
            // Fail → step 2
            integrazo_wz_zoho_fail_and_redirect(__('Account creation failed. Please try again.', 'integrazo-integration-for-zoho-apps'), $step2_url);
        }
    }
});
