<?php

namespace WPSN\Modules\BulkTable\Admin;

use WPSN\Core\Container;
use WPSN\Domain\SeoDocumentContext;
use WPSN\SEO\SeoMetaRepository;

defined('ABSPATH') || exit;

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

/**
 * WP_List_Table for the Bulk Edit screen.
 */
final class BulkTableListTable extends \WP_List_Table
{
    private Container $container;

    /** @var array{pt:string,status:string,filter:string,s:string} */
    private array $filters;

    private SeoMetaRepository $metaRepo;

    /**
     * We render the table inside a GET form (filters/search/pagination),
     * but we want editable inputs to submit through a separate POST form.
     *
     * @var string
     */
    private string $saveFormId;

    public function __construct(Container $container, array $filters, string $saveFormId = 'wpsn-bulk-table-save-form')
    {
        $this->container = $container;
        $this->filters = $filters;
        $this->metaRepo = $container->get('meta_repo');
        $this->saveFormId = $saveFormId;

        parent::__construct([
            'singular' => 'wpsn_bulk_row',
            'plural'   => 'wpsn_bulk_rows',
            'ajax'     => false,
        ]);
    }

    public function get_columns(): array
    {
        return [
            'cb' => '<input type="checkbox" />',
            'post' => __('Post', 'wp-seo-next'),
            'seo_title' => __('SEO Title', 'wp-seo-next'),
            'meta_description' => __('Meta Description', 'wp-seo-next'),
            'canonical' => __('Canonical', 'wp-seo-next'),
            'robots' => __('Robots', 'wp-seo-next'),
            'og_title' => __('OG Title', 'wp-seo-next'),
            'og_description' => __('OG Description', 'wp-seo-next'),
            'og_image' => __('OG Image', 'wp-seo-next'),
            'twitter_title' => __('Twitter Title', 'wp-seo-next'),
            'twitter_description' => __('Twitter Description', 'wp-seo-next'),
            'twitter_image' => __('Twitter Image', 'wp-seo-next'),
        ];
    }

    protected function get_default_primary_column_name(): string
    {
        return 'post';
    }

    protected function get_hidden_columns(): array
    {
        // Hide Twitter columns by default to keep the UI compact.
        return ['twitter_title', 'twitter_description', 'twitter_image'];
    }

    public function prepare_items(): void
    {
        $perPage = $this->get_items_per_page('wpsn_bulk_table_per_page', 20);
        $paged = $this->get_pagenum();
        $offset = ($paged - 1) * $perPage;

        $query = new BulkTableQuery($this->container);
        [$items, $total] = $query->fetch($this->filters, $perPage, $offset);

        // Enrich rows with resolved values for placeholders.
        foreach ($items as &$row) {
            $id = (int) ($row['ID'] ?? 0);
            if ($id <= 0) {
                continue;
            }

            $url = get_permalink($id);
            $url = is_string($url) ? $url : '';

            $ctx = new SeoDocumentContext(SeoDocumentContext::TYPE_SINGULAR, $id, (string) ($row['post_type'] ?? ''), $url, 1);
            $meta = $this->metaRepo->forContext($ctx);

            $row['resolved_seo_title'] = $meta->title;
            $row['resolved_meta_description'] = $meta->description;
            $row['resolved_canonical'] = $meta->canonical;
            $row['resolved_robots_noindex'] = (bool) ($meta->robots['noindex'] ?? false);
            $row['resolved_robots_nofollow'] = (bool) ($meta->robots['nofollow'] ?? false);
            $row['resolved_og_title'] = $meta->ogTitle;
            $row['resolved_og_description'] = $meta->ogDescription;
            $row['resolved_og_image'] = $meta->ogImage;
            $row['resolved_twitter_title'] = $meta->twitterTitle;
            $row['resolved_twitter_description'] = $meta->twitterDescription;
            $row['resolved_twitter_image'] = $meta->twitterImage;
        }
        unset($row);

        $this->items = $items;

        $this->set_pagination_args([
            'total_items' => $total,
            'per_page'    => $perPage,
            'total_pages' => (int) ceil($total / $perPage),
        ]);
    }

