<?php
declare(strict_types=1);

namespace Help4BuilderSuite\Compatibility;

use Help4BuilderSuite\Support\Settings;
use Help4BuilderSuite\Support\BusinessProfileDefaults;

if (! defined('ABSPATH')) {
    exit;
}

final class BrandCleanup
{
    private const OPTION_KEY = 'h4bs_brand_cleanup_migration';
    private const MIGRATION_ID = 'website_snapshot_20260619_v3';

    public static function maybeRun(): void
    {
        if ((string) get_option(self::OPTION_KEY, '') === self::MIGRATION_ID) {
            return;
        }
        if (wp_installing()) {
            return;
        }

        self::migrateSettings();
        self::migrateOptions();
        self::migratePostFields();
        self::migratePostMeta();
        self::migrateSliderSlides();

        update_option(self::OPTION_KEY, self::MIGRATION_ID, false);
    }

    private static function migrateSettings(): void
    {
        $settings = get_option(Settings::OPTION_KEY, []);
        if (! is_array($settings)) {
            return;
        }

        $changed = false;
        $copyPairs = [
            'godaddy_router_endpoint' => 'hosted_payments_router_endpoint',
            'godaddy_payments_profile' => 'hosted_payments_profile',
        ];
        foreach ($copyPairs as $oldKey => $newKey) {
            if (! empty($settings[$oldKey]) && empty($settings[$newKey])) {
                $settings[$newKey] = $settings[$oldKey];
                $changed = true;
            }
        }

        foreach (['commerce_gateway_routes', 'commerce_gateway_rules'] as $key) {
            if (! isset($settings[$key])) {
                continue;
            }
            $normalized = self::normalizeLegacyGatewayTokens($settings[$key]);
            if ($normalized !== $settings[$key]) {
                $settings[$key] = $normalized;
                $changed = true;
            }
        }

        if ($changed) {
            update_option(Settings::OPTION_KEY, $settings);
        }
    }

    private static function migrateOptions(): void
    {
        $optionNames = [
            Settings::OPTION_KEY,
            'h4bs_feature_flags',
            'h4bs_global_design_tokens',
            'h4bs_active_theme_pack',
            'h4bs_setup_wizard_answers',
            BusinessProfileDefaults::PROFILE_OPTION,
            BusinessProfileDefaults::SEED_STATE_OPTION,
            'h4bs_google_business_profiles',
            'h4bs_cutover_settings',
        ];

        foreach (array_unique($optionNames) as $optionName) {
            $value = get_option($optionName, null);
            if ($value === null || $value === false) {
                continue;
            }
            if (! self::containsLegacyBrandToken(maybe_serialize($value))) {
                continue;
            }

            $updated = self::replaceBrandValue($value);
            if (maybe_serialize($updated) === maybe_serialize($value)) {
                continue;
            }
            update_option($optionName, $updated);
        }
    }

    private static function migratePostFields(): void
    {
        $postIds = self::legacyPostIdsFromContent();
        if (! $postIds) {
            return;
        }

        foreach ($postIds as $postId) {
            if ($postId < 1) {
                continue;
            }
            $post = get_post($postId);
            if (! $post instanceof \WP_Post || $post->post_status === 'auto-draft') {
                continue;
            }

            $updates = [];
            foreach (['post_title', 'post_excerpt', 'post_content'] as $field) {
                $value = (string) ($post->{$field} ?? '');
                $updated = self::replaceBrandStrings($value);
                if ($updated !== $value) {
                    $updates[$field] = $updated;
                }
            }

            $oldSlug = sanitize_title((string) $post->post_name);
            if (in_array($oldSlug, ['help4-builder-siteshot', 'help4-builder-site-shot'], true)) {
                $updates['post_name'] = 'help4-builder-website-snapshot';
            }

            if (! $updates) {
                continue;
            }
            wp_update_post(wp_slash(array_merge(['ID' => $postId], $updates)));
            if (isset($updates['post_name'])) {
                self::rememberOldSlug($postId, $oldSlug);
            }
            clean_post_cache($postId);
        }
    }

