<?php

namespace WPSN\Modules\Robots;

use WPSN\Core\AbstractModule;
use WPSN\Core\Branding;
use WPSN\Core\ModuleRegistry;

defined('ABSPATH') || exit;

/**
 * Stage 6: robots.txt helpers.
 *
 * We don't create a physical file. WordPress serves a virtual robots.txt at /robots.txt.
 * This module safely appends extra directives and the sitemap reference.
 */
final class RobotsModule extends AbstractModule
{
    public function id(): string
    {
        return 'robots';
    }

    public function name(): string
    {
        return __('Robots.txt', 'wp-seo-next');
    }

    public function description(): string
    {
        return __('Virtual robots.txt rules + optional Sitemap directive.', 'wp-seo-next');
    }

    public function defaultEnabled(): bool
    {
        return true;
    }

    public function register(): void
    {
        add_filter('robots_txt', [$this, 'filterRobotsTxt'], 99, 2);
    }

    public function filterRobotsTxt(string $output, bool $public): string
    {
        $output = trim($output);
        if ($output !== '') {
            $output .= "\n";
        }

        $brand = Branding::brand($this->settings);
        if ($brand !== '') {
            // Prevent comment breakouts.
            $brand = sanitize_text_field($brand);
            $brand = str_replace(['--', '>', '<'], '', $brand);
            if ($brand !== '') {
                $output .= "# {$brand}\n";
            }
        }

        $appendSitemap = (bool) $this->settings->get('robots_txt.append_sitemap', true);

        /** @var ModuleRegistry $modules */
        $modules = $this->container->get('modules');

        if ($public && $appendSitemap && $modules->isEnabled('sitemap')) {
            $sitemap = home_url('/sitemap_index.xml');

            // Avoid duplicates if another plugin already added it.
            if (stripos($output, 'Sitemap:') === false || stripos($output, $sitemap) === false) {
                $output .= 'Sitemap: ' . $sitemap . "\n";
            }
        }

        // Managed Allow/Disallow rules (stored as structured list in settings).
        $rules = $this->settings->get('robots_txt.disallow_rules', []);
        $lines = [];
        if (is_array($rules)) {
            foreach ($rules as $r) {
                if (!is_array($r)) {
                    continue;
                }
                if (isset($r['enabled']) && !$r['enabled']) {
                    continue;
                }
                $line = isset($r['line']) ? RobotsDisallowRules::normalizeLine((string) $r['line']) : '';
                if ($line === '') {
                    continue;
                }

                $meta = '';
                $src = isset($r['source']) ? sanitize_key((string) $r['source']) : '';
                $note = isset($r['note']) ? sanitize_text_field((string) $r['note']) : '';
                if ($src !== '' && $note !== '') {
                    $meta = $src . ': ' . $note;
                } elseif ($src !== '') {
                    $meta = $src;
                } elseif ($note !== '') {
                    $meta = $note;
                }
                if ($meta !== '') {
                    $meta = substr($meta, 0, 120);
                    $lines[] = '# ' . $meta;
                }

                $lines[] = $line;
            }
        }

        if (!empty($lines)) {
            $output .= "\n";
            $output .= "# Managed rules (WP SEO Next)\n";
            // Reset UA scope so rules remain global even if custom rules contain other sections.
            $output .= "User-agent: *\n";
            $output .= implode("\n", $lines) . "\n";
        }

        // Structured User-agent groups (stored outside free-form custom rules).
        $agentGroups = $this->settings->get('robots_txt.agent_groups', []);
        if (is_array($agentGroups)) {
            $blocks = [];

            foreach ($agentGroups as $group) {
                if (!is_array($group)) {
                    continue;
                }
                if (isset($group['enabled']) && !$group['enabled']) {
                    continue;
                }

                $userAgent = isset($group['user_agent']) ? RobotsUserAgentRules::normalizeUserAgent((string) $group['user_agent']) : '';
                if ($userAgent === '') {
                    continue;
                }

                $groupLines = isset($group['lines']) && is_array($group['lines']) ? RobotsUserAgentRules::normalizeLines($group['lines']) : [];
                if (empty($groupLines)) {
                    continue;
                }

                $block = [];
                $meta = '';
                $source = isset($group['source']) ? sanitize_key((string) $group['source']) : '';
                $note = isset($group['note']) ? sanitize_text_field((string) $group['note']) : '';
                if ($source !== '' && $note !== '') {
                    $meta = $source . ': ' . $note;
                } elseif ($source !== '') {
                    $meta = $source;
                } elseif ($note !== '') {
                    $meta = $note;
                }
                if ($meta !== '') {
                    $block[] = '# ' . substr($meta, 0, 160);
                }

                $block[] = 'User-agent: ' . $userAgent;
                foreach ($groupLines as $line) {
                    $block[] = $line;
                }

                $blocks[] = implode("\n", $block);
            }

            if (!empty($blocks)) {
                $output .= "\n";
                $output .= "# User-agent rules (WP SEO Next)\n";
                $output .= implode("\n\n", $blocks) . "\n";
            }
        }

        $custom = (string) $this->settings->get('robots_txt.custom', '');
        $custom = trim($custom);
        if ($custom !== '') {
            $output .= "\n";
            $output .= "# Custom rules (validated)\n";
            $output .= $custom . "\n";
        }

        return rtrim($output) . "\n";
    }
}