    public function column_cb($item): string
    {
        $id = (int) ($item['ID'] ?? 0);
        return '<input type="checkbox" form="' . esc_attr($this->saveFormId) . '" name="post_ids[]" value="' . esc_attr((string) $id) . '" />';
    }

    public function column_post($item): string
    {
        $id = (int) ($item['ID'] ?? 0);
        $title = (string) ($item['post_title'] ?? '');
        $title = $title !== '' ? $title : __('(no title)', 'wp-seo-next');

        $edit = $id > 0 ? get_edit_post_link($id) : '';
        $view = $id > 0 ? get_permalink($id) : '';

        $out = '';
        if ($edit) {
            $out .= '<strong><a href="' . esc_url($edit) . '">#' . esc_html((string) $id) . ' ' . esc_html($title) . '</a></strong>';
        } else {
            $out .= '<strong>#' . esc_html((string) $id) . ' ' . esc_html($title) . '</strong>';
        }

        $out .= '<div class="row-actions">';
        $actions = [];
        if ($edit) {
            $actions['edit'] = '<a href="' . esc_url($edit) . '">' . esc_html__('Edit', 'wp-seo-next') . '</a>';
        }
        if (is_string($view) && $view !== '') {
            $actions['view'] = '<a href="' . esc_url($view) . '" target="_blank" rel="noopener noreferrer">' . esc_html__('View', 'wp-seo-next') . '</a>';
        }

        $out .= $this->row_actions($actions);
        $out .= '</div>';

        $meta = [];
        $meta[] = '<span class="wpsn-muted">' . esc_html((string) ($item['post_type'] ?? '')) . '</span>';
        $meta[] = '<span class="wpsn-muted">' . esc_html((string) ($item['post_status'] ?? '')) . '</span>';
        $out .= '<div class="wpsn-meta">' . implode(' · ', $meta) . '</div>';

        return $out;
    }

    public function column_seo_title($item): string
    {
        return $this->textInput($item, 'seo_title', (string) ($item['seo_title'] ?? ''), (string) ($item['resolved_seo_title'] ?? ''));
    }

    public function column_meta_description($item): string
    {
        return $this->textareaInput($item, 'meta_description', (string) ($item['meta_description'] ?? ''), (string) ($item['resolved_meta_description'] ?? ''));
    }

    public function column_canonical($item): string
    {
        return $this->urlInput($item, 'canonical', (string) ($item['canonical'] ?? ''), (string) ($item['resolved_canonical'] ?? ''));
    }

    public function column_robots($item): string
    {
        $id = (int) ($item['ID'] ?? 0);
        $rIndex = (string) ($item['robots_index'] ?? '');
        $rFollow = (string) ($item['robots_follow'] ?? '');
        $rIndex = $rIndex !== '' ? $rIndex : 'default';
        $rFollow = $rFollow !== '' ? $rFollow : 'default';

        $resolvedIndex = !empty($item['resolved_robots_noindex']) ? 'noindex' : 'index';
        $resolvedFollow = !empty($item['resolved_robots_nofollow']) ? 'nofollow' : 'follow';

        $nameBase = 'wpsn_bulk_table[' . $id . ']';

        ob_start();
        ?>
        <div class="wpsn-robots">
            <label class="wpsn-robots__label">
                <?php echo esc_html__('Index', 'wp-seo-next'); ?>
                <select form="<?php echo esc_attr($this->saveFormId); ?>" name="<?php echo esc_attr($nameBase . '[robots_index]'); ?>">
                    <option value="default" <?php selected($rIndex, 'default'); ?>><?php echo esc_html__('Default', 'wp-seo-next'); ?></option>
                    <option value="index" <?php selected($rIndex, 'index'); ?>><?php echo esc_html__('Index', 'wp-seo-next'); ?></option>
                    <option value="noindex" <?php selected($rIndex, 'noindex'); ?>><?php echo esc_html__('Noindex', 'wp-seo-next'); ?></option>
                </select>
            </label>

            <label class="wpsn-robots__label">
                <?php echo esc_html__('Follow', 'wp-seo-next'); ?>
                <select form="<?php echo esc_attr($this->saveFormId); ?>" name="<?php echo esc_attr($nameBase . '[robots_follow]'); ?>">
                    <option value="default" <?php selected($rFollow, 'default'); ?>><?php echo esc_html__('Default', 'wp-seo-next'); ?></option>
                    <option value="follow" <?php selected($rFollow, 'follow'); ?>><?php echo esc_html__('Follow', 'wp-seo-next'); ?></option>
                    <option value="nofollow" <?php selected($rFollow, 'nofollow'); ?>><?php echo esc_html__('Nofollow', 'wp-seo-next'); ?></option>
                </select>
            </label>

            <div class="wpsn-muted wpsn-resolved">
                <?php
                /* translators: 1: index/noindex, 2: follow/nofollow */
                echo esc_html(sprintf(__('Resolved: %1$s, %2$s', 'wp-seo-next'), $resolvedIndex, $resolvedFollow));
                ?>
            </div>
        </div>
        <?php
        return (string) ob_get_clean();
    }

