<?php

namespace App\Http\Controllers;

use App\Models\Article;
use App\Models\Category;
use App\Models\Tag;
use Carbon\Carbon;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\URL;

class SitemapController extends Controller
{
    /**
     * Generate sitemap index XML
     */
    public function index(): Response
    {
        $xml = Cache::remember('blog-sitemap', now()->addHours(24), function () {
            $sitemaps = [];

            // Generate post sitemaps (200 posts per file)
            $totalPosts = Article::published()->count();
            $postsPerSitemap = 200;
            $totalPostSitemaps = ceil($totalPosts / $postsPerSitemap);

            for ($i = 1; $i <= $totalPostSitemaps; $i++) {
                $sitemaps[] = [
                    'loc'     => route('sitemap.posts.paginated', ['page' => $i]),
                    'lastmod' => $this->getLastPostModified(),
                ];
            }

            // Add other sitemaps
            $sitemaps[] = [
                'loc'     => route('sitemap.pages'),
                'lastmod' => Carbon::now()->toAtomString(),
            ];

            $sitemaps[] = [
                'loc'     => route('sitemap.categories'),
                'lastmod' => $this->getLastCategoryModified(),
            ];

            return $this->generateSitemapIndexXml($sitemaps);
        });

        return response($xml, 200)->header('Content-Type', 'application/xml');
    }

    /**
     * Generate paginated posts sitemap XML
     */
    public function postsPaginated($page = 1): Response
    {
        $xml = Cache::remember('blog-post-' . $page, now()->addHours(24), function () use ($page) {
            $postsPerPage = 200;
            $offset = ($page - 1) * $postsPerPage;

            $articles = Article::published()
                ->with(['primaryCategory'])
                ->orderBy('updated_at', 'desc')
                ->offset($offset)
                ->limit($postsPerPage)
                ->get();

            $urls = [];

            foreach ($articles as $article) {
                if ($article->type === 0) {
                    // Mattock blog URLs: /blog/{category}/{slug}
                    $categorySlug = $article->primaryCategory->slug ?? 'detail';
                    $url = route('blog.detail', [
                        'category' => $categorySlug,
                        'slug'     => $article->slug,
                    ]);
                } else {
                    // Pipopa blog URLs: /blog/ai-chatbot/{slug}
                    $url = route('pipopa.blog.detail', [
                        'slug' => $article->slug,
                    ]);
                }

                // Extract images from article content
                $images = $this->extractImagesFromContent($article->content);

                $urls[] = [
                    'loc'        => $url . '/',
                    'lastmod'    => $article->updated_at->toAtomString(),
                    'changefreq' => 'weekly',
                    'priority'   => '0.8',
                    'images'     => $images,
                ];
            }

            return $this->generateUrlsetWithImagesXml($urls);
        });

        return response($xml, 200)->header('Content-Type', 'application/xml');
    }

    /**
     * Generate categories sitemap XML
     */
    public function categories(): Response
    {
        $xml = Cache::remember('blog-category-sitemap', now()->addHours(24), function () {
            $categories = Category::with(['publishedArticles'])
                ->whereHas('publishedArticles')
                ->orderBy('updated_at', 'desc')
                ->get();

            $urls = [];

            foreach ($categories as $category) {
                if ($category->type === 0) {
                    $url = route('blog.category', ['category' => $category->slug]);
                } else {
                    $url = route('pipopa.blog.category', ['category' => $category->slug]);
                }

                $url .= $this->getCategoryParentPath($category);

                $urls[] = [
                    'loc'        => $url . '/',
                    'lastmod'    => $this->getLastCategoryModified(),
                    'changefreq' => 'weekly',
                    'priority'   => '0.6',
                ];
            }

            return $this->generateUrlsetXml($urls);
        });

        return response($xml, 200)->header('Content-Type', 'application/xml');
    }

