<?php

namespace ZenoChatbot\Http\Controller\Api\V1;

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

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

    /**
     * Get combined internal content overview for admin tab.
     *
     * @param \WP_REST_Request $request
     * @return array
     */
    public function getOverview(\WP_REST_Request $request)
    {
        if (!Security::currentUserCan('manage_options')) {
            return [
                'success' => false,
                'message' => 'Insufficient permissions',
                'status' => 403
            ];
        }

        try {
            $selectedPostTypes = Settings::get('internal_content.selected_post_types', ['post', 'page']);
            if (!is_array($selectedPostTypes)) {
                $selectedPostTypes = ['post', 'page'];
            }

            $selectedPostTypes = array_values(array_unique(array_filter(array_map('sanitize_key', $selectedPostTypes))));

            $postTypes = [];
            $publicPostTypes = get_post_types(['public' => true], 'objects');
            foreach ($publicPostTypes as $postType) {
                $name = sanitize_key((string) ($postType->name ?? ''));
                if ($name === '' || $name === 'attachment') {
                    continue;
                }

                $count = wp_count_posts($name);
                $publishedCount = isset($count->publish) ? (int) $count->publish : 0;

                $postTypes[] = [
                    'name' => $name,
                    'label' => sanitize_text_field((string) ($postType->labels->name ?? $name)),
                    'count' => $publishedCount,
                    'description' => sanitize_text_field((string) (($postType->description ?? '') ?: ($postType->labels->name ?? $name)))
                ];
            }

            $service = $this->indexingService();

            return [
                'success' => true,
                'data' => [
                    'internal' => $service->stats(new InternalContentIndex()),
                    'sitemap' => $service->stats(new SiteMapIndex()),
                    'product' => $service->stats(new ProductIndex()),
                    'settings' => [
                        'selected_post_types' => $selectedPostTypes,
                    ],
                    'post_types' => $postTypes,
                ]
            ];
        } catch (\Exception $e) {
            return [
                'success' => false,
                'message' => 'Failed to get internal content overview',
                'error' => $e->getMessage(),
                'status' => 500
            ];
        }
    }

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

        try {
            $selected_post_types = $request->get_param('selected_post_types');

            if (!is_array($selected_post_types) || empty($selected_post_types)) {
                return [
                    'success' => false,
                    'message' => 'No post types selected for indexing',
                    'status' => 400
                ];
            }

            $selected_post_types = array_values(array_unique(array_filter(array_map('sanitize_key', $selected_post_types))));
            $available_post_types = get_post_types(['public' => true]);
            $valid_post_types = [];
            foreach ($selected_post_types as $post_type) {
                if ($post_type === 'attachment') {
                    continue;
                }

                if (isset($available_post_types[$post_type])) {
                    $valid_post_types[] = $post_type;
                }
            }

            if (empty($valid_post_types)) {
                return [
                    'success' => false,
                    'message' => 'No valid post types selected for indexing',
                    'status' => 400
                ];
            }

            $result = $this->indexingService()->index(new InternalContentIndex($valid_post_types));
            return $this->mapInternalBuildResponse($result);

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

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

        try {
            $result = $this->indexingService()->clear(new InternalContentIndex());
            return $this->mapInternalClearResponse($result);

        } catch (\Exception $e) {
            return [
                'success' => false,
                'message' => 'Failed to clear internal content index',
                'error' => $e->getMessage(),
                'status' => 500
            ];
        }
    }

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

        try {
            return [
                'success' => true,
                'data' => $this->indexingService()->stats(new InternalContentIndex())
            ];

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

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

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

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

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