<?php

namespace Formatrica\Admin\Pages;

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

use Formatrica\Admin\Tables\Submission_List_Table;
use Formatrica\Capability\Capabilities;
use Formatrica\Capability\Feature_Gate;
use Formatrica\Submission\Submission_Repository;

/**
 * Submissions admin surface (Free): filterable/searchable list, bulk delete, CSV export. The Pro preview
 * (P4, submissions.preview) rides on top: the UUID opens a native <dialog>
 * fed by the gated REST detail endpoint. Preview affordance is decided
 * SERVER-side per package: wporg renders plain text (hide-not-lock), the full
 * bundle renders locked-with-badge or functional per capability.
 */
final class Submissions_Page
{
    private Submission_Repository $repo;

    public function __construct(?Submission_Repository $repo = null)
    {
        $this->repo = $repo ?? new Submission_Repository();
    }

    /**
     * Preview affordance for the submissions list: 'open' (preview available)
     * | 'locked' (badge, no preview) | 'none' (Free packages — their preview
     * endpoint is stripped, so no badge for a feature that can't unlock).
     */
    public static function preview_mode(): string
    {
        if (defined('FORMATRICA_PACKAGE') && in_array(FORMATRICA_PACKAGE, ['wporg', 'selfhost'], true)) {
            return 'none';
        }
        $gate = Feature_Gate::get_default();
        return ($gate !== null && $gate->has(Capabilities::SUBMISSIONS_PREVIEW)) ? 'open' : 'locked';
    }

    public function render(): void
    {
        if (!current_user_can('manage_options')) {
            wp_die(esc_html__('You do not have permission to access this page.', 'formatrica'));
        }

        $preview_mode = self::preview_mode();
        $table = new Submission_List_Table($this->repo, $preview_mode);
        $table->prepare_items();

        echo '<div class="wrap">';
        echo '<h1 class="wp-heading-inline">' . esc_html__('Submissions', 'formatrica') . '</h1>';
        echo '<hr class="wp-header-end" />';

        $this->render_deleted_notice();

        echo '<form method="get">';
        echo '<input type="hidden" name="page" value="formatrica-submissions" />';
        $table->search_box(__('Search submissions', 'formatrica'), 'formatrica-submission');
        $table->display();
        echo '</form>';

        $this->render_styles();
        $this->render_export_script();

        if ($preview_mode === 'open') {
            $this->render_preview_dialog();
        }

        echo '</div>';
    }

    /**
     * Bulk delete / bulk export from the list checkboxes. Runs on the page's
     * load-{hook} action, BEFORE any output, so the export and post-delete
     * redirects can send headers (a bulk action processed during render()
     * fails with "headers already sent").
     */
    public function load(): void
    {
        if (!current_user_can('manage_options')) {
            return;
        }

        // phpcs:disable WordPress.Security.NonceVerification.Recommended -- verified below before acting
        $action = '';
        foreach (['action', 'action2'] as $key) {
            if (isset($_GET[$key]) && $_GET[$key] !== '-1') {
                $action = sanitize_key(wp_unslash($_GET[$key]));
                break;
            }
        }
        // The tablenav "Export CSV" button posts fmt_export instead of an action.
        if (isset($_GET['fmt_export'])) {
            $action = 'export';
        }
        if ($action === '' || !isset($_GET['submission'])) {
            return;
        }

        check_admin_referer('bulk-submissions');

        $ids = array_map('intval', (array) $_GET['submission']);
        $current_form = isset($_GET['form_id']) ? (int) $_GET['form_id'] : 0;
        $current_status = isset($_GET['status']) ? sanitize_key(wp_unslash($_GET['status'])) : '';
        // phpcs:enable

        if ($action === 'export') {
            // We are on the load-{hook} action (before any output) and the
            // bulk-submissions nonce is already verified, so stream the CSV
            // directly — no redirect to admin-post, no second nonce (which is
            // what produced "the link you followed has expired").
            (new \Formatrica\Admin\Submission_Export_Controller())->export_ids($ids);
            return;
        }

        if ($action === 'mark_read' || $action === 'mark_unread') {
            $mark_status = $action === 'mark_read' ? 'read' : 'new';
            $marked = $this->repo->mark_status($ids, $mark_status);
            $back = add_query_arg(
                array_filter([
                    'page'      => 'formatrica-submissions',
                    'form_id'   => $current_form ?: null,
                    'status'    => $current_status ?: null,
                    'marked'    => $marked > 0 ? $marked : null,
                    'marked_as' => $marked > 0 ? $mark_status : null,
                ]),
                admin_url('admin.php')
            );
            wp_safe_redirect($back);
            exit;
        }

        if ($action === 'delete') {
            $deleted = $this->repo->delete_by_ids($ids);
            $back = add_query_arg(
                array_filter([
                    'page'     => 'formatrica-submissions',
                    'form_id'  => $current_form ?: null,
                    'status'   => $current_status ?: null,
                    'deleted'  => $deleted > 0 ? $deleted : null,
                ]),
                admin_url('admin.php')
            );
            wp_safe_redirect($back);
            exit;
        }
    }