    public function column_og_title($item): string
    {
        return $this->textInput($item, 'og_title', (string) ($item['og_title'] ?? ''), (string) ($item['resolved_og_title'] ?? ''));
    }

    public function column_og_description($item): string
    {
        return $this->textareaInput($item, 'og_description', (string) ($item['og_description'] ?? ''), (string) ($item['resolved_og_description'] ?? ''));
    }

    public function column_og_image($item): string
    {
        return $this->urlInput($item, 'og_image', (string) ($item['og_image'] ?? ''), (string) ($item['resolved_og_image'] ?? ''));
    }

    public function column_twitter_title($item): string
    {
        return $this->textInput($item, 'twitter_title', (string) ($item['twitter_title'] ?? ''), (string) ($item['resolved_twitter_title'] ?? ''));
    }

    public function column_twitter_description($item): string
    {
        return $this->textareaInput($item, 'twitter_description', (string) ($item['twitter_description'] ?? ''), (string) ($item['resolved_twitter_description'] ?? ''));
    }

    public function column_twitter_image($item): string
    {
        return $this->urlInput($item, 'twitter_image', (string) ($item['twitter_image'] ?? ''), (string) ($item['resolved_twitter_image'] ?? ''));
    }

    protected function extra_tablenav($which): void
    {
        if ($which !== 'top') {
            return;
        }

        $pt = $this->filters['pt'] ?? 'any';
        $status = $this->filters['status'] ?? 'publish';
        $filter = $this->filters['filter'] ?? '';

        $postTypes = get_post_types(['public' => true], 'objects');
        unset($postTypes['attachment']);

        ?>
        <div class="alignleft actions">
            <label class="screen-reader-text" for="wpsn-pt-filter"><?php echo esc_html__('Filter by post type', 'wp-seo-next'); ?></label>
            <select name="pt" id="wpsn-pt-filter">
                <option value="any" <?php selected($pt, 'any'); ?>><?php echo esc_html__('All post types', 'wp-seo-next'); ?></option>
                <?php foreach ($postTypes as $obj) : ?>
                    <option value="<?php echo esc_attr($obj->name); ?>" <?php selected($pt, $obj->name); ?>><?php echo esc_html($obj->labels->singular_name); ?></option>
                <?php endforeach; ?>
            </select>

            <label class="screen-reader-text" for="wpsn-status-filter"><?php echo esc_html__('Filter by status', 'wp-seo-next'); ?></label>
            <select name="status" id="wpsn-status-filter">
                <?php
                $statuses = [
                    'publish' => __('Published', 'wp-seo-next'),
                    'draft' => __('Drafts', 'wp-seo-next'),
                    'pending' => __('Pending', 'wp-seo-next'),
                    'private' => __('Private', 'wp-seo-next'),
                    'future' => __('Scheduled', 'wp-seo-next'),
                    'any' => __('Any', 'wp-seo-next'),
                ];
                foreach ($statuses as $k => $label) {
                    echo '<option value="' . esc_attr($k) . '" ' . selected($status, $k, false) . '>' . esc_html($label) . '</option>';
                }
                ?>
            </select>

            <label class="screen-reader-text" for="wpsn-issue-filter"><?php echo esc_html__('Filter by condition', 'wp-seo-next'); ?></label>
            <select name="filter" id="wpsn-issue-filter">
                <?php
                $filters = [
                    '' => __('All', 'wp-seo-next'),
                    'empty_title' => __('Empty SEO Title override', 'wp-seo-next'),
                    'empty_desc' => __('Empty Meta Description override', 'wp-seo-next'),
                    'long_title' => __('Long SEO Title override', 'wp-seo-next'),
                    'long_desc' => __('Long Meta Description override', 'wp-seo-next'),
                    'duplicates_title' => __('Duplicate SEO Title overrides', 'wp-seo-next'),
                    'template_mismatch' => __('Template mismatch (override ≠ template)', 'wp-seo-next'),
                    'template_mismatch_og' => __('OG mismatch (override ≠ fallback)', 'wp-seo-next'),
                    'has_overrides' => __('Has any overrides', 'wp-seo-next'),
                    'no_overrides' => __('No overrides (templates only)', 'wp-seo-next'),
                ];
                foreach ($filters as $k => $label) {
                    echo '<option value="' . esc_attr($k) . '" ' . selected($filter, $k, false) . '>' . esc_html($label) . '</option>';
                }
                ?>
            </select>

            <?php submit_button(__('Filter', 'wp-seo-next'), 'secondary', 'filter_action', false); ?>
        </div>
        <?php
    }