    /**
     * Generate tags sitemap XML
     */
    public function tags(): Response
    {
        $tags = Tag::with(['publishedArticles'])
            ->whereHas('publishedArticles')
            ->orderBy('updated_at', 'desc')
            ->get();

        $urls = [];

        foreach ($tags as $tag) {
            if ($tag->type === 1) {
                // Only Pipopa has tag routes: /blog/ai-chatbot/tag/{slug}
                $url = route('pipopa.blog.tag', ['tag' => $tag->slug]);

                $urls[] = [
                    'loc'        => $url,
                    'lastmod'    => $tag->updated_at->toAtomString(),
                    'changefreq' => 'monthly',
                    'priority'   => '0.4',
                ];
            }
        }

        $xml = $this->generateUrlsetXml($urls);

        return response($xml, 200)
            ->header('Content-Type', 'application/xml');
    }

    /**
     * Generate static pages sitemap XML (renamed from pages to match new naming)
     */
    public function pages(): Response
    {
        $xml = Cache::remember('blog-pages-sitemap', now()->addHours(24), function () {
            $staticPages = [
                ['route' => 'blog', 'priority' => '1.0', 'changefreq' => 'daily'],
                ['route' => 'pipopa.top', 'priority' => '0.9', 'changefreq' => 'daily'],
                ['route' => 'pipopa.blog', 'priority' => '0.9', 'changefreq' => 'daily'],
                ['route' => 'pipopa.features', 'priority' => '0.8', 'changefreq' => 'monthly'],
                ['route' => 'pipopa.pricing', 'priority' => '0.8', 'changefreq' => 'monthly'],
                ['route' => 'pipopa.demo', 'priority' => '0.8', 'changefreq' => 'monthly'],
                ['route' => 'pipopa.company', 'priority' => '0.8', 'changefreq' => 'monthly'],
                ['route' => 'pipopa.contact', 'priority' => '0.8', 'changefreq' => 'monthly'],
                ['route' => 'pipopa.help', 'priority' => '0.8', 'changefreq' => 'monthly'],
                ['route' => 'pipopa.api', 'priority' => '0.8', 'changefreq' => 'monthly'],
                ['route' => 'pipopa.privacy', 'priority' => '0.8', 'changefreq' => 'monthly'],
                ['route' => 'pipopa.terms', 'priority' => '0.8', 'changefreq' => 'monthly'],
                ['route' => 'pipopa.security', 'priority' => '0.8', 'changefreq' => 'monthly'],
                ['route' => 'pipopa.status', 'priority' => '0.8', 'changefreq' => 'monthly'],
                ['route' => 'pipopa.careers', 'priority' => '0.8', 'changefreq' => 'monthly'],
                ['route' => 'pipopa.doc', 'priority' => '0.8', 'changefreq' => 'monthly'],
            ];

            $urls = [];

            foreach ($staticPages as $page) {
                $urls[] = [
                    'loc'        => route($page['route']) . '/',
                    'lastmod'    => '2021-05-12T12:03:04+00:00', // Static date as per your example
                    'changefreq' => $page['changefreq'],
                    'priority'   => $page['priority'],
                ];
            }

            return $this->generateUrlsetXml($urls);
        });

        return response($xml, 200)->header('Content-Type', 'application/xml');
    }

    /**
     * Generate sitemap index XML structure
     */
    private function generateSitemapIndexXml(array $sitemaps): string
    {
        $xml = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
        $xml .= '<?xml-stylesheet type="text/xsl" href="' . asset('sitemap.xsl') . '"?>' . "\n";
        $xml .= '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";

        foreach ($sitemaps as $sitemap) {
            $xml .= "  <sitemap>\n";
            $xml .= '    <loc>' . htmlspecialchars($sitemap['loc']) . "</loc>\n";
            $xml .= '    <lastmod>' . $sitemap['lastmod'] . "</lastmod>\n";
            $xml .= "  </sitemap>\n";
        }

        $xml .= '</sitemapindex>';

        return $xml;
    }

