<?php

namespace GriffinForms\Admin\Html\Pages\Lists;

use GriffinForms\Includes\Integrations\Providers;

class Submissions extends \GriffinForms\Admin\Html\Pages\Lists\Format
{   
    protected $meta;
    protected $sql;
    protected $inline_js;
    protected $form_id = '';
    protected $status = '';
    
    protected function setType()
    {
        $this->type = 'submission';
    }

    protected function checkBoxCell($index, $list_column, $item)
    {
        echo '<th scope="row" class="check-column">';
        echo '<input id="cb-select-' . absint($item->id) . '" type="checkbox"';
        echo ' class="griffinforms-listitem-cb"';
        echo ' value="' . absint($item->id) . '"';
        echo ' data-gf-form-id="' . absint($item->form_id) . '">';
        echo '</th>';
    }
    
    protected function setFilterNames()
    {
        $this->filter_names = array(
            'form_id',
            'status',
            'edited',
            'is_read',
            'search',
            'date_from',
            'date_to',
        );
    }

    protected function setFilterLinks()
    {
        $this->filter_links = array('all', 'complete', 'incomplete', 'edited', 'read', 'unread');
    }

    protected function registerColumns(): void
    {
        $r = $this->column_registry;

        $r->register('submission', 'checkbox',      ['label' => '',                                                     'locked' => true, 'default_on' => true]);
        $r->register('submission', 'pseudonym',     ['label' => $this->lang->getText('pseudonym', 'list_head'),         'locked' => true, 'default_on' => true]);

        $r->register('submission', 'readstatus',     ['label' => __('Read Status', 'griffinforms-form-builder'),          'default_on' => true]);
        $r->register('submission', 'signals',       ['label' => __('Signals', 'griffinforms-form-builder'),             'default_on' => true]);
        $r->register('submission', 'filecount',     ['label' => $this->lang->getText('filecount', 'list_head'),         'default_on' => true]);
        $r->register('submission', 'status',        ['label' => $this->lang->getText('status', 'list_head'),            'default_on' => true, 'sortable' => true]);
        $r->register('submission', 'revisions',     ['label' => $this->lang->getText('revisions', 'list_head'),         'default_on' => true]);
        $r->register('submission', 'form',          ['label' => $this->lang->getText('form', 'list_head'),              'default_on' => true]);
        $r->register('submission', 'compliance',    ['label' => $this->lang->getText('compliance', 'list_head'),        'default_on' => true]);
        $r->register('submission', 'author',        ['label' => $this->lang->getText('author', 'list_head'),            'default_on' => true,
            'variants' => [
                'default'  => __('Username + full name', 'griffinforms-form-builder'),
                'nicename' => __('Username only', 'griffinforms-form-builder'),
                'fullname' => __('Full name only', 'griffinforms-form-builder'),
            ],
            'default_variant' => 'default',
        ]);
        $r->register('submission', 'created',       ['label' => $this->lang->getText('created', 'list_head'),           'default_on' => true, 'sortable' => true]);

        $r->register('submission', 'id',            ['label' => __('ID', 'griffinforms-form-builder'),                  'default_on' => false]);
        $r->register('submission', 'submissionip',  ['label' => __('IP Address', 'griffinforms-form-builder'),          'default_on' => false]);
        $r->register('submission', 'sourceurl',     ['label' => __('Source Page', 'griffinforms-form-builder'),         'default_on' => false]);
        $r->register('submission', 'paymentstatus', ['label' => __('Payment Status', 'griffinforms-form-builder'),      'default_on' => false]);
        $r->register('submission', 'lastedited',    ['label' => __('Last Edited', 'griffinforms-form-builder'),         'default_on' => false, 'sortable' => true]);
        $r->register('submission', 'lasteditor',   ['label' => __('Last Editor', 'griffinforms-form-builder'),         'default_on' => false,
            'variants' => [
                'default'  => __('Username + full name', 'griffinforms-form-builder'),
                'nicename' => __('Username only', 'griffinforms-form-builder'),
            ],
            'default_variant' => 'default',
        ]);

        parent::registerColumns();
    }

