<?php

namespace ZenoChatbot\Http\Controller\Api\V1;

use ZenoChatbot\Helper\Resources;
use ZenoChatbot\Helper\Security;
use ZenoChatbot\Services\Indexing\ContentIndexService;
use ZenoChatbot\Services\Indexing\Strategies\SiteMapIndex;

class SitemapContentIndexController
{
    private function indexingService(): ContentIndexService
    {
        return ContentIndexService::create(Resources::getBaseDirPath());
    }

    /**
     * @param mixed $path
     * @return string
     */
    private static function sanitizeManualPath($path)
    {
        $path = wp_unslash((string) $path);
        $path = wp_check_invalid_utf8($path);
        $path = str_replace("\0", '', $path);
        $path = trim($path);
        if ($path === '') {
            return '';
        }

        $path = preg_replace('/[^A-Za-z0-9\-._~\/?&=%#+]/', '', $path) ?? '';
        return sanitize_text_field($path);
    }

    public function buildSitemapIndex(\WP_REST_Request $request)
    {
        if (!Security::currentUserCan('manage_options')) {
            return [
                'success' => false,
                'message' => 'Insufficient permissions',
                'status' => 403
            ];
        }

        try {
            $chunkSize = (int) $request->get_param('chunk_size');
            if ($chunkSize <= 0) {
                $chunkSize = 50;
            }

            $result = $this->indexingService()->index(new SiteMapIndex([
                'chunk_size' => $chunkSize,
            ]));

            return $this->mapSitemapBuildResponse($result);
        } catch (\Exception $e) {
            return [
                'success' => false,
                'message' => 'Failed to build sitemap index',
                'error' => $e->getMessage(),
                'status' => 500
            ];
        }
    }

    public function clearSitemapIndex(\WP_REST_Request $request)
    {
        if (!Security::currentUserCan('manage_options')) {
            return [
                'success' => false,
                'message' => 'Insufficient permissions',
                'status' => 403
            ];
        }

        try {
            $result = $this->indexingService()->clear(new SiteMapIndex());
            return $this->mapSitemapClearResponse($result);
        } catch (\Exception $e) {
            return [
                'success' => false,
                'message' => 'Failed to clear sitemap index',
                'error' => $e->getMessage(),
                'status' => 500
            ];
        }
    }

    public function getSitemapIndexStatus(\WP_REST_Request $request)
    {
        if (!Security::currentUserCan('manage_options')) {
            return [
                'success' => false,
                'message' => 'Insufficient permissions',
                'status' => 403
            ];
        }

        try {
            $chunkSize = (int) $request->get_param('chunk_size');
            if ($chunkSize <= 0) {
                $chunkSize = 50;
            }

            $this->indexingService()->sync(new SiteMapIndex([
                'chunk_size' => $chunkSize,
            ]));

            return [
                'success' => true,
                'data' => $this->indexingService()->stats(new SiteMapIndex())
            ];
        } catch (\Exception $e) {
            return [
                'success' => false,
                'message' => 'Failed to get sitemap index status',
                'error' => $e->getMessage(),
                'status' => 500
            ];
        }
    }

    public function startSitemapBuildJob(\WP_REST_Request $request)
    {
        if (!Security::currentUserCan('manage_options')) {
            return [
                'success' => false,
                'message' => 'Insufficient permissions',
                'status' => 403
            ];
        }

        try {
            $mode = sanitize_key((string) $request->get_param('mode'));
            if (!in_array($mode, ['auto', 'manual'], true)) {
                $mode = 'auto';
            }

            $manualPath = static::sanitizeManualPath($request->get_param('manual_path'));
            $chunkSize = (int) $request->get_param('chunk_size');
            if ($chunkSize <= 0) {
                $chunkSize = 50;
            }

            $result = $this->indexingService()->startJob(new SiteMapIndex([
                'mode' => $mode,
                'manual_path' => $manualPath,
                'chunk_size' => $chunkSize,
            ]));

            return $this->mapSitemapStartResponse($result);
        } catch (\Exception $e) {
            return [
                'success' => false,
                'message' => 'Failed to start sitemap build job',
                'error' => $e->getMessage(),
                'status' => 500
            ];
        }
    }

