<?php
defined( 'ABSPATH' ) || exit;

class SITECL_SEO_Checker {

    public static function scan(): array {
        $posts = get_posts( [
            'post_type'      => [ 'post', 'page' ],
            'post_status'    => 'publish',
            'posts_per_page' => 500,
        ] );

        if ( empty( $posts ) ) {
            return [];
        }

        $issues = [];

        foreach ( $posts as $post ) {
            $post_issues = self::check_post( $post );
            foreach ( $post_issues as $issue ) {
                $issues[] = $issue;
            }
        }

        // Site-wide: duplicate title check.
        $issues = array_merge( $issues, self::check_duplicate_titles( $posts ) );

        return $issues;
    }

    // -------------------------------------------------------------------------

    private static function check_post( WP_Post $post ): array {
        $issues  = [];
        $edit_url = get_edit_post_link( $post->ID, 'raw' );
        $label   = esc_html( $post->post_title );

        // Missing meta description (Yoast / RankMath / native).
        $meta_desc = self::get_meta_description( $post->ID );
        if ( empty( $meta_desc ) ) {
            $issues[] = self::issue( $post->ID, $label, $edit_url, 'warning',
                __( 'Missing meta description', 'site-cliniq' ),
                __( 'Add a unique meta description (120–160 chars) via your SEO plugin.', 'site-cliniq' )
            );
        }

        // Missing or multiple H1.
        preg_match_all( '/<h1[^>]*>/i', $post->post_content, $h1_matches );
        $h1_count = count( $h1_matches[0] );
        if ( $h1_count === 0 ) {
            $issues[] = self::issue( $post->ID, $label, $edit_url, 'warning',
                __( 'No H1 heading found', 'site-cliniq' ),
                __( 'Add one H1 heading that includes your main keyword.', 'site-cliniq' )
            );
        } elseif ( $h1_count > 1 ) {
            $issues[] = self::issue( $post->ID, $label, $edit_url, 'info',
                /* translators: %d: number of H1 headings found on the page */
                sprintf( __( 'Multiple H1 headings (%d)', 'site-cliniq' ), $h1_count ),
                __( 'Use only one H1 per page. Remaining headings should be H2 or H3.', 'site-cliniq' )
            );
        }

        // Noindex on public page.
        $robots = get_post_meta( $post->ID, '_yoast_wpseo_meta-robots-noindex', true )
               ?: get_post_meta( $post->ID, 'rank_math_robots', true );
        if ( $robots && str_contains( (string) $robots, 'noindex' ) ) {
            $issues[] = self::issue( $post->ID, $label, $edit_url, 'critical',
                __( 'Page is set to noindex (hidden from Google)', 'site-cliniq' ),
                __( 'Remove the noindex setting in your SEO plugin unless this page should be excluded from search.', 'site-cliniq' )
            );
        }

        // Thin content (< 300 words).
        $word_count = str_word_count( wp_strip_all_tags( $post->post_content ) );
        if ( $word_count < 300 && $post->post_type === 'post' ) {
            $issues[] = self::issue( $post->ID, $label, $edit_url, 'info',
                /* translators: %d: number of words in the post */
                sprintf( __( 'Thin content: %d words', 'site-cliniq' ), $word_count ),
                __( 'Expand this post to at least 300 words to improve SEO.', 'site-cliniq' )
            );
        }

        // No images.
        if ( ! has_post_thumbnail( $post->ID ) && ! str_contains( $post->post_content, '<img' ) ) {
            $issues[] = self::issue( $post->ID, $label, $edit_url, 'info',
                __( 'No images in post', 'site-cliniq' ),
                __( 'Add at least one image to improve engagement and SEO.', 'site-cliniq' )
            );
        }

        // No internal links.
        $site_domain = wp_parse_url( home_url(), PHP_URL_HOST );
        preg_match_all( '/<a\s[^>]*href=["\']([^"\']+)["\'][^>]*>/i', $post->post_content, $links );
        $internal = array_filter( $links[1], fn( $url ) => str_contains( $url, $site_domain ) || str_starts_with( $url, '/' ) );

        if ( empty( $internal ) ) {
            $issues[] = self::issue( $post->ID, $label, $edit_url, 'info',
                __( 'No internal links', 'site-cliniq' ),
                __( 'Link to at least 2–3 other pages on your site to improve navigation and SEO.', 'site-cliniq' )
            );
        }

        return $issues;
    }

    private static function check_duplicate_titles( array $posts ): array {
        $titles = [];
        foreach ( $posts as $post ) {
            $title = trim( $post->post_title );
            $titles[ $title ][] = $post->ID;
        }

        $issues = [];
        foreach ( $titles as $title => $ids ) {
            if ( count( $ids ) < 2 ) {
                continue;
            }
            $issues[] = [
                'type'     => 'seo',
                'severity' => 'warning',
                /* translators: %s: the duplicate page title text */
                'title'    => sprintf( __( 'Duplicate page title: "%s"', 'site-cliniq' ), esc_html( $title ) ),
                /* translators: %d: number of posts or pages sharing this duplicate title */
                'detail'   => sprintf( __( 'Used on %d posts/pages. Each page needs a unique title for SEO.', 'site-cliniq' ), count( $ids ) ),
                'post_ids' => $ids,
            ];
        }

        return $issues;
    }

    // -------------------------------------------------------------------------

    private static function get_meta_description( int $post_id ): string {
        // Yoast.
        $desc = get_post_meta( $post_id, '_yoast_wpseo_metadesc', true );
        if ( $desc ) {
            return (string) $desc;
        }
        // RankMath.
        $desc = get_post_meta( $post_id, 'rank_math_description', true );
        if ( $desc ) {
            return (string) $desc;
        }
        // AIOSEO.
        $desc = get_post_meta( $post_id, '_aioseo_description', true );
        return (string) $desc;
    }

    private static function issue( int $post_id, string $label, ?string $edit_url, string $severity, string $title, string $detail ): array {
        return [
            'type'     => 'seo',
            'severity' => $severity,
            'title'    => "{$label}: {$title}",
            'detail'   => $detail,
            'post_id'  => $post_id,
            'edit_url' => $edit_url,
        ];
    }
}