    protected function getListFilters()
    {
        $filters = parent::getListFilters();
        if (!isset($filters['is_read']) && isset($_GET['is_read']) && $_GET['is_read'] !== '') {
            $filters['is_read'] = sanitize_text_field(wp_unslash($_GET['is_read']));
        }
        return $filters;
    }

    protected function setFormId()
    {
        if (isset($_GET['form_id'])) {
            $this->form_id = absint(wp_unslash($_GET['form_id']));
        }
    }
    
    protected function setBulkActions()
    {
        $actions = apply_filters(
            'griffinforms_submissions_bulk_actions',
            [
                'deleteItems' => __('Delete', 'griffinforms-form-builder'),
                'markRead'    => __('Mark Read', 'griffinforms-form-builder'),
                'markUnread'  => __('Mark Unread', 'griffinforms-form-builder'),
            ]
        );

        $this->bulk_actions = is_array($actions) ? $actions : [];

        // Locked discoverability: if Pro hasn't added a live export action, show a disabled placeholder.
        if (!isset($this->bulk_actions['gfpro_export'])) {
            $upsell = \GriffinForms\Includes\Upsells\UpsellRegistry::getInstance();
            if ($upsell->shouldRenderLockedShell('submission_export')) {
                $this->bulk_actions['gfpro_export_locked'] = [
                    'label'    => __('Download (Pro)', 'griffinforms-form-builder'),
                    'disabled' => true,
                ];
            }
        }
    }

    protected function setRowActions()
    {
        $actions = apply_filters(
            'griffinforms_submissions_row_actions',
            ['view', 'markread', 'trash']
        );

        $this->row_actions = is_array($actions) ? $actions : [];

        // Locked discoverability: if Pro hasn't added a live export row action, show a locked placeholder.
        if (!in_array('gfpro_export', $this->row_actions, true)) {
            $upsell = \GriffinForms\Includes\Upsells\UpsellRegistry::getInstance();
            if ($upsell->shouldRenderLockedShell('submission_export')) {
                $this->row_actions[] = 'gfpro_export_locked';
            }
        }
    }

    protected function pageModals()
    {
        $this->deleteItemsModal();
        $this->deleteListItemModal();
        $this->exportLockedModal();
        do_action('griffinforms_submissions_page_modals');
        (new \GriffinForms\Admin\Html\Modals\ColumnManager())->html();
    }

    protected function exportLockedModal()
    {
        $upsell = \GriffinForms\Includes\Upsells\UpsellRegistry::getInstance();
        if (!$upsell->shouldRenderLockedShell('submission_export')) {
            return;
        }
        if (!$upsell->isDiscoverabilityEnabled()) {
            return;
        }

        echo '<div class="modal fade" id="griffinforms-gfpro_export_locked-modal" tabindex="-1">';
        echo '<div class="modal-dialog modal-dialog-centered">';
        echo '<div class="modal-content rounded-2 border-0">';
        echo '<div class="modal-header border-bottom-0">';
        echo '<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="' . esc_attr__('Close', 'griffinforms-form-builder') . '"></button>';
        echo '</div>';
        echo '<div class="modal-body">';
        $upsell->render('submission_export', 'card');
        echo '</div>';
        echo '</div></div></div>';
    }

    protected function rowActionGfproExportLocked($item)
    {
        $upsell = \GriffinForms\Includes\Upsells\UpsellRegistry::getInstance();
        $vm     = $upsell->getViewModel('submission_export', 'card');
        $url    = esc_url($vm['cta_url'] ?? '');
        $label  = esc_html__('Download', 'griffinforms-form-builder');
        $title  = esc_attr__('Upgrade to GriffinForms Pro to export submissions', 'griffinforms-form-builder');
        echo '<a href="' . $url . '" class="gf-pro-locked-action" title="' . $title . '" aria-label="' . $title . '">';
        echo $label . ' <span class="gf-pro-badge-inline">Pro</span>';
        echo '</a>';
    }

