<?php

namespace WPSN\Modules\BulkTable\Admin;

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

defined('ABSPATH') || exit;

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

final class TermBulkTableListTable extends \WP_List_Table
{
    private Container $container;
    private SeoMetaRepository $metaRepo;
    /** @var array{tax:string,filter:string,s:string} */
    private array $filters;
    private string $saveFormId;

    /**
     * @param array{tax:string,filter:string,s:string} $filters
     */
    public function __construct(Container $container, array $filters, string $saveFormId)
    {
        $this->container = $container;
        $this->metaRepo = $container->get('meta_repo');
        $this->filters = $filters;
        $this->saveFormId = $saveFormId;

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

    public function get_columns(): array
    {
        return [
            'cb' => '<input type="checkbox" />',
            'term' => __('Term', 'wp-seo-next'),
            'seo_title' => __('SEO Title (override)', 'wp-seo-next'),
            'meta_description' => __('Meta Description (override)', 'wp-seo-next'),
            'canonical' => __('Canonical (override)', 'wp-seo-next'),
            'robots' => __('Robots (override)', 'wp-seo-next'),
            'og_title' => __('OG Title (override)', 'wp-seo-next'),
            'og_description' => __('OG Description (override)', 'wp-seo-next'),
            'og_image' => __('OG Image (override)', 'wp-seo-next'),

            'twitter_title' => __('Twitter Title (override)', 'wp-seo-next'),
            'twitter_description' => __('Twitter Description (override)', 'wp-seo-next'),
            'twitter_image' => __('Twitter Image (override)', 'wp-seo-next'),
        ];
    }

    protected function get_sortable_columns(): array
    {
        return [];
    }

    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);
        $currentPage = max(1, (int) ($this->get_pagenum()));
        $offset = ($currentPage - 1) * $perPage;

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