    /**
     * Success notices after a post-action redirect (delete / mark read-unread).
     */
    private function render_deleted_notice(): void
    {
        // phpcs:disable WordPress.Security.NonceVerification.Recommended -- read-only display of redirect flags
        $deleted   = isset($_GET['deleted']) ? (int) $_GET['deleted'] : 0;
        $marked    = isset($_GET['marked']) ? (int) $_GET['marked'] : 0;
        $marked_as = (isset($_GET['marked_as']) && $_GET['marked_as'] === 'read') ? 'read' : 'new';
        // phpcs:enable

        if ($deleted > 0) {
            echo '<div class="notice notice-success is-dismissible"><p>'
                . esc_html(sprintf(
                    /* translators: %d: number of submissions deleted */
                    _n('%d submission deleted.', '%d submissions deleted.', $deleted, 'formatrica'),
                    $deleted
                ))
                . '</p></div>';
        }

        if ($marked > 0) {
            if ($marked_as === 'read') {
                /* translators: %d: number of submissions marked as read */
                $message = _n('%d submission marked as read.', '%d submissions marked as read.', $marked, 'formatrica');
            } else {
                /* translators: %d: number of submissions marked as unread */
                $message = _n('%d submission marked as unread.', '%d submissions marked as unread.', $marked, 'formatrica');
            }
            echo '<div class="notice notice-success is-dismissible"><p>'
                . esc_html(sprintf($message, $marked))
                . '</p></div>';
        }
    }

    /**
     * Enables the tablenav "Export CSV" button only while at least one row is
     * checked. The button submits the list form (fmt_export), so it carries the
     * current filters and selection through to load().
     */
    private function render_export_script(): void
    {
        $script = <<<'JS'
(function () {
    function init() {
        var btn = document.getElementById('fmt-export-selected');
        if (!btn) { return; }
        var form = btn.closest('form');
        if (!form) { return; }
        function sync() {
            btn.disabled = form.querySelectorAll('input[name="submission[]"]:checked').length === 0;
        }
        form.addEventListener('change', sync);
        sync();
    }
    if (document.readyState !== 'loading') { init(); }
    else { document.addEventListener('DOMContentLoaded', init); }
})();
JS;
        // Static admin-page helper JS (dynamic values ride in via wp_json_encode).
        wp_print_inline_script_tag($script);
    }

