<?php

namespace WPSN\Modules\ImportExport;

defined('ABSPATH') || exit;

final class ImportAssistChecklistBuilder
{
    /**
     * @param array<string,mixed> $entry
     * @return array<int,array{key:string,label:string,description:string,url:string,url_label:string,priority:string}>
     */
    public function build(array $entry, string $reviewUrl = ''): array
    {
        $tasks = [];
        $haystack = $this->entryHaystack($entry);
        $kind = isset($entry['kind']) ? sanitize_key((string) $entry['kind']) : '';
        $summary = isset($entry['summary']) && is_array($entry['summary']) ? $entry['summary'] : [];

        if ($reviewUrl !== '') {
            $this->addTask(
                $tasks,
                'report',
                __('Open the raw import report', 'wp-seo-next'),
                __('Use the original report when you want to compare source fields, confirm skipped paths, or audit anything that still looks off after the import.', 'wp-seo-next'),
                $reviewUrl,
                __('Open report', 'wp-seo-next'),
                'low'
            );
        }

        if ($this->containsAny($haystack, ['archive controls', 'author archive', 'date archive', 'post type archive', 'robots.author_archive', 'robots.date_archive', 'robots.post_type_archive', 'attachment pages'])) {
            $this->addTask(
                $tasks,
                'archives',
                __('Review Archive Controls', 'wp-seo-next'),
                __('Check author/date/post-type archive robots and attachment-page behavior after the import.', 'wp-seo-next'),
                $this->settingsUrl('#wpsn-settings-archives'),
                __('Open Archive Controls', 'wp-seo-next'),
                'high'
            );
        }

        if ($this->containsAny($haystack, ['breadcrumb', 'breadcrumbs'])) {
            $this->addTask(
                $tasks,
                'breadcrumbs',
                __('Review Breadcrumbs', 'wp-seo-next'),
                __('Confirm the separator, home label, and archive behavior match the old plugin or the new site setup.', 'wp-seo-next'),
                $this->settingsUrl('#wpsn-settings-breadcrumbs'),
                __('Open Breadcrumbs', 'wp-seo-next'),
                'medium'
            );
        }

        if ($this->containsAny($haystack, ['schema', 'json-ld', 'structured data', 'schema_type'])) {
            $this->addTask(
                $tasks,
                'schema',
                __('Review Schema and custom JSON-LD', 'wp-seo-next'),
                __('Source plugins often store schema defaults differently. Double-check schema defaults, templates, and any custom JSON-LD rules.', 'wp-seo-next'),
                $this->settingsUrl('#wpsn-settings-schema'),
                __('Open Schema settings', 'wp-seo-next'),
                'high'
            );
        }

        if ($this->containsAny($haystack, ['redirect', 'regex'])) {
            $this->addTask(
                $tasks,
                'redirects',
                __('Review Redirect Migration', 'wp-seo-next'),
                __('Check skipped or unsupported redirects and verify regex rules if the source plugin used them.', 'wp-seo-next'),
                admin_url('tools.php?page=wpsn-redirect-migration'),
                __('Open Redirect Migration', 'wp-seo-next'),
                'high'
            );
        }

        if ($this->containsAny($haystack, ['stripcategorybase', 'category base', 'permalink', 'search url', 'canonicalization', 'archive rewrites'])) {
            $this->addTask(
                $tasks,
                'search_urls',
                __('Review Search URL / permalink behavior', 'wp-seo-next'),
                __('Check canonical search URLs and any source-plugin permalink behavior such as category-base stripping or archive rewrites.', 'wp-seo-next'),
                $this->settingsUrl('#wpsn-settings-search-urls'),
                __('Open Search URL settings', 'wp-seo-next'),
                'medium'
            );
        }

        if ($this->containsAny($haystack, ['title separator', 'title template', 'meta description', 'templates.title', 'templates.description', 'default title template', 'default meta description'])) {
            $this->addTask(
                $tasks,
                'templates',
                __('Review title and description templates', 'wp-seo-next'),
                __('Spot-check default title and meta-description templates to make sure separators and token behavior match expectations.', 'wp-seo-next'),
                $this->settingsUrl('#wpsn-settings-templates'),
                __('Open Templates', 'wp-seo-next'),
                'medium'
            );
        }

        if ($this->containsAny($haystack, ['robots meta', 'robots index', 'robots follow', 'noindex', 'nofollow'])) {
            $this->addTask(
                $tasks,
                'robots',
                __('Review Robots meta defaults', 'wp-seo-next'),
                __('Confirm the imported index/follow defaults still match how you want posts, pages, and archives handled.', 'wp-seo-next'),
                $this->settingsUrl('#wpsn-settings-robots'),
                __('Open Robots meta', 'wp-seo-next'),
                'medium'
            );
        }

        if ($this->containsAny($haystack, ['social meta', 'og ', 'open graph', 'twitter', 'facebook', 'social'])) {
            $this->addTask(
                $tasks,
                'social',
                __('Review Social defaults', 'wp-seo-next'),
                __('Check default OG/Twitter titles, descriptions, and fallback images after the import.', 'wp-seo-next'),
                $this->settingsUrl('#wpsn-settings-social'),
                __('Open Social settings', 'wp-seo-next'),
                'medium'
            );
        }

        if ($this->containsAny($haystack, ['local seo', 'organization', 'logo', 'address', 'nap', 'business'])) {
            $this->addTask(
                $tasks,
                'local',
                __('Review Local / Organization details', 'wp-seo-next'),
                __('Confirm logo, business name, address, and other organization or local SEO details after the import.', 'wp-seo-next'),
                $this->settingsUrl('#wpsn-settings-local'),
                __('Open Local SEO', 'wp-seo-next'),
                'medium'
            );
        }

        if ($this->containsAny($haystack, ['indexnow'])) {
            $this->addTask(
                $tasks,
                'indexnow',
                __('Review IndexNow setup', 'wp-seo-next'),
                __('Verify the key and module state if the old plugin did not export a reusable IndexNow key.', 'wp-seo-next'),
                $this->settingsUrl('#wpsn-settings-indexnow'),
                __('Open IndexNow', 'wp-seo-next'),
                'low'
            );
        }

        if ($this->containsAny($haystack, ['sitemap'])) {
            $this->addTask(
                $tasks,
                'sitemaps',
                __('Review Sitemaps', 'wp-seo-next'),
                __('Check sitemap coverage and exclusions after the import, especially if the source plugin used custom sitemap rules.', 'wp-seo-next'),
                $this->settingsUrl('#wpsn-sitemaps'),
                __('Open Sitemaps', 'wp-seo-next'),
                'low'
            );
        }

        if ($kind === 'migration' && !empty($summary['posts_updated'])) {
            $this->addTask(
                $tasks,
                'content_qa',
                __('Spot-check migrated content', 'wp-seo-next'),
                __('Review a few high-value posts or pages to confirm migrated titles, descriptions, social fields, and schema-related fields look correct.', 'wp-seo-next'),
                $reviewUrl !== '' ? $reviewUrl : admin_url('tools.php?page=wpsn-import-export'),
                $reviewUrl !== '' ? __('Open migration report', 'wp-seo-next') : __('Open Import Assist', 'wp-seo-next'),
                'medium'
            );
        }

        usort($tasks, function (array $a, array $b): int {
            $weight = ['high' => 0, 'medium' => 1, 'low' => 2];
            $aWeight = $weight[$a['priority']] ?? 9;
            $bWeight = $weight[$b['priority']] ?? 9;
            if ($aWeight === $bWeight) {
                return strcmp($a['label'], $b['label']);
            }
            return $aWeight <=> $bWeight;
        });

        return array_values($tasks);
    }

