<?php
/**
 * Calls list table.
 *
 * @link       https://github.com/sitestaffr/sitestaffr-plugin
 * @since      1.0.0
 *
 * @package    SiteStaffr
 * @subpackage SiteStaffr/admin
 */

// Load WP_List_Table if not loaded
if ( ! class_exists( 'WP_List_Table' ) ) {
    require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}

/**
 * Calls list table class.
 *
 * Extends WP_List_Table to display call records with filtering,
 * sorting, and bulk actions.
 *
 * @since      1.0.0
 * @package    SiteStaffr
 * @subpackage SiteStaffr/admin
 * @author     SiteStaffr
 */
// phpcs:disable WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended -- Reads query-string state only; mutating actions are nonce-protected by WP list-table forms/actions.
class SiteStaffr_Calls_List_Table extends WP_List_Table {

    /**
     * Whether this table is displaying trashed items.
     *
     * @var bool
     */
    private $is_trash = false;

    /**
     * Constructor.
     *
     * @since    1.0.0
     * @param    array    $args    Optional. Accepts 'trash' => true to show trashed items.
     */
    public function __construct( $args = array() ) {
        $this->is_trash = ! empty( $args['trash'] );

        parent::__construct( array(
            'singular' => 'call',
            'plural'   => 'calls',
            'ajax'     => false,
        ) );
    }

    /**
     * Get table columns.
     *
     * @since    1.0.0
     * @return   array    Columns array.
     */
    public function get_columns() {
        return array(
            'cb'          => '<input type="checkbox" />',
            'status'      => __( 'Status', 'sitestaffr' ),
            'created_at'  => __( 'Date/Time', 'sitestaffr' ),
            'from_number' => __( 'Summary', 'sitestaffr' ),
            'call_duration' => __( 'Duration', 'sitestaffr' ),
        );
    }

    /**
     * Get sortable columns.
     *
     * @since    1.0.0
     * @return   array    Sortable columns array.
     */
    protected function get_sortable_columns() {
        return array(
            'created_at'    => array( 'created_at', true ),
            'call_duration' => array( 'call_duration', false ),
        );
    }

    /**
     * Set the primary column for responsive table rows.
     *
     * WordPress mobile table mode only shows the primary column inline.
     * Use the summary column so conversation content stays visible.
     *
     * @since    1.0.0
     * @return   string
     */
    protected function get_default_primary_column_name() {
        return 'from_number';
    }

    /**
     * Get bulk actions.
     *
     * @since    1.0.0
     * @return   array    Bulk actions array.
     */
    protected function get_bulk_actions() {
        if ( $this->is_trash ) {
            return array(
                'restore'          => __( 'Restore', 'sitestaffr' ),
                'permanent_delete' => __( 'Delete Permanently', 'sitestaffr' ),
            );
        }

        return array(
            'mark_read'   => __( 'Mark as Read', 'sitestaffr' ),
            'mark_unread' => __( 'Mark as Unread', 'sitestaffr' ),
            'delete'      => __( 'Move to Trash', 'sitestaffr' ),
        );
    }

