<?php
// admin/webhook-admin.php

if (!defined('ABSPATH')) exit;

if (!function_exists('asana_automator_get_webhook_base_url')) {
    function asana_automator_get_webhook_base_url() {
        $override = trim((string) get_option('asana_automator_public_base_url', ''));

        if ($override !== '') {
            return untrailingslashit($override) . '/wp-json/asana-automator/v1/webhook/';
        }

        return rest_url('asana-automator/v1/webhook/');
    }
}

if (!function_exists('asana_automator_get_webhook_target_url')) {
    function asana_automator_get_webhook_target_url($webhook_id) {
        return asana_automator_get_webhook_base_url() . rawurlencode((string) $webhook_id);
    }
}

/* ---------------------------------------------------------------------------
   Admin menu entry
--------------------------------------------------------------------------- */
if (!defined('AFB_AUTOMATOR_EMBEDDED')) {
    add_action('admin_menu', function () {
        add_submenu_page(
            'asana-automator',
            'Webhooks',
            'Webhooks',
            'manage_options',
            'asana-automator-webhooks',
            'asana_automator_webhooks_page'
        );
    });
}

/* ---------------------------------------------------------------------------
   Admin actions (register / delete)
--------------------------------------------------------------------------- */
add_action('admin_init', function () {

    /* ── Save/clear public tunnel URL ── */
    if (isset($_POST['asana_automator_save_tunnel_url']) && current_user_can('manage_options')) {
        check_admin_referer('asana_automator_save_tunnel_url');

        $raw = trim((string) wp_unslash($_POST['asana_automator_public_base_url'] ?? ''));

        if ($raw === '') {
            delete_option('asana_automator_public_base_url');
            update_option('asana_automator_last_register_notice', [
                'type' => 'success',
                'msg'  => 'Public tunnel URL cleared. Webhook target URL will use your site REST URL.',
            ]);
        } else {
            $clean = esc_url_raw($raw);
            $scheme = strtolower((string) parse_url($clean, PHP_URL_SCHEME));
            $host = (string) parse_url($clean, PHP_URL_HOST);

            if ($clean === '' || $scheme !== 'https' || $host === '') {
                update_option('asana_automator_last_register_notice', [
                    'type' => 'error',
                    'msg'  => 'Please enter a valid HTTPS tunnel URL, for example: https://abc123.ngrok-free.app',
                ]);
            } else {
                update_option('asana_automator_public_base_url', untrailingslashit($clean));
                update_option('asana_automator_last_register_notice', [
                    'type' => 'success',
                    'msg'  => 'Public tunnel URL saved. New webhooks will use this target base URL.',
                ]);
            }
        }

        wp_redirect(admin_url('admin.php?page=asana-automator-webhooks'));
        exit;
    }

    /* ── Register new webhook ── */
    if (isset($_POST['asana_automator_register_webhook']) && current_user_can('manage_options')) {
        check_admin_referer('asana_automator_register_webhook');

        $project_gid  = sanitize_text_field($_POST['webhook_project_gid'] ?? '');
        $project_name = sanitize_text_field($_POST['webhook_project_name'] ?? '');
        $pat_label    = sanitize_text_field($_POST['webhook_pat_label'] ?? '');

        if ($project_gid && $pat_label) {
            $webhook_id = 'wh_' . substr(md5($project_gid . microtime()), 0, 12);
            $target_url = asana_automator_get_webhook_target_url($webhook_id);

            // Asana requires an HTTPS target. If this site isn't served over HTTPS
            // (local dev), abort here and show a helpful admin notice instead
            $scheme = strtolower((string) parse_url($target_url, PHP_URL_SCHEME));
            if (strtolower($scheme) !== 'https') {
                $msg = 'Asana requires webhook target URLs to begin with https://. Your endpoint is: ' . $target_url . '.\n' .
                       'For local development expose your site using a public HTTPS tunnel (for example: https://ngrok.com) and then retry.';
                update_option('asana_automator_last_register_notice', ['type' => 'error', 'msg' => $msg]);
                wp_redirect(admin_url('admin.php?page=asana-automator-webhooks'));
                exit;
            }

            $token = asana_automator_get_pat_token($pat_label);

            if ($token) {
                // Persist a pending webhook record before calling Asana.
                // Asana performs a handshake POST during registration and this allows
                // the endpoint to find the webhook ID and return X-Hook-Secret.
                $webhooks = get_option('asana_automator_webhooks', []);
                $webhooks[$webhook_id] = [
                    'asana_gid'        => '',
                    'project_gid'      => $project_gid,
                    'project_name'     => $project_name,
                    'pat_label'        => $pat_label,
                    'target_url'       => $target_url,
                    'secret'           => '',
                    'handshake_status' => 'pending',
                    'created_at'       => date('c'),
                ];
                update_option('asana_automator_webhooks', $webhooks);

                $res = wp_remote_post('https://app.asana.com/api/1.0/webhooks', [
                    'headers' => [
                        'Authorization' => 'Bearer ' . $token,
                        'Content-Type'  => 'application/json',
                    ],
                    'body' => json_encode([
                        'data' => [
                            'resource' => $project_gid,
                            'target'   => $target_url,
                            'filters'  => [
                                ['resource_type' => 'task', 'action' => 'changed'],
                                ['resource_type' => 'story', 'action' => 'added'],
                            ],
                        ],
                    ]),
                ]);

                if (is_wp_error($res)) {
                    $webhooks = get_option('asana_automator_webhooks', []);
                    unset($webhooks[$webhook_id]);
                    update_option('asana_automator_webhooks', $webhooks);

                    $msg = 'Asana API request failed: ' . $res->get_error_message();
                    error_log('asana-automator: ' . $msg);
                    update_option('asana_automator_last_register_notice', ['type' => 'error', 'msg' => $msg]);
                } else {
                    $code = wp_remote_retrieve_response_code($res);
                    $body = wp_remote_retrieve_body($res);
                    $decoded = json_decode($body, true);
                    $data = $decoded['data'] ?? [];

                    if (!empty($data['gid'])) {
                        $asana_gid = sanitize_text_field((string)$data['gid']);

                        // Store Asana GID out-of-band first. This avoids racing with
                        // handshake writes that set the webhook secret.
                        $pending_gids = get_option('asana_automator_webhook_pending_gids', []);
                        if (!is_array($pending_gids)) {
                            $pending_gids = [];
                        }
                        $pending_gids[$webhook_id] = $asana_gid;
                        update_option('asana_automator_webhook_pending_gids', $pending_gids);

                        // If handshake already populated secret, we can safely persist
                        // the Asana GID directly into the webhook record now.
                        $webhooks = get_option('asana_automator_webhooks', []);
                        $existing = (array)($webhooks[$webhook_id] ?? []);

                        if (!empty($existing['secret'])) {
                            $webhooks[$webhook_id] = array_merge($existing, [
                                'asana_gid'    => $asana_gid,
                                'project_gid'  => $project_gid,
                                'project_name' => $project_name,
                                'pat_label'    => $pat_label,
                                'target_url'   => $target_url,
                                'created_at'   => $existing['created_at'] ?? date('c'),
                            ]);

                            if (empty($webhooks[$webhook_id]['handshake_status'])) {
                                $webhooks[$webhook_id]['handshake_status'] = 'confirmed';
                            }

                            update_option('asana_automator_webhooks', $webhooks);

                            unset($pending_gids[$webhook_id]);
                            update_option('asana_automator_webhook_pending_gids', $pending_gids);
                        }

                        $msg = 'Webhook registered successfully (Asana GID: ' . $data['gid'] . ')';
                        update_option('asana_automator_last_register_notice', ['type' => 'success', 'msg' => $msg]);
                    } else {
                        $webhooks = get_option('asana_automator_webhooks', []);
                        unset($webhooks[$webhook_id]);
                        update_option('asana_automator_webhooks', $webhooks);

                        $sample = substr($body, 0, 1000);
                        $msg = 'Asana API did not return webhook GID. HTTP ' . $code . ' response: ' . $sample;
                        error_log('asana-automator: ' . $msg);
                        update_option('asana_automator_last_register_notice', ['type' => 'error', 'msg' => $msg]);
                    }
                }
            } else {
                update_option('asana_automator_last_register_notice', [
                    'type' => 'error',
                    'msg'  => 'No PAT token found for the selected account.',
                ]);
            }
        }

        wp_redirect(admin_url('admin.php?page=asana-automator-webhooks'));
        exit;
    }

    /* ── Delete webhook ── */
    if (isset($_GET['delete_webhook']) && current_user_can('manage_options')) {
        $webhook_id = sanitize_key($_GET['delete_webhook']);
        check_admin_referer('asana_automator_delete_webhook_' . $webhook_id);

        $webhooks = get_option('asana_automator_webhooks', []);
        $pending_gids = get_option('asana_automator_webhook_pending_gids', []);
        if (!is_array($pending_gids)) {
            $pending_gids = [];
        }

        if (isset($webhooks[$webhook_id])) {
            $asana_gid = $webhooks[$webhook_id]['asana_gid'] ?? '';
            if ($asana_gid === '' && !empty($pending_gids[$webhook_id])) {
                $asana_gid = sanitize_text_field((string)$pending_gids[$webhook_id]);
            }
            $pat_label = $webhooks[$webhook_id]['pat_label'] ?? '';

            // Tell Asana to remove the webhook
            if ($asana_gid) {
                $token = asana_automator_get_pat_token((string) $pat_label);
                if ($token) {
                    wp_remote_request(
                        "https://app.asana.com/api/1.0/webhooks/{$asana_gid}",
                        [
                            'method'  => 'DELETE',
                            'headers' => ['Authorization' => 'Bearer ' . $token],
                        ]
                    );
                }
            }

            unset($webhooks[$webhook_id]);
            update_option('asana_automator_webhooks', $webhooks);
        }

        if (isset($pending_gids[$webhook_id])) {
            unset($pending_gids[$webhook_id]);
            update_option('asana_automator_webhook_pending_gids', $pending_gids);
        }

        wp_redirect(admin_url('admin.php?page=asana-automator-webhooks'));
        exit;
    }
});