    protected function rowActionView($item)
    {
        echo '<a href="' . esc_url($this->getItemUrl($item)) . '">' . esc_html($this->lang->getText('view', 'row_action')) . '</a>';
    }

    protected function rowActionMarkread($item)
    {
        $nonce    = wp_create_nonce('griffinforms_mark_submission_read');
        $is_read  = isset($item->is_read) && (bool) $item->is_read;
        $value    = $is_read ? 0 : 1;
        $label    = $is_read
            ? esc_html__('Mark Unread', 'griffinforms-form-builder')
            : esc_html__('Mark Read', 'griffinforms-form-builder');

        echo '<a href="#"'
            . ' class="gf-mark-read-btn"'
            . ' data-gf-id="' . absint($item->id) . '"'
            . ' data-gf-value="' . absint($value) . '"'
            . ' data-gf-nonce="' . esc_attr($nonce) . '">'
            . $label
            . '</a>';
    }

    protected function addNewButton()
    {
    }
    
    protected function statusFilterLink($status)
    {
        $data = array_filter($this->getListArgs());
        $data['filters']['status'] = $status;
        $count = $this->sql->resultsCount($data);
        $url = $this->createUrl($data);
        $link_class = '';
        
        $status_param = isset($_GET['status']) ? sanitize_text_field(wp_unslash($_GET['status'])) : '';
        if ($status_param === $status) {
            $link_class = 'current'; 
        }
        
        echo '<a href="' . esc_url($url) . '" class="' . esc_attr($link_class) . '" aria-current="page">';
        echo esc_html($this->lang->getText('status' . $status . 'Filter'));
        echo '<span class="count"> (';
        echo absint($count);
        echo ')</span>';
        echo '</a>';
    }
    
    protected function completeFilterLink()
    {
        $this->statusFilterLink("complete");
    }
    
    protected function incompleteFilterLink()
    {
        $this->statusFilterLink("incomplete");
    }

    protected function readFilterLink()
    {
        $this->isReadFilterLink(1);
    }

    protected function unreadFilterLink()
    {
        $this->isReadFilterLink(0);
    }

    protected function isReadFilterLink(int $value)
    {
        $data = array_filter($this->getListArgs());
        $data['filters']['is_read'] = $value;
        unset($data['filters']['status'], $data['filters']['edited']);
        $count = $this->sql->resultsCount($data);
        $url   = $this->createUrl($data);

        $is_read_param = isset($_GET['is_read']) ? $_GET['is_read'] : null;
        $link_class    = ($is_read_param !== null && (int) $is_read_param === $value) ? 'current' : '';
        $label         = $value === 1
            ? esc_html($this->lang->getText('read', 'filter_link'))
            : esc_html($this->lang->getText('unread', 'filter_link'));

        echo '<a href="' . esc_url($url) . '" class="' . esc_attr($link_class) . '" aria-current="page">';
        echo $label;
        echo '<span class="count"> (' . absint($count) . ')</span>';
        echo '</a>';
    }

    protected function editedFilterLink()
    {
        $data = array_filter($this->getListArgs());
        $data['filters']['edited'] = '1';
        unset($data['filters']['status']);
        $count = $this->sql->resultsCount($data);
        $url = $this->createUrl($data);

        $edited_param = isset($_GET['edited']) ? sanitize_text_field(wp_unslash($_GET['edited'])) : '';
        $link_class = $edited_param === '1' ? 'current' : '';

        echo '<a href="' . esc_url($url) . '" class="' . esc_attr($link_class) . '" aria-current="page">';
        echo esc_html($this->lang->getText('statuseditedFilter'));
        echo '<span class="count"> (' . absint($count) . ')</span>';
        echo '</a>';
    }
    
    protected function itemFilters()
    {
        echo '<div class="alignleft actions">';
        $this->formFilter();
        $this->dateFilter();
        echo '</div>';
    }
    
    protected function formFilter()
    {
        $form_filter = new \GriffinForms\Admin\Html\FormControls\Submissions\FormFilter('form_filter', $this->form_id);
        $form_filter->html();
    }
    