    public function processSitemapBuildJob(\WP_REST_Request $request)
    {
        if (!Security::currentUserCan('manage_options')) {
            return [
                'success' => false,
                'message' => 'Insufficient permissions',
                'status' => 403
            ];
        }

        try {
            $jobId = sanitize_text_field((string) $request->get_param('job_id'));
            if ($jobId === '') {
                return [
                    'success' => false,
                    'message' => 'Job id is required',
                    'status' => 400
                ];
            }

            $result = $this->indexingService()->processJob(new SiteMapIndex(), $jobId);
            return $this->mapSitemapProcessResponse($result);
        } catch (\Exception $e) {
            return [
                'success' => false,
                'message' => 'Failed to process sitemap build job',
                'error' => $e->getMessage(),
                'status' => 500
            ];
        }
    }

    public function getSitemapBuildJobStatus(\WP_REST_Request $request)
    {
        if (!Security::currentUserCan('manage_options')) {
            return [
                'success' => false,
                'message' => 'Insufficient permissions',
                'status' => 403
            ];
        }

        try {
            $jobId = sanitize_text_field((string) $request->get_param('job_id'));
            if ($jobId === '') {
                return [
                    'success' => false,
                    'message' => 'Job id is required',
                    'status' => 400
                ];
            }

            $result = $this->indexingService()->jobStatus(new SiteMapIndex(), $jobId);
            return $this->mapSitemapStatusResponse($result);
        } catch (\Exception $e) {
            return [
                'success' => false,
                'message' => 'Failed to get sitemap build job status',
                'error' => $e->getMessage(),
                'status' => 500
            ];
        }
    }

    /** @param array<string,mixed> $serviceResult */
    private function mapSitemapBuildResponse(array $serviceResult): array
    {
        if (!($serviceResult['success'] ?? false)) {
            return [
                'success' => false,
                'message' => (string) ($serviceResult['message'] ?? 'Failed to build sitemap index'),
                'status' => 400
            ];
        }

        return [
            'success' => true,
            'message' => (string) ($serviceResult['message'] ?? 'Sitemap indexed successfully.'),
            'data' => $serviceResult['data'] ?? []
        ];
    }

    /** @param array<string,mixed> $serviceResult */
    private function mapSitemapClearResponse(array $serviceResult): array
    {
        if (!($serviceResult['success'] ?? false)) {
            return [
                'success' => false,
                'message' => (string) ($serviceResult['message'] ?? 'Failed to clear sitemap index'),
                'status' => 500
            ];
        }

        return [
            'success' => true,
            'message' => (string) ($serviceResult['message'] ?? 'Sitemap index cleared successfully.'),
            'data' => $serviceResult['data'] ?? []
        ];
    }

    /** @param array<string,mixed> $serviceResult */
    private function mapSitemapStartResponse(array $serviceResult): array
    {
        if (!($serviceResult['success'] ?? false)) {
            return [
                'success' => false,
                'message' => (string) ($serviceResult['message'] ?? 'Failed to start sitemap build job'),
                'status' => 400
            ];
        }

        return [
            'success' => true,
            'data' => $serviceResult['data'] ?? []
        ];
    }

    /** @param array<string,mixed> $serviceResult */
    private function mapSitemapProcessResponse(array $serviceResult): array
    {
        if (!($serviceResult['success'] ?? false)) {
            return [
                'success' => false,
                'message' => (string) ($serviceResult['message'] ?? 'Failed to process sitemap build job'),
                'data' => $serviceResult['data'] ?? null,
                'status' => 400
            ];
        }

        return [
            'success' => true,
            'data' => $serviceResult['data'] ?? []
        ];
    }

    /** @param array<string,mixed> $serviceResult */
    private function mapSitemapStatusResponse(array $serviceResult): array
    {
        if (!($serviceResult['success'] ?? false)) {
            return [
                'success' => false,
                'message' => (string) ($serviceResult['message'] ?? 'Sitemap build job not found.'),
                'status' => 404
            ];
        }

        return [
            'success' => true,
            'data' => $serviceResult['data'] ?? []
        ];
    }
}