    /**
     * Prepare items for display.
     *
     * @since    1.0.0
     */
    public function prepare_items() {
        $columns = $this->get_columns();
        $hidden = array();
        $sortable = $this->get_sortable_columns();

        $this->_column_headers = array( $columns, $hidden, $sortable );

        // Handle bulk actions
        $this->process_bulk_action();

        // Get current page
        $current_page = $this->get_pagenum();
        $per_page = 20;

        // phpcs:disable WordPress.Security.NonceVerification.Recommended,WordPress.Security.NonceVerification.Missing -- read-only filter/sort/search params for WP_List_Table display on capability-gated admin page.
        $filter_status = isset( $_POST['filter_status'] ) ? sanitize_text_field( wp_unslash( $_POST['filter_status'] ) ) :
                        ( isset( $_GET['filter_status'] ) ? sanitize_text_field( wp_unslash( $_GET['filter_status'] ) ) : '' );
        $filter_read = isset( $_POST['filter_read'] ) ? sanitize_text_field( wp_unslash( $_POST['filter_read'] ) ) :
                      ( isset( $_GET['filter_read'] ) ? sanitize_text_field( wp_unslash( $_GET['filter_read'] ) ) : '' );
        $filter_date = isset( $_POST['filter_date'] ) ? sanitize_text_field( wp_unslash( $_POST['filter_date'] ) ) :
                      ( isset( $_GET['filter_date'] ) ? sanitize_text_field( wp_unslash( $_GET['filter_date'] ) ) : '' );
        $filter_date_from = isset( $_POST['filter_date_from'] ) ? sanitize_text_field( wp_unslash( $_POST['filter_date_from'] ) ) :
                           ( isset( $_GET['filter_date_from'] ) ? sanitize_text_field( wp_unslash( $_GET['filter_date_from'] ) ) : '' );
        $filter_date_to = isset( $_POST['filter_date_to'] ) ? sanitize_text_field( wp_unslash( $_POST['filter_date_to'] ) ) :
                         ( isset( $_GET['filter_date_to'] ) ? sanitize_text_field( wp_unslash( $_GET['filter_date_to'] ) ) : '' );
        $search = isset( $_POST['s'] ) ? sanitize_text_field( wp_unslash( $_POST['s'] ) ) :
                 ( isset( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : '' );

        $args = array(
            'per_page' => $per_page,
            'page'     => $current_page,
            'orderby'  => isset( $_POST['orderby'] ) ? sanitize_text_field( wp_unslash( $_POST['orderby'] ) ) :
                         ( isset( $_GET['orderby'] ) ? sanitize_text_field( wp_unslash( $_GET['orderby'] ) ) : 'created_at' ),
            'order'    => isset( $_POST['order'] ) ? sanitize_text_field( wp_unslash( $_POST['order'] ) ) :
                         ( isset( $_GET['order'] ) ? sanitize_text_field( wp_unslash( $_GET['order'] ) ) : 'DESC' ),
            'search'   => $search,
            'trash'    => $this->is_trash,
        );
        // phpcs:enable WordPress.Security.NonceVerification.Recommended,WordPress.Security.NonceVerification.Missing

        // Apply filters (only for non-trash view)
        if ( ! $this->is_trash ) {
            if ( $filter_status ) {
                $args['status'] = $filter_status;
            }

            if ( $filter_read === 'new' ) {
                $args['is_read'] = 0;
            } elseif ( $filter_read === 'read' ) {
                $args['is_read'] = 1;
            }

            // Date range filter
            $current_dt = current_datetime();
            if ( $filter_date === '7days' ) {
                $args['date_from'] = $current_dt->modify( '-7 days' )->format( 'Y-m-d H:i:s' );
            } elseif ( $filter_date === '30days' ) {
                $args['date_from'] = $current_dt->modify( '-30 days' )->format( 'Y-m-d H:i:s' );
            } elseif ( $filter_date === 'custom' ) {
                // HTML5 date inputs produce YYYY-MM-DD; append time boundaries for inclusive range
                if ( ! empty( $filter_date_from ) ) {
                    $args['date_from'] = $filter_date_from . ' 00:00:00';
                }
                if ( ! empty( $filter_date_to ) ) {
                    $args['date_to'] = $filter_date_to . ' 23:59:59';
                }
            }
        }

        // Get items
        $this->items = SiteStaffr_Call_Manager::get_calls( $args );
        $total_items = SiteStaffr_Call_Manager::get_calls_count( $args );

        // Set pagination
        $this->set_pagination_args( array(
            'total_items' => $total_items,
            'per_page'    => $per_page,
            'total_pages' => ceil( $total_items / $per_page ),
        ) );
    }

    /**
     * Render a single table row.
     *
     * Adds a custom class for unread/new calls so they can be subtly highlighted.
     *
     * @since    1.0.0
     * @param    object    $item    Call object.
     */
    public function single_row( $item ) {
        $row_classes = array();

        if ( isset( $item->is_read ) && 0 === (int) $item->is_read ) {
            $row_classes[] = 'sitestaffr-row-new';
        }

        $class_attr = ! empty( $row_classes ) ? ' class="' . esc_attr( implode( ' ', $row_classes ) ) . '"' : '';
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $class_attr is built from esc_attr() above
        echo '<tr' . $class_attr . '>';
        $this->single_row_columns( $item );
        echo '</tr>';
    }

    /**
     * Column checkbox.
     *
     * @since    1.0.0
     * @param    object    $item    Call object.
     * @return   string             Checkbox HTML.
     */
    protected function column_cb( $item ) {
        return sprintf(
            '<input type="checkbox" name="call_ids[]" value="%d" />',
            $item->id
        );
    }

    /**
     * Column status.
     *
     * @since    1.0.0
     * @param    object    $item    Call object.
     * @return   string             Status HTML.
     */
    protected function column_status( $item ) {
        $badges = '';

        // Add filtered badge for non-billable calls (spam/low-quality)
        if ( isset( $item->is_billable ) && $item->is_billable == 0 ) {
            $badges .= '<span class="sitestaffr-status-badge sitestaffr-status-filtered">' . __( 'Filtered', 'sitestaffr' ) . '</span>';
        } else {
            // Only show read/unread badge for billable calls
            // Add read/unread badge
            if ( $item->is_read ) {
                $badges .= '<span class="sitestaffr-status-badge sitestaffr-status-read">' . __( 'Read', 'sitestaffr' ) . '</span>';
            } else {
                $badges .= '<span class="sitestaffr-status-badge sitestaffr-status-new">' . __( 'New', 'sitestaffr' ) . '</span>';
            }
        }

        return $badges;
    }

    /**
     * Column created_at.
     *
     * @since    1.0.0
     * @param    object    $item    Call object.
     * @return   string             Date/time HTML.
     */
    protected function column_created_at( $item ) {
        $dt = new DateTime( $item->created_at, new DateTimeZone( 'UTC' ) );
        $dt->setTimezone( new DateTimeZone( 'America/New_York' ) );

        return sprintf(
            '<span class="sitestaffr-date-value">%s</span><span class="sitestaffr-time-value">%s</span>',
            esc_html( $dt->format( 'M j, Y' ) ),
            esc_html( $dt->format( 'g:i a' ) )
        );
    }

    /**
     * Column from_number (repurposed as Summary column).
     *
     * Displays a short preview of the AI summary for the conversation.
     * Row actions (View, Mark as Read/Unread, Delete) are attached here.
     *
     * @since    1.0.0
     * @param    object    $item    Call object.
     * @return   string             Summary snippet HTML with row actions.
     */
    protected function column_from_number( $item ) {
        // Build summary snippet
        $raw_summary = isset( $item->ai_summary ) ? stripslashes( (string) $item->ai_summary ) : '';
        $raw_summary = trim( $raw_summary );

        if ( ! empty( $raw_summary ) ) {
            // For onboarding table recaps, build a clean "Name · Business" snippet.
            if ( false !== stripos( $raw_summary, '<table' ) ) {
                $snippet_parts = array();
                if ( preg_match_all( '/<td[^>]*style="padding:6px 0;"[^>]*>(.*?)<\/td>/si', $raw_summary, $td_matches ) ) {
                    foreach ( $td_matches[1] as $td_val ) {
                        $clean = trim( wp_strip_all_tags( $td_val ) );
                        if ( '' !== $clean ) {
                            $snippet_parts[] = $clean;
                        }
                    }
                }
                $plain_summary = implode( ' · ', $snippet_parts );
            } else {
                $plain_summary = wp_strip_all_tags( $raw_summary );
            }
            if ( mb_strlen( $plain_summary ) > 80 ) {
                $snippet = esc_html( mb_substr( $plain_summary, 0, 80 ) ) . '&hellip;';
            } else {
                $snippet = esc_html( $plain_summary );
            }
            $summary_html = '<span>' . $snippet . '</span>';
        } else {
            $summary_html = '<em style="color:#999;">' . __( 'No summary', 'sitestaffr' ) . '</em>';
        }

        // Add persona badge for onboarding leads.
        $item_persona = isset( $item->persona ) ? sanitize_key( $item->persona ) : 'default';
        if ( 'onboarding' === $item_persona ) {
            $summary_html = '<span class="sitestaffr-persona-badge sitestaffr-persona-badge--onboarding">' . esc_html__( 'Onboarding Lead', 'sitestaffr' ) . '</span> ' . $summary_html;
        }

        // Add row actions
        $actions = array();

        if ( $this->is_trash ) {
            // Trash view: Restore and Delete Permanently
            $restore_url = wp_nonce_url(
                add_query_arg( array(
                    'action'  => 'restore_single',
                    'call_id' => $item->id,
                    'view'    => 'trash',
                ) ),
                'sitestaffr_restore_' . $item->id
            );
            $actions['restore'] = sprintf(
                '<a href="%s">%s</a>',
                esc_url( $restore_url ),
                __( 'Restore', 'sitestaffr' )
            );

            $permanent_delete_url = wp_nonce_url(
                add_query_arg( array(
                    'action'  => 'permanent_delete_single',
                    'call_id' => $item->id,
                    'view'    => 'trash',
                ) ),
                'sitestaffr_permanent_delete_' . $item->id
            );
            $actions['permanent_delete'] = sprintf(
                '<a href="%s" onclick="return confirm(\'%s\')" class="submitdelete">%s</a>',
                esc_url( $permanent_delete_url ),
                esc_js( __( 'Are you sure you want to permanently delete this conversation? This cannot be undone.', 'sitestaffr' ) ),
                __( 'Delete Permanently', 'sitestaffr' )
            );
        } else {
            // Normal view: View, Mark as Read/Unread, Delete (trash)
            $view_url = wp_nonce_url( add_query_arg( array(
                'page'    => 'sitestaffr',
                'action'  => 'view',
                'call_id' => $item->id,
            ), admin_url( 'admin.php' ) ), 'sitestaffr_view_call' );
            $actions['view'] = sprintf(
                '<a href="%s">%s</a>',
                esc_url( $view_url ),
                __( 'View', 'sitestaffr' )
            );

            if ( ! $item->is_read ) {
                $mark_read_url = wp_nonce_url(
                    add_query_arg( array(
                        'action' => 'mark_read_single',
                        'call_id' => $item->id,
                    ) ),
                    'sitestaffr_mark_read_' . $item->id
                );
                $actions['mark_read'] = sprintf(
                    '<a href="%s">%s</a>',
                    esc_url( $mark_read_url ),
                    __( 'Mark as Read', 'sitestaffr' )
                );
            } else {
                $mark_unread_url = wp_nonce_url(
                    add_query_arg( array(
                        'action' => 'mark_unread_single',
                        'call_id' => $item->id,
                    ) ),
                    'sitestaffr_mark_unread_' . $item->id
                );
                $actions['mark_unread'] = sprintf(
                    '<a href="%s">%s</a>',
                    esc_url( $mark_unread_url ),
                    __( 'Mark as Unread', 'sitestaffr' )
                );
            }

            $delete_url = wp_nonce_url(
                add_query_arg( array(
                    'action' => 'delete_single',
                    'call_id' => $item->id,
                ) ),
                'sitestaffr_delete_' . $item->id
            );
            $actions['delete'] = sprintf(
                '<a href="%s" onclick="return confirm(\'%s\')">%s</a>',
                esc_url( $delete_url ),
                esc_js( __( 'Are you sure you want to move this conversation to trash?', 'sitestaffr' ) ),
                __( 'Trash', 'sitestaffr' )
            );
        }

        return $summary_html . $this->row_actions( $actions );
    }

    /**
     * Column call_duration.
     *
     * @since    1.0.0
     * @param    object    $item    Call object.
     * @return   string             Duration HTML.
     */
    protected function column_call_duration( $item ) {
        if ( $item->call_duration > 0 ) {
            $minutes = floor( $item->call_duration / 60 );
            $seconds = $item->call_duration % 60;
            return sprintf( '%d:%02d', $minutes, $seconds );
        }
        // Show "In Progress" for calls with no duration yet
        return '<span style="color: #999; font-style: italic;">' . __( 'In Progress', 'sitestaffr' ) . '</span>';
    }


    /**
     * Default column output.
     *
     * @since    1.0.0
     * @param    object    $item         Call object.
     * @param    string    $column_name  Column name.
     * @return   string                  Column HTML.
     */
    protected function column_default( $item, $column_name ) {
        return isset( $item->$column_name ) ? esc_html( $item->$column_name ) : '&#8212;';
    }

    /**
     * Process bulk actions.
     *
     * Note: This method is kept for backward compatibility but no longer
     * performs redirects. All action processing is now handled in
     * SiteStaffr_Admin::process_dashboard_actions() before page load.
     *
     * @since    1.0.0
     */
    public function process_bulk_action() {
        // Actions are now processed early in SiteStaffr_Admin::process_dashboard_actions()
        // This method is kept empty to maintain WP_List_Table compatibility
    }

    /**
     * Extra table navigation (filters).
     *
     * @since    1.0.0
     * @param    string    $which    Top or bottom.
     */
    protected function extra_tablenav( $which ) {
        if ( 'top' !== $which ) {
            return;
        }

        if ( ! $this->is_trash ) {
            // phpcs:disable WordPress.Security.NonceVerification.Recommended,WordPress.Security.NonceVerification.Missing -- read-only filter display state for WP_List_Table on capability-gated admin page.
            $filter_status = isset( $_POST['filter_status'] ) ? sanitize_text_field( wp_unslash( $_POST['filter_status'] ) ) :
                            ( isset( $_GET['filter_status'] ) ? sanitize_text_field( wp_unslash( $_GET['filter_status'] ) ) : '' );
            $filter_read = isset( $_POST['filter_read'] ) ? sanitize_text_field( wp_unslash( $_POST['filter_read'] ) ) :
                          ( isset( $_GET['filter_read'] ) ? sanitize_text_field( wp_unslash( $_GET['filter_read'] ) ) : '' );
            $filter_date = isset( $_POST['filter_date'] ) ? sanitize_text_field( wp_unslash( $_POST['filter_date'] ) ) :
                          ( isset( $_GET['filter_date'] ) ? sanitize_text_field( wp_unslash( $_GET['filter_date'] ) ) : '' );
            $filter_date_from = isset( $_POST['filter_date_from'] ) ? sanitize_text_field( wp_unslash( $_POST['filter_date_from'] ) ) :
                               ( isset( $_GET['filter_date_from'] ) ? sanitize_text_field( wp_unslash( $_GET['filter_date_from'] ) ) : '' );
            $filter_date_to = isset( $_POST['filter_date_to'] ) ? sanitize_text_field( wp_unslash( $_POST['filter_date_to'] ) ) :
                             ( isset( $_GET['filter_date_to'] ) ? sanitize_text_field( wp_unslash( $_GET['filter_date_to'] ) ) : '' );
            // phpcs:enable WordPress.Security.NonceVerification.Recommended,WordPress.Security.NonceVerification.Missing
            ?>
            <div class="alignleft actions">
                <select name="filter_read">
                    <option value=""><?php esc_html_e( 'All Status', 'sitestaffr' ); ?></option>
                    <option value="new" <?php selected( $filter_read, 'new' ); ?>><?php esc_html_e( 'New', 'sitestaffr' ); ?></option>
                    <option value="read" <?php selected( $filter_read, 'read' ); ?>><?php esc_html_e( 'Read', 'sitestaffr' ); ?></option>
                </select>

                <select name="filter_date" id="sitestaffr-filter-date">
                    <option value=""><?php esc_html_e( 'All Time', 'sitestaffr' ); ?></option>
                    <option value="7days" <?php selected( $filter_date, '7days' ); ?>><?php esc_html_e( 'Last 7 Days', 'sitestaffr' ); ?></option>
                    <option value="30days" <?php selected( $filter_date, '30days' ); ?>><?php esc_html_e( 'Last 30 Days', 'sitestaffr' ); ?></option>
                    <option value="custom" <?php selected( $filter_date, 'custom' ); ?>><?php esc_html_e( 'Custom Range', 'sitestaffr' ); ?></option>
                </select>

                <span id="sitestaffr-custom-date-range" style="<?php echo $filter_date === 'custom' ? '' : 'display:none;'; ?>">
                    <input type="date" name="filter_date_from" value="<?php echo esc_attr( $filter_date_from ); ?>" style="vertical-align: middle;" />
                    <span style="vertical-align: middle;">&ndash;</span>
                    <input type="date" name="filter_date_to" value="<?php echo esc_attr( $filter_date_to ); ?>" style="vertical-align: middle;" />
                </span>

                <?php submit_button( __( 'Filter', 'sitestaffr' ), '', 'filter_action', false ); ?>
            </div>
            <?php
        }
        ?>
        <!-- Calls list controls JS enqueued via class-sitestaffr-admin.php -->
        <?php
    }

    /**
     * Display no items message.
     *
     * @since    1.0.0
     */
    public function no_items() {
        if ( $this->is_trash ) {
            esc_html_e( 'No conversations in trash.', 'sitestaffr' );
        } else {
            esc_html_e( 'No conversations found.', 'sitestaffr' );
        }
    }
}
// phpcs:enable WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