    protected function statusHeadingText($list_column)
    {
        echo '<span>' . esc_html__('Status', 'griffinforms-form-builder') . '</span>';
    }
    
    protected function fileCountHeadingText($list_column)
    {
        echo '<span>' . esc_html__('Attachments', 'griffinforms-form-builder') . '</span>';
    }

    protected function fileCountCellText($list_column, $item)
    {
        $submission_id = isset($item->id) ? (int) $item->id : 0;
        $count = 0;
        if ($submission_id > 0 && isset($this->sql) && method_exists($this->sql, 'getAttachmentCountBySubmissionId')) {
            $count = (int) $this->sql->getAttachmentCountBySubmissionId($submission_id);
        }
        if ($count > 0) {
            $size = 0;
            if (isset($this->sql) && method_exists($this->sql, 'getTotalAttachmentSizeBySubmissionId')) {
                $size = (int) $this->sql->getTotalAttachmentSizeBySubmissionId($submission_id);
            }
            echo '<span class="badge text-bg-secondary">' . absint($count) . '</span>';
            if ($size > 0) {
                $formatted_size = \GriffinForms\Admin\Units::getInstance()->formatBytes($size);
                echo '<span class="small text-muted ms-1">(' . esc_html($formatted_size) . ')</span>';
            }
        } else {
            echo '<span class="text-muted">—</span>';
        }
    }
    
    protected function pseudonymCellText($list_column, $item)
    {
        $submission_name = $this->sql->getSubmissionDisplayName($item->id);
        echo esc_html($submission_name);
    }

    protected function readstatusHeadingText($list_column)
    {
        echo '<span class="screen-reader-text">' . esc_html__('Read Status', 'griffinforms-form-builder') . '</span>';
    }

    protected function readstatusCell($index, $list_column, $item)
    {
        $is_unread = isset($item->is_read) && ! (bool) $item->is_read;
        echo '<td class="column-readstatus">';
        if ($is_unread) {
            echo sprintf(
                '<span class="gf-submissions-signal gf-submissions-signal-unread" title="%s" aria-label="%s"></span>',
                esc_attr__('Unread', 'griffinforms-form-builder'),
                esc_attr__('Unread', 'griffinforms-form-builder')
            );
        } else {
            echo '<span class="gf-submissions-signal-placeholder" aria-hidden="true">—</span>';
        }
        echo '</td>';
    }

    protected function signalsHeadingText($list_column)
    {
        echo '<span class="screen-reader-text">' . esc_html__('Signals', 'griffinforms-form-builder') . '</span>';
    }