    private function render_styles(): void
    {
        echo '<style>
            .fmt-status-badge{display:inline-block;font-size:11px;font-weight:700;text-transform:uppercase;padding:1px 7px;border-radius:3px;letter-spacing:.02em;}
            .fmt-status-badge--new{background:#2271b1;color:#fff;}
            .fmt-status-badge--read{background:#dcdcde;color:#50575e;}
            .fmt-pro-badge{font-size:10px;font-weight:700;text-transform:uppercase;color:#8b5cf6;border:1px solid currentColor;border-radius:4px;padding:0 4px;margin-left:4px;vertical-align:middle;}
            dialog.fmt-submission-dialog{width:min(720px,calc(100vw - 2rem));max-height:calc(100vh - 4rem);overflow-y:auto;border:0;border-radius:8px;padding:24px;box-shadow:0 10px 40px rgba(0,0,0,.3);}
            dialog.fmt-submission-dialog::backdrop{background:rgba(0,0,0,.5);}
            .fmt-submission-dialog h2{margin-top:0;padding-right:2rem;}
            .fmt-submission-dialog table{width:100%;border-collapse:collapse;}
            .fmt-submission-dialog th{width:32%;text-align:left;vertical-align:top;padding:8px 10px;border-bottom:1px solid #eee;color:#50575e;}
            .fmt-submission-dialog td{padding:8px 10px;border-bottom:1px solid #eee;word-break:break-word;}
            .fmt-submission-dialog .fmt-dialog-close{position:absolute;top:10px;right:10px;border:0;background:transparent;font-size:20px;cursor:pointer;line-height:1;}
            .fmt-submission-dialog .fmt-dialog-meta{color:#787c82;font-size:12px;margin-top:12px;}
        </style>';
    }

    /**
     * The Pro preview dialog + its loader. Server-rendered only when the
     * capability is live (never in the wporg package), so no Pro affordance
     * leaks into Free surfaces.
     */
    private function render_preview_dialog(): void
    {
        $rest_url = esc_url_raw(rest_url('formatrica/v1/submissions/'));
        $nonce = wp_create_nonce('wp_rest');

        echo '<dialog class="fmt-submission-dialog" id="fmt-submission-dialog" aria-labelledby="fmt-submission-dialog-title">'
            . '<button type="button" class="fmt-dialog-close" aria-label="' . esc_attr__('Close', 'formatrica') . '">&times;</button>'
            . '<h2 id="fmt-submission-dialog-title">' . esc_html__('Submission', 'formatrica') . '</h2>'
            . '<div id="fmt-submission-dialog-body"></div>'
            . '</dialog>';

        $script = <<<'JS'
(function () {
    var dialog = document.getElementById('fmt-submission-dialog');
    if (!dialog || typeof dialog.showModal !== 'function') { return; }
    var body = document.getElementById('fmt-submission-dialog-body');
    var restBase = %REST%;
    var nonce = %NONCE%;

    function esc(value) {
        var div = document.createElement('div');
        div.textContent = value == null ? '' : String(value);
        return div.innerHTML;
    }

    function renderValue(field, value) {
        var type = field && field.type ? field.type : '';
        if (Array.isArray(value)) {
            return value.map(function (v) { return renderValue(field, v); }).join('<br>');
        }
        var str = value == null ? '' : String(value);
        if (type === 'richtext') {
            // Server already re-sanitised through the admin_html context.
            return str;
        }
        if (/^https?:\/\//i.test(str)) {
            return '<a href="' + esc(str) + '" target="_blank" rel="noopener noreferrer">' + esc(str) + '</a>';
        }
        return esc(str);
    }

    function open(id) {
        body.innerHTML = '<p>' + esc(%LOADING%) + '</p>';
        dialog.showModal();
        fetch(restBase + id, { headers: { 'X-WP-Nonce': nonce } })
            .then(function (r) { return r.json().then(function (j) { return { ok: r.ok, json: j }; }); })
            .then(function (res) {
                if (!res.ok) {
                    body.innerHTML = '<p>' + esc(res.json && res.json.message ? res.json.message : 'Error') + '</p>';
                    return;
                }
                var d = res.json;
                var fieldsByName = {};
                (d.form_fields || []).forEach(function (f) { if (f && f.name) { fieldsByName[f.name] = f; } });
                var rows = '';
                Object.keys(d.submitted_data || {}).forEach(function (name) {
                    var field = fieldsByName[name] || null;
                    var label = field && field.label ? field.label : name;
                    rows += '<tr><th>' + esc(label) + '</th><td>' + renderValue(field, d.submitted_data[name]) + '</td></tr>';
                });
                body.innerHTML =
                    '<table>' + rows + '</table>' +
                    '<p class="fmt-dialog-meta">' +
                    esc(d.form_title) + ' &middot; ' + esc(d.created_at) + ' &middot; ' + esc(d.uuid) +
                    (d.ip_address ? ' &middot; IP: ' + esc(d.ip_address) : '') +
                    '</p>';
                var row = document.querySelector('.fmt-submission-preview[data-submission-id="' + id + '"]');
                if (row) {
                    var badge = row.closest('tr') && row.closest('tr').querySelector('.fmt-status-badge--new');
                    if (badge) {
                        badge.classList.remove('fmt-status-badge--new');
                        badge.classList.add('fmt-status-badge--read');
                        badge.textContent = %READ%;
                    }
                }
            })
            .catch(function () { body.innerHTML = '<p>Error</p>'; });
    }

    document.addEventListener('click', function (event) {
        var trigger = event.target.closest('.fmt-submission-preview');
        if (trigger) {
            event.preventDefault();
            open(parseInt(trigger.getAttribute('data-submission-id'), 10));
            return;
        }
        if (event.target === dialog || event.target.closest('.fmt-dialog-close')) {
            dialog.close();
        }
    });
})();
JS;
        $script = str_replace(
            ['%REST%', '%NONCE%', '%LOADING%', '%READ%'],
            [
                wp_json_encode($rest_url),
                wp_json_encode($nonce),
                wp_json_encode(__('Loading…', 'formatrica')),
                wp_json_encode(__('Read', 'formatrica')),
            ],
            $script
        );

        // Static admin-page helper JS (dynamic values ride in via wp_json_encode).
        wp_print_inline_script_tag($script);
    }
}
