<?php

namespace WPSN\SEO;

use WPSN\Domain\SeoDocumentContext;

defined('ABSPATH') || exit;

final class DocumentResolver
{
    /**
     * Resolve current WP query into a SeoDocumentContext.
     */
    public function resolve(): SeoDocumentContext
    {
        $paged = (int) get_query_var('paged');
        if ($paged < 1) {
            $paged = (int) get_query_var('page');
        }
        $paged = max(1, $paged);

        if (is_singular()) {
            $post = get_queried_object();
            $id   = ($post && isset($post->ID)) ? (int) $post->ID : null;
            $url  = $id ? get_permalink($id) : home_url(add_query_arg([]));
            $sub  = $id ? get_post_type($id) : null;

            $ctx = new SeoDocumentContext(SeoDocumentContext::TYPE_SINGULAR, $id, $sub, $url, $paged);
        } elseif (is_category() || is_tag() || is_tax()) {
            $term = get_queried_object();
            $id   = ($term && isset($term->term_id)) ? (int) $term->term_id : null;
            $tax  = ($term && isset($term->taxonomy)) ? (string) $term->taxonomy : null;

            $link = ($id && $tax) ? get_term_link($id, $tax) : home_url(add_query_arg([]));
            $url  = is_string($link) ? $link : home_url(add_query_arg([]));

            $ctx = new SeoDocumentContext(SeoDocumentContext::TYPE_TERM, $id, $tax, $url, $paged);
        } elseif (is_front_page() || is_home()) {
            $url = home_url('/');

            // Static front page / posts page support.
            if (get_option('show_on_front') === 'page') {
                if (function_exists('is_front_page') && is_front_page()) {
                    $frontId = (int) get_option('page_on_front');
                    if ($frontId > 0) {
                        $p = get_permalink($frontId);
                        if (is_string($p) && $p !== '') {
                            $url = $p;
                        }
                    }
                } elseif (function_exists('is_home') && is_home()) {
                    $postsId = (int) get_option('page_for_posts');
                    if ($postsId > 0) {
                        $p = get_permalink($postsId);
                        if (is_string($p) && $p !== '') {
                            $url = $p;
                        }
                    }
                }
            }

            $ctx = new SeoDocumentContext(SeoDocumentContext::TYPE_HOME, null, null, $url, $paged);
        } elseif (is_search()) {
            $url = function_exists('get_search_link') ? get_search_link(get_search_query(false)) : home_url(add_query_arg([]));
            $url = is_string($url) ? $url : home_url(add_query_arg([]));
            $ctx = new SeoDocumentContext(SeoDocumentContext::TYPE_SEARCH, null, null, $url, $paged);
        } elseif (is_404()) {
            // 404 has no canonical, but Social/schema may still want a stable URL.
            $url = home_url(add_query_arg([]));
            $url = is_string($url) ? $url : home_url('/');
            $ctx = new SeoDocumentContext(SeoDocumentContext::TYPE_404, null, null, $url, $paged);
        } elseif (is_archive()) {
            $url = $this->resolveArchiveUrl();

            // Author archive context (for template variables / schema enhancements).
            if (function_exists('is_author') && is_author()) {
                $authorId = (int) get_queried_object_id();
                if ($authorId > 0) {
                    $ctx = new SeoDocumentContext(SeoDocumentContext::TYPE_ARCHIVE, $authorId, 'author', $url, $paged);
                } else {
                    $ctx = new SeoDocumentContext(SeoDocumentContext::TYPE_ARCHIVE, null, null, $url, $paged);
                }
            } else {
                $ctx = new SeoDocumentContext(SeoDocumentContext::TYPE_ARCHIVE, null, null, $url, $paged);
            }
        } else {
            $ctx = new SeoDocumentContext(SeoDocumentContext::TYPE_ARCHIVE, null, null, home_url('/'), $paged);
        }

        /**
         * Allow third-parties / modules to tweak the resolved document context.
         *
         * @since 0.1.0
         */
        $ctx = apply_filters('wpsn/document_context', $ctx);

        return $ctx;
    }
    /**
     * Resolve a stable URL for archive-like contexts (author/date/post type archive).
     */
    private function resolveArchiveUrl(): string
    {
        // Post type archive.
        if (function_exists('is_post_type_archive') && is_post_type_archive()) {
            $pt = get_query_var('post_type');
            if (is_array($pt)) {
                $pt = reset($pt);
            }
            $pt = is_string($pt) ? $pt : '';
            if ($pt !== '') {
                $url = get_post_type_archive_link($pt);
                if (is_string($url) && $url !== '') {
                    return $url;
                }
            }
        }

        // Author archive.
        if (function_exists('is_author') && is_author()) {
            $authorId = (int) get_queried_object_id();
            if ($authorId > 0) {
                $url = get_author_posts_url($authorId);
                if (is_string($url) && $url !== '') {
                    return $url;
                }
            }
        }

        // Date archives.
        if (function_exists('is_date') && is_date()) {
            $y = (int) get_query_var('year');
            $m = (int) get_query_var('monthnum');
            $d = (int) get_query_var('day');

            if (function_exists('is_day') && is_day() && $y > 0 && $m > 0 && $d > 0) {
                $url = get_day_link($y, $m, $d);
                if (is_string($url) && $url !== '') {
                    return $url;
                }
            }

            if (function_exists('is_month') && is_month() && $y > 0 && $m > 0) {
                $url = get_month_link($y, $m);
                if (is_string($url) && $url !== '') {
                    return $url;
                }
            }

            if (function_exists('is_year') && is_year() && $y > 0) {
                $url = get_year_link($y);
                if (is_string($url) && $url !== '') {
                    return $url;
                }
            }
        }

        // Generic archive title page; fall back to current URL with query args.
        $url = home_url(add_query_arg([]));
        return is_string($url) && $url !== '' ? $url : (string) home_url('/');
    }

}