    private static function migratePostMeta(): void
    {
        $postIds = self::legacyPostIdsFromMeta();
        if (! $postIds) {
            return;
        }

        foreach ($postIds as $postId) {
            $postId = absint($postId);
            if ($postId < 1) {
                continue;
            }
            $meta = get_post_meta($postId);
            if (! is_array($meta) || ! $meta) {
                continue;
            }

            $changed = false;
            foreach ($meta as $metaKey => $values) {
                foreach ((array) $values as $rawValue) {
                    if (! self::containsLegacyBrandToken(maybe_serialize($rawValue))) {
                        continue;
                    }
                    $updated = self::replaceBrandValue($rawValue);
                    if (maybe_serialize($updated) === maybe_serialize($rawValue)) {
                        continue;
                    }
                    update_post_meta($postId, (string) $metaKey, $updated, $rawValue);
                    $changed = true;
                }
            }
            if ($changed) {
                clean_post_cache($postId);
            }
        }
    }

    private static function rememberOldSlug(int $postId, string $oldSlug): void
    {
        if ($oldSlug === '' || $oldSlug === 'help4-builder-website-snapshot') {
            return;
        }

        $existing = get_post_meta($postId, '_wp_old_slug', false);
        if (is_array($existing) && in_array($oldSlug, array_map('strval', $existing), true)) {
            return;
        }

        add_post_meta($postId, '_wp_old_slug', $oldSlug);
    }

    /**
     * @param mixed $value
     * @return mixed
     */
    private static function replaceBrandValue($value)
    {
        if (is_array($value)) {
            $out = [];
            foreach ($value as $key => $item) {
                $newKey = is_string($key) ? self::replaceBrandStrings($key) : $key;
                $newItem = self::replaceBrandValue($item);
                if (array_key_exists($newKey, $out)) {
                    if (self::isEmptyCompatValue($out[$newKey]) && ! self::isEmptyCompatValue($newItem)) {
                        $out[$newKey] = $newItem;
                    }
                    continue;
                }
                $out[$newKey] = $newItem;
            }
            return $out;
        }

        if (is_object($value)) {
            foreach (get_object_vars($value) as $key => $item) {
                $value->{$key} = self::replaceBrandValue($item);
            }
            return $value;
        }

        if (is_string($value)) {
            return self::replaceBrandStrings($value);
        }

        return $value;
    }

    private static function migrateSliderSlides(): void
    {
        $sliders = get_posts(
            [
                'post_type'      => 'h4_slider',
                'post_status'    => 'any',
                'posts_per_page' => -1,
                'fields'         => 'ids',
            ]
        );
        if (! is_array($sliders) || ! $sliders) {
            return;
        }

        foreach ($sliders as $sliderId) {
            $postId = absint($sliderId);
            if ($postId < 1) {
                continue;
            }
            $raw = (string) get_post_meta($postId, '_h4_slider_slides', true);
            if ($raw === '' || ! self::containsLegacyBrandToken($raw)) {
                continue;
            }
            $decoded = json_decode($raw, true);
            if (! is_array($decoded)) {
                $updated = self::replaceBrandStrings($raw);
                if ($updated !== $raw) {
                    update_post_meta($postId, '_h4_slider_slides', wp_slash($updated));
                }
                continue;
            }

            $changed = false;
            foreach ($decoded as &$slide) {
                if (! is_array($slide)) {
                    continue;
                }
                if (($slide['source'] ?? '') === 'siteshot') {
                    $slide['source'] = 'snapshot';
                    $changed = true;
                }
                foreach ([
                    'siteshot_url' => 'snapshot_url',
                    'siteshot_width' => 'snapshot_width',
                    'siteshot_height' => 'snapshot_height',
                ] as $oldKey => $newKey) {
                    if (array_key_exists($oldKey, $slide)) {
                        if (! array_key_exists($newKey, $slide)) {
                            $slide[$newKey] = $slide[$oldKey];
                        }
                        unset($slide[$oldKey]);
                        $changed = true;
                    }
                }
            }
            unset($slide);

            if ($changed) {
                update_post_meta(
                    $postId,
                    '_h4_slider_slides',
                    wp_slash((string) wp_json_encode($decoded, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES))
                );
            }
        }
    }