/* ---------------------------------------------------------------------------
   Page render
--------------------------------------------------------------------------- */
function asana_automator_webhooks_page() {
    $webhooks     = get_option('asana_automator_webhooks', []);
    $pat_accounts = asana_automator_get_pat_accounts();
    $tunnel_base  = trim((string) get_option('asana_automator_public_base_url', ''));

    $home_url  = home_url('/');
    $home_host = (string) parse_url($home_url, PHP_URL_HOST);
    $home_port = (string) parse_url($home_url, PHP_URL_PORT);
    $local_target = $home_host !== '' ? $home_host . ($home_port !== '' ? ':' . $home_port : '') : '127.0.0.1:80';
    $ngrok_cmd = 'ngrok http --host-header=rewrite ' . $local_target;

    $effective_base = asana_automator_get_webhook_base_url();
    $base_scheme = strtolower((string) parse_url($effective_base, PHP_URL_SCHEME));
    ?>
    <div class="wrap">
        <?php
        $last = get_option('asana_automator_last_register_notice');
        if (!empty($last) && is_array($last)) {
            $class = ($last['type'] === 'success') ? 'updated' : 'error';
            echo '<div class="' . esc_attr($class) . ' notice is-dismissible"><p>' . esc_html($last['msg']) . '</p></div>';
            delete_option('asana_automator_last_register_notice');
        }
        ?>
        <h1>🔗 Asana Webhooks</h1>
        <p>
            Webhooks receive real-time task events from Asana.
            Currently used for <strong>completion cleanup rules</strong> and <strong>comment-triggered client email rules</strong>.
        </p>
        <p>
            If a webhook was created before comment support was added, delete and re-register it so the
            <code>story added</code> event filter is included.
        </p>
        <p>
            <strong>Your webhook endpoint base URL:</strong>
            <code><?php echo esc_html($effective_base); ?></code>
        </p>
        <p>
            <strong>WordPress REST base URL:</strong>
            <code><?php echo esc_html(rest_url('asana-automator/v1/webhook/')); ?></code>
        </p>

        <hr style="margin:20px 0;">

        <h2>Local Tunnel Helper (ngrok)</h2>
        <p>Use this helper to expose your local site with HTTPS so Asana can reach your webhook endpoint.</p>
        <ol style="margin-left:20px;">
            <li>Run this command in a terminal:</li>
        </ol>
        <input type="text" readonly style="width:520px;" value="<?php echo esc_attr($ngrok_cmd); ?>">
        <ol start="2" style="margin-left:20px; margin-top:10px;">
            <li>From ngrok output, copy the <strong>HTTPS Forwarding</strong> URL (for example <code>https://abc123.ngrok-free.app</code>).</li>
            <li>Paste it below and save. New webhook registrations will use it as the target base URL.</li>
        </ol>

        <form method="post" style="margin-top:10px;">
            <?php wp_nonce_field('asana_automator_save_tunnel_url'); ?>
            <table class="form-table" style="margin-top:0;">
                <tr>
                    <th><label for="asana_automator_public_base_url">Public Tunnel Base URL</label></th>
                    <td>
                        <input
                            type="url"
                            id="asana_automator_public_base_url"
                            name="asana_automator_public_base_url"
                            placeholder="https://abc123.ngrok-free.app"
                            value="<?php echo esc_attr($tunnel_base); ?>"
                            style="width:420px;"
                        >
                        <p class="description">Leave empty and save to use your default WordPress REST URL.</p>
                    </td>
                </tr>
            </table>
            <?php submit_button('Save Tunnel URL', 'secondary', 'asana_automator_save_tunnel_url', false); ?>
        </form>

        <?php
        if (strtolower($base_scheme) !== 'https') :
        ?>
            <p style="color:orange;">
                ⚠️ Asana requires webhook endpoints to be public HTTPS URLs. Set a tunnel URL above, or move this site to HTTPS, then register the webhook.
            </p>
        <?php endif; ?>

        <?php if (!empty($webhooks)): ?>
            <h2>Active Webhooks</h2>
            <table class="widefat striped" style="max-width:1000px;">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>Project</th>
                        <th>PAT</th>
                        <th>Handshake</th>
                        <th>Registered</th>
                        <th>Actions</th>
                    </tr>
                </thead>
                <tbody>
                <?php foreach ($webhooks as $wh_id => $wh): ?>
                    <tr>
                        <td><code><?php echo esc_html($wh_id); ?></code></td>
                        <td><?php echo esc_html($wh['project_name'] ?? $wh['project_gid'] ?? '—'); ?></td>
                        <td><?php echo esc_html($wh['pat_label'] ?? '—'); ?></td>
                        <td>
                            <?php if (!empty($wh['secret'])): ?>
                                <span style="color:green;">✅ Confirmed</span>
                            <?php else: ?>
                                <span style="color:orange;">⏳ Pending</span>
                            <?php endif; ?>
                        </td>
                        <td><?php echo esc_html($wh['created_at'] ?? '—'); ?></td>
                        <td>
                            <?php
                            $del_url = wp_nonce_url(
                                admin_url('admin.php?page=asana-automator-webhooks&delete_webhook=' . urlencode($wh_id)),
                                'asana_automator_delete_webhook_' . $wh_id
                            );
                            ?>
                            <a href="<?php echo esc_url($del_url); ?>" class="button button-small"
                               onclick="return confirm('Delete this webhook from Asana?');">🗑 Delete</a>
                        </td>
                    </tr>
                <?php endforeach; ?>
                </tbody>
            </table>
        <?php else: ?>
            <p>No webhooks registered yet.</p>
        <?php endif; ?>

        <hr style="margin:30px 0;">

        <h2>Register New Webhook</h2>
        <?php if (empty($pat_accounts)): ?>
            <p style="color:red;">⚠️ No PAT accounts configured. <a href="<?php echo admin_url('admin.php?page=asana-automator'); ?>">Add one first.</a></p>
        <?php else: ?>
        <form method="post">
            <?php wp_nonce_field('asana_automator_register_webhook'); ?>
            <table class="form-table">
                <tr>
                    <th><label for="webhook_pat_label">PAT Account</label></th>
                    <td>
                        <select name="webhook_pat_label" id="webhook_pat_label" required>
                            <?php foreach ($pat_accounts as $label => $_): ?>
                                <option value="<?php echo esc_attr($label); ?>"><?php echo esc_html($label); ?></option>
                            <?php endforeach; ?>
                        </select>
                    </td>
                </tr>
                <tr>
                    <th><label>Project</label></th>
                    <td>
                        <button type="button" class="button button-secondary" id="wh-fetch-projects">🔄 Fetch Projects</button>
                        <br><br>
                        <select name="webhook_project_gid" id="wh-project-select" style="width:350px;" required>
                            <option value="">— Select a project —</option>
                        </select>
                        <input type="hidden" name="webhook_project_name" id="wh-project-name">
                        <p id="wh-project-status" style="display:none; margin-top:6px;"></p>
                    </td>
                </tr>
            </table>
            <?php submit_button('➕ Register Webhook', 'primary', 'asana_automator_register_webhook'); ?>
        </form>
        <?php endif; ?>
    </div>

    <script>
    (function ($) {
        var $btn    = $('#wh-fetch-projects');
        var $sel    = $('#wh-project-select');
        var $status = $('#wh-project-status');

        $btn.on('click', function () {
            $btn.prop('disabled', true).text('⏳ Fetching…');
            $status.text('').hide();

            $.ajax({
                url:      ajaxurl,
                type:     'GET',
                data:     { action: 'get_asana_projects' },
                dataType: 'text'
            })
            .done(function (raw) {
                try {
                    var rsp;
                    var txt = String(raw || '');

                    // Be tolerant of stray output from other plugins/themes.
                    txt = txt.replace(/^\uFEFF/, '').trim();
                    txt = txt.replace(/^;+/, '').replace(/;+$/, '').trim();

                    rsp = JSON.parse(txt);
                    console.debug('get_asana_projects response:', rsp);
                    $sel.empty();
                    $sel.append($('<option>').val('').text('— Select a project —'));

                    if (!rsp || !rsp.success) {
                        var msg = (rsp && rsp.data) ? (typeof rsp.data === 'string' ? rsp.data : JSON.stringify(rsp.data)) : 'No projects returned';
                        $status.text('⚠️ ' + msg).show();
                        return;
                    }

                    if (!Array.isArray(rsp.data) || rsp.data.length === 0) {
                        $status.text('⚠️ No projects found in this workspace.').show();
                        return;
                    }

                    rsp.data.forEach(function (p) {
                        var gid = p.gid || p.id || '';
                        var name = p.name || p.title || gid;
                        if (!gid) return; // skip malformed
                        var $opt = $('<option>').val(gid).text(name);
                        $sel.append($opt);
                    });

                    $status.text('✅ ' + rsp.data.length + ' project(s) loaded.').show();
                    console.debug('Projects appended to select:', $sel.find('option').length);

                    // If the select is enhanced by select2/chosen, trigger updates
                    try {
                        $sel.trigger('change');
                        if ($.fn.select2) $sel.trigger('change.select2');
                        if ($.fn.chosen) $sel.trigger('chosen:updated');
                    } catch (e) {
                        /* ignore */
                    }
                } catch (e) {
                    console.error('Error processing projects response', e, raw);
                    $status.text('❌ Error processing response; check console.').show();
                }
            })
            .fail(function (xhr, status, err) {
                console.error('AJAX error:', status, err, xhr && xhr.responseText);
                $status.text('❌ AJAX request failed (HTTP ' + (xhr.status||'N/A') + '). Check the browser console.').show();
            })
            .always(function () {
                $btn.prop('disabled', false).text('🔄 Fetch Projects');
            });
        });

        $sel.on('change', function () {
            $('#wh-project-name').val($(this).find('option:selected').text());
        });
    })(jQuery);
    </script>
    <?php
}