    protected function signalsCellText($list_column, $item)
    {
        $signals = [];

        if (!empty($item->id) && (int) $this->sql->getAttachmentCountBySubmissionId((int) $item->id) > 0) {
            $signals[] = sprintf(
                '<span class="gf-submissions-signal gf-submissions-signal-attachments" title="%s" aria-label="%s"><img src="%s" alt="" width="16" height="16" loading="lazy" decoding="async" /></span>',
                esc_attr__('Has attachments', 'griffinforms-form-builder'),
                esc_attr__('Has attachments', 'griffinforms-form-builder'),
                esc_url($this->config->getRootUrl() . 'admin/images/icons/paperclip.svg')
            );
        }

        if (!empty($item->is_payment_form)) {
            $payment_gateway = $this->resolveSubmissionPaymentGateway($item);
            $payment_provider = $this->getSubmissionPaymentProviderMeta($payment_gateway);
            $payment_status = isset($item->payment_status) ? sanitize_key((string) $item->payment_status) : '';
            if ($payment_status === 'pending') {
                $payment_title = __('Pending payment', 'griffinforms-form-builder');
                $payment_icon = $this->config->getRootUrl() . 'admin/images/log-timeline-icons/payment-integration-pending.svg';
            } else {
                $payment_title = !empty($payment_provider['name'])
                    ? sprintf(
                        /* translators: %s: payment provider name */
                        __('Paid submission via %s', 'griffinforms-form-builder'),
                        $payment_provider['name']
                    )
                    : __('Has payment', 'griffinforms-form-builder');
                $payment_icon = !empty($payment_provider['icon'])
                    ? $payment_provider['icon']
                    : ($this->config->getRootUrl() . 'admin/images/icons/payment.svg');
            }
            $signals[] = sprintf(
                '<span class="gf-submissions-signal gf-submissions-signal-payment" title="%s" aria-label="%s"><img src="%s" alt="" width="16" height="16" loading="lazy" decoding="async" /></span>',
                esc_attr($payment_title),
                esc_attr($payment_title),
                esc_url($payment_icon)
            );
        }

        if ($this->submissionHasAccountsActivity($item)) {
            $signals[] = sprintf(
                '<span class="gf-submissions-signal gf-submissions-signal-accounts" title="%s" aria-label="%s"><img src="%s" alt="" width="16" height="16" loading="lazy" decoding="async" /></span>',
                esc_attr__('Submission recorded user registration activity', 'griffinforms-form-builder'),
                esc_attr__('Submission recorded user registration activity', 'griffinforms-form-builder'),
                esc_url($this->config->getRootUrl() . 'admin/images/icons/accounts.svg')
            );
        }

        $mailchimp_signal = $this->getSubmissionMailchimpSignal($item);
        if (!empty($mailchimp_signal)) {
            $signals[] = $mailchimp_signal;
        }

        $klaviyo_signal = $this->getSubmissionKlaviyoSignal($item);
        if (!empty($klaviyo_signal)) {
            $signals[] = $klaviyo_signal;
        }

        $google_sheets_signal = $this->getSubmissionGoogleSheetsSignal($item);
        if (!empty($google_sheets_signal)) {
            $signals[] = $google_sheets_signal;
        }

        if (empty($signals)) {
            echo '<span class="gf-submissions-signal-placeholder" aria-hidden="true">—</span>';
            return;
        }

        echo '<div class="gf-submissions-signals-wrap">';
        echo wp_kses_post(implode('', $signals));
        echo '</div>';
    }

    protected function resolveSubmissionPaymentGateway($item): string
    {
        if (!is_object($item)) {
            return '';
        }

        $payment_meta = $this->decodeSubmissionPaymentMeta($item->payment_meta ?? '');
        if (!is_array($payment_meta) || empty($payment_meta)) {
            return '';
        }

        // Pick the most recently updated gateway entry — handles mid-flow gateway switches.
        // PayPal/Stripe store updated_at as a Unix timestamp; Square as a MySQL datetime string.
        $latest = '';
        $latest_ts = 0;
        foreach (['paypal', 'stripe', 'square'] as $gw) {
            if (empty($payment_meta[$gw])) {
                continue;
            }
            $raw = $payment_meta[$gw]['updated_at'] ?? 0;
            $ts  = is_numeric($raw) ? (int) $raw : (int) strtotime((string) $raw);
            if ($ts > $latest_ts) {
                $latest_ts = $ts;
                $latest    = $gw;
            }
        }

        if ($latest !== '') {
            return $latest;
        }

        if (!empty($payment_meta['gateway'])) {
            return sanitize_key((string) $payment_meta['gateway']);
        }

        return '';
    }

    protected function decodeSubmissionPaymentMeta($value): array
    {
        if (is_array($value)) {
            return $value;
        }

        if (!is_string($value) || $value === '') {
            return [];
        }

        $decoded = json_decode($value, true);
        if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
            return $decoded;
        }