    private function inputName(array $item, string $field): string
    {
        $id = (int) ($item['ID'] ?? 0);
        return 'wpsn_bulk_table[' . $id . '][' . $field . ']';
    }

    private function textInput(array $item, string $field, string $value, string $resolved): string
    {
        $name = $this->inputName($item, $field);

        $out = '<input type="text" form="' . esc_attr($this->saveFormId) . '" class="wpsn-input" name="' . esc_attr($name) . '" value="' . esc_attr($value) . '" placeholder="' . esc_attr($resolved) . '" />';
        if (trim($resolved) !== '') {
            $out .= '<div class="wpsn-muted wpsn-resolved">' . esc_html__('Resolved:', 'wp-seo-next') . ' <span class="wpsn-mono">' . esc_html($resolved) . '</span></div>';
        }
        return $out;
    }

    private function textareaInput(array $item, string $field, string $value, string $resolved): string
    {
        $name = $this->inputName($item, $field);
        $out = '<textarea form="' . esc_attr($this->saveFormId) . '" class="wpsn-textarea" name="' . esc_attr($name) . '" rows="3" placeholder="' . esc_attr($resolved) . '">' . esc_textarea($value) . '</textarea>';
        if (trim($resolved) !== '') {
            $out .= '<div class="wpsn-muted wpsn-resolved">' . esc_html__('Resolved:', 'wp-seo-next') . ' <span class="wpsn-mono">' . esc_html($resolved) . '</span></div>';
        }
        return $out;
    }

    private function urlInput(array $item, string $field, string $value, string $resolved): string
    {
        $name = $this->inputName($item, $field);
        $out = '<input type="url" form="' . esc_attr($this->saveFormId) . '" class="wpsn-input" name="' . esc_attr($name) . '" value="' . esc_attr($value) . '" placeholder="' . esc_attr($resolved) . '" />';
        if (trim($resolved) !== '') {
            $out .= '<div class="wpsn-muted wpsn-resolved">' . esc_html__('Resolved:', 'wp-seo-next') . ' <span class="wpsn-mono">' . esc_html($resolved) . '</span></div>';
        }
        return $out;
    }
}