    /**
     * @param array<int,array{key:string,label:string,description:string,url:string,url_label:string,priority:string}> $tasks
     */
    private function addTask(array &$tasks, string $key, string $label, string $description, string $url, string $urlLabel, string $priority): void
    {
        if ($url === '') {
            return;
        }
        foreach ($tasks as $task) {
            if (($task['key'] ?? '') === $key) {
                return;
            }
        }
        $tasks[] = [
            'key' => $key,
            'label' => $label,
            'description' => $description,
            'url' => $url,
            'url_label' => $urlLabel,
            'priority' => $priority,
        ];
    }

    /**
     * @param array<string,mixed> $entry
     */
    private function entryHaystack(array $entry): string
    {
        $parts = [];
        foreach (['title', 'source_label', 'context', 'kind', 'source'] as $key) {
            if (!empty($entry[$key]) && is_scalar($entry[$key])) {
                $parts[] = (string) $entry[$key];
            }
        }

        $summary = isset($entry['summary']) && is_array($entry['summary']) ? $entry['summary'] : [];
        foreach ($summary as $value) {
            if (is_scalar($value)) {
                $parts[] = (string) $value;
            }
        }

        $items = isset($entry['items']) && is_array($entry['items']) ? $entry['items'] : [];
        foreach ($items as $bucket) {
            if (!is_array($bucket)) {
                continue;
            }
            foreach ($bucket as $value) {
                if (is_scalar($value)) {
                    $parts[] = (string) $value;
                }
            }
        }

        return strtolower(implode("\n", $parts));
    }

    /**
     * @param array<int,string> $needles
     */
    private function containsAny(string $haystack, array $needles): bool
    {
        foreach ($needles as $needle) {
            $needle = trim(strtolower((string) $needle));
            if ($needle === '') {
                continue;
            }
            if (strpos($haystack, $needle) !== false) {
                return true;
            }
        }
        return false;
    }

    private function settingsUrl(string $anchor): string
    {
        return admin_url('admin.php?page=wp-seo-next') . $anchor;
    }
}