        $maybe = maybe_unserialize($value);
        return is_array($maybe) ? $maybe : [];
    }

    protected function getSubmissionPaymentProviderMeta(string $gateway): array
    {
        if ($gateway === '') {
            return [];
        }

        $provider = Providers::getInstance()->get($gateway, false);
        return is_array($provider) ? $provider : [];
    }
    
    protected function formCellText($list_column, $item)
    {
        $form_name = $this->sql->getItemValue($item->form_id, 'name', 'form');

        if (!empty($form_name)) {
            echo esc_html($form_name);
        } else {
            if ($this->sql->itemExists('form', $item->form_id)) {
                echo esc_html($this->lang->formPseudonym($item->form_id));  
            } else {
                echo '<span class="text-muted">';
                echo esc_html($this->lang->getText('form_does_not_exists'));
                echo '</span>';
            }
        }
    }
    
    protected function statusCellText($list_column, $item)
    {
        if ($item->status) {
            /* translators: Indicates that the submission was successful */
            echo '<span class="badge text-bg-success">' . esc_html__('Complete', 'griffinforms-form-builder') . '</span>';
        } else {
            /* translators: Indicates that the submission was unsuccessful or incomplete */
            echo '<span class="badge text-bg-secondary">' . esc_html__('Incomplete', 'griffinforms-form-builder') . '</span>';
        }
    }

    protected function complianceCellText($list_column, $item)
    {
        $raw_meta = isset($item->submission_meta) ? $item->submission_meta : '';
        $decoded = $this->maybeDecode($raw_meta);
        $compliance = is_array($decoded) && isset($decoded['compliance']) && is_array($decoded['compliance'])
            ? $decoded['compliance']
            : [];

        $mode = isset($compliance['mode']) ? (int) $compliance['mode'] : null;
        $profile = isset($compliance['profile']) ? strtolower((string) $compliance['profile']) : '';

        $label = '—';
        $icon_key = '';

        if ($mode === 0) {
            $label = __('Off', 'griffinforms-form-builder');
        } elseif ($mode === 1) {
            if ($profile === 'gdpr') {
                $label = __('GDPR', 'griffinforms-form-builder');
                $icon_key = 'gdpr';
            } elseif ($profile === 'hipaa') {
                $label = __('HIPAA‑ready', 'griffinforms-form-builder');
                $icon_key = 'hipaa-ready';
            } else {
                $label = __('Standard', 'griffinforms-form-builder');
            }
        }

        $icon_url = '';
        if ($icon_key !== '') {
            $base_path = $this->config->getRootPath() . 'admin/images/compliance-icons/';
            $base_url = $this->config->getRootUrl() . 'admin/images/compliance-icons/';
            $svg_path = $base_path . $icon_key . '.svg';
            $png_path = $base_path . $icon_key . '.png';
            if (file_exists($svg_path)) {
                $icon_url = $base_url . $icon_key . '.svg';
            } elseif (file_exists($png_path)) {
                $icon_url = $base_url . $icon_key . '.png';
            }
        }

        echo '<div class="gf-compliance-list-cell d-flex align-items-center gap-2">';
        if ($icon_url !== '') {
            echo '<span class="gf-compliance-list-icon"><img src="' . esc_url($icon_url) . '" alt="" aria-hidden="true"></span>';
        }
        echo '<span>' . esc_html($label) . '</span>';
        echo '</div>';
    }

    protected function revisionsHeadingText($list_column)
    {
        echo '<span>' . esc_html__('Revisions', 'griffinforms-form-builder') . '</span>';
    }

    protected function revisionsCellText($list_column, $item)
    {
        $count = isset($item->submission_edit_count) ? absint($item->submission_edit_count) : 0;
        if ($count === 0) {
            echo '<span class="text-muted">—</span>';
        } else {
            echo '<span class="badge text-bg-secondary">' . esc_html((string) $count) . '</span>';
        }
    }

    protected function lasteditedHeadingText($list_column)
    {
        echo '<span>' . esc_html__('Last Edited', 'griffinforms-form-builder') . '</span>';
    }

    protected function idCellText($list_column, $item)
    {
        echo '<span class="badge text-bg-secondary">' . absint($item->id) . '</span>';
    }

    protected function submissionipCellText($list_column, $item)
    {
        $ip = trim((string) ($item->submission_ip ?? ''));
        echo $ip !== '' ? esc_html($ip) : '<span class="text-muted">—</span>';
    }

    protected function sourceurlCellText($list_column, $item)
    {
        $url = trim((string) ($item->source_url ?? ''));
        if ($url === '') {
            echo '<span class="text-muted">—</span>';
            return;
        }
        $label = parse_url($url, PHP_URL_PATH) ?: $url;
        echo '<a href="' . esc_url($url) . '" target="_blank" class="text-truncate d-inline-block" style="max-width:180px">' . esc_html($label) . '</a>';
    }

    protected function paymentstatusCellText($list_column, $item)
    {
        if (!$item->is_payment_form) {
            echo '<span class="text-muted">—</span>';
            return;
        }
        $status = sanitize_key($item->payment_status ?? 'pending');
        $badge  = $status === 'paid' ? 'text-bg-success' : ($status === 'failed' ? 'text-bg-danger' : 'text-bg-secondary');
        echo '<span class="badge ' . esc_attr($badge) . '">' . esc_html(ucfirst($status)) . '</span>';
    }

    protected function authorCellTextNicename($list_column, $item)
    {
        $user = get_user_by('id', $item->author ?? 0);
        echo $user ? esc_html($user->user_nicename) : '<span class="text-muted">—</span>';
    }

    protected function authorCellTextFullname($list_column, $item)
    {
        $user = get_user_by('id', $item->author ?? 0);
        if (!$user) {
            echo '<span class="text-muted">—</span>';
            return;
        }
        $full = trim($user->user_firstname . ' ' . $user->user_lastname);
        echo esc_html($full ?: $user->user_nicename);
    }

    protected function pageAlerts()
    {
        $this->keepSubmissionsAlert();
    }

    protected function submissionHasAccountsActivity($item): bool
    {
        $raw_meta = isset($item->submission_meta) ? $item->submission_meta : '';
        $decoded = $this->maybeDecode($raw_meta);

        if (!is_array($decoded)) {
            return false;
        }

        $accounts = isset($decoded['accounts']) && is_array($decoded['accounts'])
            ? $decoded['accounts']
            : [];

        $setups = isset($accounts['setups']) && is_array($accounts['setups'])
            ? $accounts['setups']
            : [];

        return !empty($setups);
    }

    protected function getSubmissionMailchimpSignal($item): string
    {
        $raw_meta = isset($item->submission_meta) ? $item->submission_meta : '';
        $decoded = $this->maybeDecode($raw_meta);
        if (!is_array($decoded)) {
            return '';
        }

        $mailchimp = isset($decoded['mailchimp']) && is_array($decoded['mailchimp'])
            ? $decoded['mailchimp']
            : [];
        if (empty($mailchimp)) {
            return '';
        }

        $status = sanitize_key((string) ($mailchimp['status'] ?? ''));
        if ($status === '') {
            return '';
        }

        $title = __('Mailchimp sync activity recorded', 'griffinforms-form-builder');
        if ($status === 'queued') {
            $title = __('Mailchimp sync queued', 'griffinforms-form-builder');
        } elseif ($status === 'synced') {
            $title = __('Mailchimp subscriber synced', 'griffinforms-form-builder');
        } elseif ($status === 'skipped') {
            $title = __('Mailchimp sync skipped', 'griffinforms-form-builder');
        } elseif ($status === 'failed') {
            $title = __('Mailchimp sync failed', 'griffinforms-form-builder');
        }

        return sprintf(
            '<span class="gf-submissions-signal gf-submissions-signal-mailchimp is-%s" title="%s" aria-label="%s"><img src="%s" alt="" width="16" height="16" loading="lazy" decoding="async" /></span>',
            esc_attr($status),
            esc_attr($title),
            esc_attr($title),
            esc_url($this->config->getRootUrl() . 'admin/images/integrations/mailchimp.svg')
        );
    }

    protected function getSubmissionKlaviyoSignal($item): string
    {
        $raw_meta = isset($item->submission_meta) ? $item->submission_meta : '';
        $decoded  = $this->maybeDecode($raw_meta);
        if (!is_array($decoded)) {
            return '';
        }

        $klaviyo = isset($decoded['klaviyo']) && is_array($decoded['klaviyo'])
            ? $decoded['klaviyo']
            : [];
        if (empty($klaviyo)) {
            return '';
        }

        $status = sanitize_key((string) ($klaviyo['status'] ?? ''));
        if ($status === '') {
            return '';
        }

        $title = __('Klaviyo sync activity recorded', 'griffinforms-form-builder');
        if ($status === 'queued') {
            $title = __('Klaviyo sync queued', 'griffinforms-form-builder');
        } elseif ($status === 'synced') {
            $title = __('Klaviyo contact synced', 'griffinforms-form-builder');
        } elseif ($status === 'skipped') {
            $title = __('Klaviyo sync skipped', 'griffinforms-form-builder');
        } elseif ($status === 'failed') {
            $title = __('Klaviyo sync failed', 'griffinforms-form-builder');
        }

        return sprintf(
            '<span class="gf-submissions-signal gf-submissions-signal-klaviyo is-%s" title="%s" aria-label="%s"><img src="%s" alt="" width="16" height="16" loading="lazy" decoding="async" /></span>',
            esc_attr($status),
            esc_attr($title),
            esc_attr($title),
            esc_url($this->config->getRootUrl() . 'admin/images/integrations/klaviyo.svg')
        );
    }

    protected function getSubmissionGoogleSheetsSignal($item): string
    {
        $raw_meta = isset($item->submission_meta) ? $item->submission_meta : '';
        $decoded  = $this->maybeDecode($raw_meta);
        if (!is_array($decoded)) {
            return '';
        }

        $state = isset($decoded['google_sheets']) && is_array($decoded['google_sheets'])
            ? $decoded['google_sheets']
            : [];
        if (empty($state)) {
            return '';
        }

        $status = sanitize_key((string) ($state['status'] ?? ''));
        if ($status === '') {
            return '';
        }

        $title = __('Google Sheets sync activity recorded', 'griffinforms-form-builder');
        if ($status === 'synced') {
            $title = __('Synced to Google Sheets', 'griffinforms-form-builder');
        } elseif ($status === 'failed') {
            $title = __('Google Sheets sync failed', 'griffinforms-form-builder');
        }

        return sprintf(
            '<span class="gf-submissions-signal gf-submissions-signal-google-sheets is-%s" title="%s" aria-label="%s"><img src="%s" alt="" width="16" height="16" loading="lazy" decoding="async" /></span>',
            esc_attr($status),
            esc_attr($title),
            esc_attr($title),
            esc_url($this->config->getRootUrl() . 'admin/images/integrations/sheets.svg')
        );
    }

    /**
     * Displays an alert on the submissions page if the selected form
     * is configured to not save all submissions (e.g., none or recent X).
     * Skips the alert if no form is selected or if all entries are saved.
     */
    protected function keepSubmissionsAlert()
    {
        if ($this->isFiltered() and !empty($this->form_id)) {
            $form = new \GriffinForms\Items\Form();
            $form->loadItem($this->form_id);
            $save_entries = $form->getProp('save_entries');

            if (empty($save_entries) || $save_entries === 'all_entries') {
                return;
            }

            $form_url = get_admin_url() . 'admin.php?page=griffinforms-form&id=' . $this->form_id;
            echo '<div class="notice notice-warning py-2">';
            echo wp_kses_post($this->lang->getText('save_entries', $save_entries));
            $lifetime_count = $form->getProp('lifetime_submission_count');
            if (is_numeric($lifetime_count)) {
                $formatted_count = number_format_i18n((int) $lifetime_count);
                echo ' ' . esc_html($this->lang->lifetimeSubmissionCountNotice($formatted_count));
            }
            echo ' ';
            echo wp_kses_post($this->lang->formSettingsNotice($form_url));
            $nonce = wp_create_nonce('run_retention_cleanup');
            echo ' <a href="#" class="gf-run-retention-cleanup" data-gf-form-id="' . absint($this->form_id) . '" data-gf-nonce="' . esc_attr($nonce) . '">';
            echo esc_html__('Clean Up Now', 'griffinforms-form-builder');
            echo '</a>';
            echo '</div>';
        }
    }
}