    private static function replaceBrandStrings(string $value): string
    {
        $replacements = [
            '[h4_siteshot' => '[h4_website_snapshot',
            'h4_siteshot' => 'h4_website_snapshot',
            'data-siteshot-fit' => 'data-snapshot-fit',
            '--h4bs-siteshot-fit' => '--h4bs-snapshot-fit',
            'h4bs-siteshot-' => 'h4bs-website-snapshot-',
            'h4-siteshot-' => 'h4-website-snapshot-',
            'siteshot_fit' => 'snapshot_fit',
            'siteshot_url' => 'snapshot_url',
            'siteshot_width' => 'snapshot_width',
            'siteshot_height' => 'snapshot_height',
            'starter-siteshot-' => 'starter-website-snapshot-',
            'siteshot-gallery' => 'website-snapshot-gallery',
            'siteshot-' => 'website-snapshot-',
            'kit-siteshot-' => 'kit-website-snapshot-',
            'help4-builder-siteshot' => 'help4-builder-website-snapshot',
            'help4-builder-site-shot' => 'help4-builder-website-snapshot',
            'SiteShot' => 'Website Snapshot',
            'site-shot' => 'website snapshot',
            'Site shot' => 'Website snapshot',
            'site shot' => 'website snapshot',
            'godaddy_router_endpoint' => 'hosted_payments_router_endpoint',
            'godaddy_payments_profile' => 'hosted_payments_profile',
            'godaddy_payments_route' => 'hosted_payments_route',
            'godaddy_payments' => 'hosted_payments',
            'GoDaddy Payments' => 'Hosted Payments',
        ];

        return str_replace(array_keys($replacements), array_values($replacements), $value);
    }

    /**
     * @return array<int, string>
     */
    private static function legacySearchTokens(): array
    {
        return [
            'h4_siteshot',
            'siteshot',
            'SiteShot',
            'site-shot',
            'GoDaddy Payments',
            'godaddy_payments',
            'godaddy_router_endpoint',
        ];
    }

    /**
     * @return array<int, int>
     */
    private static function legacyPostIdsFromContent(): array
    {
        $ids = [];
        foreach (['help4-builder-siteshot', 'help4-builder-site-shot'] as $slug) {
            $page = get_page_by_path($slug, OBJECT, 'page');
            if ($page instanceof \WP_Post) {
                $ids[(int) $page->ID] = (int) $page->ID;
            }
        }

        foreach (self::legacySearchTokens() as $token) {
            $posts = get_posts(
                [
                    'post_type'              => 'any',
                    'post_status'            => 'any',
                    'posts_per_page'         => 250,
                    'fields'                 => 'ids',
                    's'                      => $token,
                    'no_found_rows'          => true,
                    'orderby'                => 'ID',
                    'order'                  => 'DESC',
                    'update_post_meta_cache' => false,
                    'update_post_term_cache' => false,
                    'suppress_filters'       => false,
                ]
            );
            foreach ((array) $posts as $postId) {
                $ids[absint($postId)] = absint($postId);
            }
        }

        unset($ids[0]);
        return array_values($ids);
    }

    /**
     * @return array<int, int>
     */
    private static function legacyPostIdsFromMeta(): array
    {
        $ids = [];
        for ($page = 1; $page <= 20; $page++) {
            $posts = get_posts(
                [
                    'post_type'              => 'any',
                    'post_status'            => 'any',
                    'posts_per_page'         => 250,
                    'paged'                  => $page,
                    'fields'                 => 'ids',
                    'no_found_rows'          => true,
                    'orderby'                => 'ID',
                    'order'                  => 'DESC',
                    'update_post_meta_cache' => true,
                    'update_post_term_cache' => false,
                    'suppress_filters'       => false,
                ]
            );
            if (! is_array($posts) || ! $posts) {
                break;
            }
            foreach ((array) $posts as $postId) {
                $ids[absint($postId)] = absint($postId);
            }
            if (count($posts) < 250) {
                break;
            }
        }

        unset($ids[0]);
        return array_values($ids);
    }

    private static function containsLegacyBrandToken(string $value): bool
    {
        foreach (self::legacySearchTokens() as $token) {
            if (str_contains($value, $token)) {
                return true;
            }
        }

        return false;
    }

    /**
     * @param mixed $value
     */
    private static function isEmptyCompatValue($value): bool
    {
        if (is_array($value)) {
            return $value === [];
        }

        if (is_object($value)) {
            return get_object_vars($value) === [];
        }

        return trim((string) $value) === '';
    }

    /**
     * @param mixed $value
     * @return mixed
     */
    private static function normalizeLegacyGatewayTokens($value)
    {
        if (is_array($value)) {
            $out = [];
            foreach ($value as $key => $item) {
                $out[$key] = self::normalizeLegacyGatewayTokens($item);
            }
            return $out;
        }

        if (is_string($value)) {
            return str_replace(
                [
                    'godaddy_payments_route',
                    'godaddy_payments',
                    'GoDaddy Payments',
                ],
                [
                    'hosted_payments_route',
                    'hosted_payments',
                    'Hosted Payments',
                ],
                $value
            );
        }

        return $value;
    }
}
