<?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\ProductIndex;

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

    /**
     * @return array<int,string>
     */
    private static function sanitizeRequestedFields($fields)
    {
        if (!is_array($fields)) {
            return [];
        }

        $allowed = [
            'title',
            'short_description',
            'description',
            'price',
            'sale_price',
            'sku',
            'stock_status',
            'categories',
            'tags',
            'attributes',
            'image_urls',
            'meta_data',
            'variations',
        ];

        $sanitized = [];
        foreach ($fields as $field) {
            $key = sanitize_key((string) $field);
            if (in_array($key, $allowed, true)) {
                $sanitized[] = $key;
            }
        }

        return array_values(array_unique($sanitized));
    }

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

        try {
            $fields = static::sanitizeRequestedFields($request->get_param('fields'));

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

            $result = $this->indexingService()->startJob(new ProductIndex([
                'fields' => $fields,
                'chunk_size' => $chunkSize,
            ]));
            return $this->mapProductStartResponse($result);
        } catch (\Exception $e) {
            return [
                'success' => false,
                'message' => 'Failed to start product index build job',
                'error' => $e->getMessage(),
                'status' => 500
            ];
        }
    }

    public function processProductBuildJob(\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 ProductIndex(), $jobId);
            return $this->mapProductProcessResponse($result);
        } catch (\Exception $e) {
            return [
                'success' => false,
                'message' => 'Failed to process product index build job',
                'error' => $e->getMessage(),
                'status' => 500
            ];
        }
    }

    public function getProductBuildJobStatus(\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 ProductIndex(), $jobId);
            return $this->mapProductStatusResponse($result);
        } catch (\Exception $e) {
            return [
                'success' => false,
                'message' => 'Failed to get product index build job status',
                'error' => $e->getMessage(),
                'status' => 500
            ];
        }
    }

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

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

    public function getProductIndexStatus(\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 ProductIndex())
            ];
        } catch (\Exception $e) {
            return [
                'success' => false,
                'message' => 'Failed to get product index status',
                'error' => $e->getMessage(),
                'status' => 500
            ];
        }
    }

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

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

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

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

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

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

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

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