    /**
     * Generate urlset XML structure
     */
    private function generateUrlsetXml(array $urls): string
    {
        $xml = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
        $xml .= '<?xml-stylesheet type="text/xsl" href="' . asset('sitemap.xsl') . '"?>' . "\n";
        $xml .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";

        foreach ($urls as $url) {
            $xml .= "  <url>\n";
            $xml .= '    <loc>' . htmlspecialchars($url['loc']) . "</loc>\n";
            $xml .= '    <lastmod>' . $url['lastmod'] . "</lastmod>\n";
            $xml .= '    <changefreq>' . $url['changefreq'] . "</changefreq>\n";
            $xml .= '    <priority>' . $url['priority'] . "</priority>\n";
            $xml .= "  </url>\n";
        }

        $xml .= '</urlset>';

        return $xml;
    }

    /**
     * Generate urlset XML structure with images
     */
    private function generateUrlsetWithImagesXml(array $urls): string
    {
        $xml = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
        $xml .= '<?xml-stylesheet type="text/xsl" href="' . asset('sitemap.xsl') . '"?>' . "\n";
        $xml .= '<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd http://www.google.com/schemas/sitemap-image/1.1 http://www.google.com/schemas/sitemap-image/1.1/sitemap-image.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";

        foreach ($urls as $url) {
            $xml .= "  <url>\n";
            $xml .= '    <loc>' . htmlspecialchars($url['loc']) . "</loc>\n";
            $xml .= '    <lastmod>' . $url['lastmod'] . "</lastmod>\n";
            $xml .= '    <changefreq>' . $url['changefreq'] . "</changefreq>\n";
            $xml .= '    <priority>' . $url['priority'] . "</priority>\n";

            // Add images if available
            if (! empty($url['images'])) {
                foreach ($url['images'] as $image) {
                    $xml .= "    <image:image>\n";
                    $xml .= '      <image:loc>' . htmlspecialchars($image) . "</image:loc>\n";
                    $xml .= "    </image:image>\n";
                }
            }

            $xml .= "  </url>\n";
        }

        $xml .= '</urlset>';

        return $xml;
    }

    /**
     * Extract image URLs from article content
     */
    private function extractImagesFromContent($content): array
    {
        $images = [];

        if (! $content) {
            return $images;
        }

        // Extract img tags with src attributes
        preg_match_all('/<img[^>]+src=["\']([^"\'>]+)["\'][^>]*>/i', $content, $matches);

        if (! empty($matches[1])) {
            foreach ($matches[1] as $src) {
                // Convert relative URLs to absolute URLs
                if (strpos($src, 'http') !== 0) {
                    // If it's a relative URL, make it absolute
                    if (strpos($src, '/') === 0) {
                        $src = rtrim(config('app.url'), '/') . $src;
                    } else {
                        $src = rtrim(config('app.url'), '/') . '/' . ltrim($src, '/');
                    }
                }

                $images[] = $src;
            }
        }

        // Remove duplicates and limit to reasonable number
        $images = array_unique($images);

        return array_slice($images, 0, 10); // Limit to 10 images per article
    }

    /**
     * Get last modified date for posts
     */
    private function getLastPostModified(): string
    {
        $lastPost = Article::published()
            ->orderBy('updated_at', 'desc')
            ->first();

        return $lastPost ? $lastPost->updated_at->toAtomString() : Carbon::now()->toAtomString();
    }

    /**
     * Get last modified date for categories
     */
    private function getLastCategoryModified(): string
    {
        $lastCategory = Category::orderBy('updated_at', 'desc')->first();

        return $lastCategory ? $lastCategory->updated_at->toAtomString() : Carbon::now()->toAtomString();
    }

    /**
     * Get last modified date for tags
     */
    private function getLastTagModified(): string
    {
        $lastTag = Tag::orderBy('updated_at', 'desc')->first();

        return $lastTag ? $lastTag->updated_at->toAtomString() : Carbon::now()->toAtomString();
    }

    /**
     * Get category parent path
     */
    private function getCategoryParentPath($category): string
    {
        $path = '';

        while ($category->parent) {
            $path = '/' . $category->slug . $path;
            $category = $category->parent;
        }

        return $path;
    }
}