        // Enrich with resolved meta for placeholders.
        foreach ($items as &$row) {
            $termId = (int) ($row['term_id'] ?? 0);
            $taxonomy = (string) ($row['taxonomy'] ?? '');
            $url = '';

            if ($termId > 0 && $taxonomy !== '') {
                $link = get_term_link($termId, $taxonomy);
                if (!is_wp_error($link)) {
                    $url = is_string($link) ? $link : '';
                }
            }

            $ctx = new SeoDocumentContext(SeoDocumentContext::TYPE_TERM, $termId, $taxonomy, $url, 1);
            $meta = $this->metaRepo->forContext($ctx);

            $row['resolved_title'] = $meta->title;
            $row['resolved_description'] = $meta->description;
            $row['resolved_canonical'] = $meta->canonical;

            $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' => $perPage > 0 ? (int) ceil($total / $perPage) : 1,
        ]);

        $this->_column_headers = [$this->get_columns(), [], $this->get_sortable_columns(), 'term'];
    }

    public function column_cb($item): string
    {
        $id = (int) ($item['term_id'] ?? 0);
        return sprintf(
            '<input type="checkbox" form="%s" name="term_ids[]" value="%d" />',
            esc_attr($this->saveFormId),
            $id
        );
    }

    public function column_term($item): string
    {
        $id = (int) ($item['term_id'] ?? 0);
        $taxonomy = (string) ($item['taxonomy'] ?? '');
        $name = (string) ($item['term_name'] ?? '');
        $slug = (string) ($item['term_slug'] ?? '');

        $edit = ($id > 0 && $taxonomy !== '') ? get_edit_term_link($id, $taxonomy) : '';
        $view = ($id > 0 && $taxonomy !== '') ? get_term_link($id, $taxonomy) : '';

        if (is_wp_error($view)) {
            $view = '';
        }

        $titleHtml = $edit ? '<a href="' . esc_url($edit) . '"><strong>#' . esc_html((string) $id) . '</strong> ' . esc_html($name) . '</a>' : '<strong>#' . esc_html((string) $id) . '</strong> ' . esc_html($name);

        $metaLine = '<div class="wpsn-muted" style="margin-top:4px;">' . esc_html($taxonomy) . ' · ' . esc_html($slug);
        if (is_string($view) && $view !== '') {
            $metaLine .= ' · <a href="' . esc_url($view) . '" target="_blank" rel="noopener noreferrer">' . esc_html__('View', 'wp-seo-next') . '</a>';
        }
        $metaLine .= '</div>';

        // Hidden taxonomy for save handler.
        $hidden = sprintf(
            '<input type="hidden" form="%s" name="wpsn_bulk_table_terms[%d][taxonomy]" value="%s" />',
            esc_attr($this->saveFormId),
            $id,
            esc_attr($taxonomy)
        );

        return $hidden . $titleHtml . $metaLine;
    }

    public function column_robots($item): string
    {
        $id = (int) ($item['term_id'] ?? 0);
        $index = (string) ($item['robots_index'] ?? '');
        $follow = (string) ($item['robots_follow'] ?? '');

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

        return $this->renderRobotsSelect($nameBase . '[robots_index]', $index, true)
            . $this->renderRobotsSelect($nameBase . '[robots_follow]', $follow, false);
    }

    public function column_default($item, $column_name): string
    {
        $id = (int) ($item['term_id'] ?? 0);
        $nameBase = 'wpsn_bulk_table_terms[' . $id . ']';

        switch ($column_name) {
            case 'seo_title':
                return $this->renderTextInput($nameBase . '[seo_title]', (string) ($item['seo_title'] ?? ''), (string) ($item['resolved_title'] ?? ''), 50);
            case 'meta_description':
                return $this->renderTextarea($nameBase . '[meta_description]', (string) ($item['meta_description'] ?? ''), (string) ($item['resolved_description'] ?? ''), 2);
            case 'canonical':
                return $this->renderTextInput($nameBase . '[canonical]', (string) ($item['canonical'] ?? ''), (string) ($item['resolved_canonical'] ?? ''), 60);
            case 'og_title':
                return $this->renderTextInput($nameBase . '[og_title]', (string) ($item['og_title'] ?? ''), (string) ($item['resolved_og_title'] ?? ''), 50);
            case 'og_description':
                return $this->renderTextarea($nameBase . '[og_description]', (string) ($item['og_description'] ?? ''), (string) ($item['resolved_og_description'] ?? ''), 2);
            case 'og_image':
                return $this->renderTextInput($nameBase . '[og_image]', (string) ($item['og_image'] ?? ''), (string) ($item['resolved_og_image'] ?? ''), 60);
            case 'twitter_title':
                return $this->renderTextInput($nameBase . '[twitter_title]', (string) ($item['twitter_title'] ?? ''), (string) ($item['resolved_twitter_title'] ?? ''), 50);
            case 'twitter_description':
                return $this->renderTextarea($nameBase . '[twitter_description]', (string) ($item['twitter_description'] ?? ''), (string) ($item['resolved_twitter_description'] ?? ''), 2);
            case 'twitter_image':
                return $this->renderTextInput($nameBase . '[twitter_image]', (string) ($item['twitter_image'] ?? ''), (string) ($item['resolved_twitter_image'] ?? ''), 60);
            default:
                return (string) ($item[$column_name] ?? '');
        }
    }

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

        $tax = (string) ($this->filters['tax'] ?? 'any');
        $filter = (string) ($this->filters['filter'] ?? '');

        $taxObjects = get_taxonomies(['public' => true], 'objects');
        if (!is_array($taxObjects)) {
            $taxObjects = [];
        }

        $filters = [
            '' => __('All', 'wp-seo-next'),
            'empty_title' => __('Empty SEO Title override', 'wp-seo-next'),
            'empty_desc' => __('Empty Meta Description override', 'wp-seo-next'),
            'empty_og_image' => __('Empty OG Image override', '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', 'wp-seo-next'),
        ];

        echo '<div class="alignleft actions">';

        echo '<label class="screen-reader-text" for="wpsn_tax">' . esc_html__('Taxonomy', 'wp-seo-next') . '</label>';
        echo '<select name="tax" id="wpsn_tax">';
        echo '<option value="any"' . selected($tax, 'any', false) . '>' . esc_html__('All taxonomies', 'wp-seo-next') . '</option>';
        foreach ($taxObjects as $tx => $obj) {
            if (!is_object($obj)) {
                continue;
            }
            echo '<option value="' . esc_attr((string) $tx) . '"' . selected($tax, (string) $tx, false) . '>' . esc_html((string) ($obj->labels->singular_name ?? $tx)) . '</option>';
        }
        echo '</select>';

        echo '<label class="screen-reader-text" for="wpsn_filter">' . esc_html__('Filter', 'wp-seo-next') . '</label>';
        echo '<select name="filter" id="wpsn_filter">';
        foreach ($filters as $k => $label) {
            echo '<option value="' . esc_attr($k) . '"' . selected($filter, $k, false) . '>' . esc_html($label) . '</option>';
        }
        echo '</select>';

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

    private function renderTextInput(string $name, string $value, string $placeholder = '', int $size = 50): string
    {
        $value = (string) $value;
        $ph = $value === '' ? $placeholder : '';

        return sprintf(
            '<input type="text" form="%s" name="%s" value="%s" placeholder="%s" size="%d" class="regular-text" />',
            esc_attr($this->saveFormId),
            esc_attr($name),
            esc_attr($value),
            esc_attr($ph),
            $size
        );
    }

    private function renderTextarea(string $name, string $value, string $placeholder = '', int $rows = 2): string
    {
        $value = (string) $value;
        $ph = $value === '' ? $placeholder : '';

        return sprintf(
            '<textarea form="%s" name="%s" rows="%d" class="large-text" placeholder="%s">%s</textarea>',
            esc_attr($this->saveFormId),
            esc_attr($name),
            $rows,
            esc_attr($ph),
            esc_textarea($value)
        );
    }

    private function renderRobotsSelect(string $name, string $value, bool $isIndex): string
    {
        $value = $value !== '' ? $value : 'default';
        $options = $isIndex
            ? ['default' => __('Default', 'wp-seo-next'), 'index' => __('Index', 'wp-seo-next'), 'noindex' => __('Noindex', 'wp-seo-next')]
            : ['default' => __('Default', 'wp-seo-next'), 'follow' => __('Follow', 'wp-seo-next'), 'nofollow' => __('Nofollow', 'wp-seo-next')];

        $html = '<select form="' . esc_attr($this->saveFormId) . '" name="' . esc_attr($name) . '" style="margin-right: 6px;">';
        foreach ($options as $k => $label) {
            $html .= '<option value="' . esc_attr($k) . '"' . selected($value, $k, false) . '>' . esc_html($label) . '</option>';
        }
        $html .= '</select>';

        return $html;
    }
}
