<?php

namespace Tricks\LaravelSitemapForDynamicPages\Http\Controllers;

use Illuminate\Container\Container;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use ReflectionClass;
use Spatie\Sitemap\Sitemap;
use Spatie\Sitemap\Tags\Url;
use Symfony\Component\HttpFoundation\Response;

class Controller
{
    use ValidatesRequests;

    public function __invoke(Request $request, $extension): Application|Factory|View|JsonResponse|Response
    {
        $sitemap = Sitemap::create();

        $methodName = 'getSitemapPaths';

        $namespace = Container::getInstance()->getNamespace();

        $urls = collect(File::allFiles(app_path()))
            ->map(fn($item) => $item->getRelativePathName())

            // Models/News.php -> App\Models\News
            ->map(fn($className) => Str::of($className)
                ->prepend($namespace)
                ->remove('.php')
                ->replace('/', '\\')
                ->__toString()
            )
            ->filter(fn($className) => Arr::has(config('sitemap-for-dynamic-pages.frontend'), 'paths.'.$className))
            ->filter(fn($className) => class_exists($className))
            ->map(fn($className) => new ReflectionClass($className))
            ->filter(fn($reflection) => $reflection->isSubclassOf(Model::class) && !$reflection->isAbstract())
            ->filter(fn($reflection) => $reflection->hasMethod($methodName))
            ->map(fn($reflection) => $reflection->newInstance())
            ->flatMap(fn($modelInstance) => $modelInstance->all())
            ->map(fn($instance) => $instance->$methodName())
            ->flatten()
            ->sort()
            ->filter() // removes empty string
            ->map(fn($url) => Url::create($url));

        if ($extension === 'json') {
            return response()->json($urls->pluck('url'));
        }

        if ($extension === 'html') {
            return view('laravel-sitemap-for-dynamic-pages::sitemap-links', [
                'urls' => $urls
            ]);
        }

        $urls->map(fn($url) => $url
            ->setChangeFrequency(Url::CHANGE_FREQUENCY_YEARLY)
            ->setPriority(0.1))
            ->each(fn($url) => $sitemap->add($url));

        return $sitemap->toResponse($request);
    }
}
