<?php
/**
 * AI Chat Controller
 *
 * Handles AI chat endpoints.
 * Uses AIProviderManager to route requests to active provider.
 *
 * @package FleekDash\Controllers\AI
 * @since 2.3.0
 */

namespace FleekDash\Controllers\AI;

use FleekDash\AI\Core\AIProviderManager;
use FleekDash\Core\AuthMiddleware;

defined('ABSPATH') || exit;

/**
 * Class AIChatController
 *
 * Handles AI chat requests.
 */
class AIChatController
{
    private const MSG_AUTHENTICATION_REQUIRED = 'Authentication is required.';

    private const MSG_PROVIDER_ID_REQUIRED = 'Provider ID is required.';

    /**
     * Handle chat request
     *
     * @param \WP_REST_Request $request Request object
     * @return \WP_REST_Response|\WP_Error Response
     */
    public function chat($request)
    {
        $response = null;
        try {
            $service = new AIChatConversationService(function (array $data, int $status = 200) {
                return $this->respond($data, $status);
            });
            $response = $service->run($request);
        } catch (\Exception $e) {
            $response = $this->respond([
                'success' => false,
                'message' => $e->getMessage(),
            ], 500);
        }

        return $response;
    }

    /**
     * Get available providers
     *
     * @param \WP_REST_Request $request Request object
     * @return \WP_REST_Response Response
     */
    public function getProviders($request)
    {
        \assert($request instanceof \WP_REST_Request);
        $response = null;
        try {
            $gate = $this->respondIfUnauthenticated();
            if ($gate !== null) {
                $response = $gate;
            } else {
                $providerManager = AIProviderManager::getInstance();
                $response = \rest_ensure_response([
                    'success' => true,
                    'providers' => $providerManager->getAllProvidersData(),
                    'active_provider_id' => $providerManager->getActiveProviderId(),
                ]);
            }
        } catch (\Exception $e) {
            $response = $this->respond([
                'success' => false,
                'message' => $e->getMessage(),
            ], 500);
        }

        return $response;
    }

    /**
     * Get active provider
     *
     * @param \WP_REST_Request $request Request object
     * @return \WP_REST_Response Response
     */
    public function getActiveProvider($request)
    {
        \assert($request instanceof \WP_REST_Request);
        $response = null;
        try {
            $gate = $this->respondIfUnauthenticated();
            if ($gate !== null) {
                $response = $gate;
            } else {
                $providerManager = AIProviderManager::getInstance();
                $provider = $providerManager->getActiveProvider();
                if (!$provider) {
                    $response = \rest_ensure_response([
                        'success' => true,
                        'provider' => null,
                    ]);
                } else {
                    $response = \rest_ensure_response([
                        'success' => true,
                        'provider' => [
                            'id' => $provider->getId(),
                            'name' => $provider->getName(),
                            'icon' => $provider->getIcon(),
                            'description' => $provider->getDescription(),
                            'is_configured' => $provider->isConfigured(),
                            'models' => $provider->getModels(),
                        ],
                    ]);
                }
            }
        } catch (\Exception $e) {
            $response = $this->respond([
                'success' => false,
                'message' => $e->getMessage(),
            ], 500);
        }

        return $response;
    }

    /**
     * Get provider settings
     *
     * @param \WP_REST_Request $request Request object
     * @return \WP_REST_Response Response
     */
    public function getProviderSettings($request)
    {
        $response = null;
        try {
            $gate = $this->respondIfUnauthenticated();
            if ($gate !== null) {
                $response = $gate;
            } else {
                $provider_id = $request->get_param('id');
                if (empty($provider_id)) {
                    $response = $this->respond([
                        'success' => false,
                        'message' => self::MSG_PROVIDER_ID_REQUIRED,
                    ], 400);
                } else {
                    $manager = AIProviderManager::getInstance();
                    $provider = $manager->getProvider($provider_id);
                    if (!$provider) {
                        $response = $this->respond([
                            'success' => false,
                            'message' => 'Provider not found.',
                        ], 404);
                    } else {
                        $settings = $provider->getSettings();
                        if (isset($settings['api_key']) && !empty($settings['api_key'])) {
                            $settings['api_key'] = '***configured***';
                        }
                        $response = $this->respond([
                            'success' => true,
                            'settings' => $settings,
                            'provider' => [
                                'id' => $provider->getId(),
                                'name' => $provider->getName(),
                                'is_configured' => $provider->isConfigured(),
                            ],
                        ]);
                    }
                }
            }
        } catch (\Exception $e) {
            $response = $this->respond([
                'success' => false,
                'message' => 'Error getting settings: ' . $e->getMessage(),
            ], 500);
        }

        return $response;
    }

    /**
     * Update provider settings
     *
     * @param \WP_REST_Request $request Request object
     * @return \WP_REST_Response Response
     */
    public function updateProviderSettings($request)
    {
        $response = null;
        try {
            $gate = $this->respondIfUnauthenticated();
            if ($gate !== null) {
                $response = $gate;
            } else {
                $response = $this->updateProviderSettingsCore($request);
            }
        } catch (\Exception $e) {
            $response = $this->respond([
                'success' => false,
                'message' => 'Error updating settings: ' . $e->getMessage(),
            ], 500);
        }

        return $response;
    }

    /**
     * @return array<string, mixed>
     */
    private function extractProviderSettingsPayload(\WP_REST_Request $request): array
    {
        $json_params = $request->get_json_params();
        $body_params = $request->get_body_params();
        $raw = $json_params ?? $body_params ?? [];

        if (!\is_array($raw)) {
            return [];
        }

        if (isset($raw['settings']) && \is_array($raw['settings'])) {
            return $raw['settings'];
        }

        return $raw;
    }

    /**
     * @param array<string, mixed> $settings
     * @return array<string, mixed>
     */
    private function sanitizeProviderSettingsForSave(array $settings): array
    {
        if (isset($settings['api_key']) && $settings['api_key'] === '***configured***') {
            unset($settings['api_key']);
        }

        return $settings;
    }

    private function updateProviderSettingsCore(\WP_REST_Request $request): \WP_REST_Response
    {
        $provider_id = $request->get_param('id');
        $manager = AIProviderManager::getInstance();
        $provider = empty($provider_id) ? null : $manager->getProvider($provider_id);
        $settings = $this->sanitizeProviderSettingsForSave($this->extractProviderSettingsPayload($request));

        $out = null;
        if (empty($provider_id)) {
            $out = $this->respond([
                'success' => false,
                'message' => self::MSG_PROVIDER_ID_REQUIRED,
            ], 400);
        } elseif ($provider === null) {
            $out = $this->respond([
                'success' => false,
                'message' => 'Provider not found.',
            ], 404);
        } elseif (empty($settings)) {
            $out = $this->respond([
                'success' => false,
                'message' => 'Settings data is required.',
            ], 400);
        } elseif (!$provider->updateSettings($settings)) {
            $out = $this->respond([
                'success' => false,
                'message' => 'Failed to update settings.',
            ], 500);
        } else {
            $out = $this->respond([
                'success' => true,
                'message' => 'Settings updated successfully.',
                'provider' => [
                    'id' => $provider->getId(),
                    'name' => $provider->getName(),
                    'is_configured' => $provider->isConfigured(),
                ],
            ]);
        }

        return $out;
    }

    /**
     * Activate a provider
     *
     * @param \WP_REST_Request $request Request object
     * @return \WP_REST_Response Response
     */
    public function activateProvider($request)
    {
        $response = null;
        try {
            $gate = $this->respondIfUnauthenticated();
            if ($gate !== null) {
                $response = $gate;
            } else {
                $provider_id = $request->get_param('id');
                if (empty($provider_id)) {
                    $response = $this->respond([
                        'success' => false,
                        'message' => self::MSG_PROVIDER_ID_REQUIRED,
                    ], 400);
                } else {
                    $manager = AIProviderManager::getInstance();
                    $success = $manager->setActiveProvider($provider_id);
                    if (!$success) {
                        $response = $this->respond([
                            'success' => false,
                            'message' => 'Provider not found or could not be activated.',
                        ], 404);
                    } else {
                        $provider = $manager->getProvider($provider_id);
                        $response = $this->respond([
                            'success' => true,
                            'message' => 'Provider activated successfully.',
                            'provider' => [
                                'id' => $provider->getId(),
                                'name' => $provider->getName(),
                                'icon' => $provider->getIcon(),
                                'description' => $provider->getDescription(),
                                'is_configured' => $provider->isConfigured(),
                                'is_active' => true,
                            ],
                        ]);
                    }
                }
            }
        } catch (\Exception $e) {
            $response = $this->respond([
                'success' => false,
                'message' => 'Error activating provider: ' . $e->getMessage(),
            ], 500);
        }

        return $response;
    }

    /**
     * Deactivate a provider
     *
     * @param \WP_REST_Request $request Request object
     * @return \WP_REST_Response Response
     */
    public function deactivateProvider($request)
    {
        $response = null;
        try {
            $gate = $this->respondIfUnauthenticated();
            if ($gate !== null) {
                $response = $gate;
            } else {
                $provider_id = $request->get_param('id');
                if (empty($provider_id)) {
                    $response = $this->respond([
                        'success' => false,
                        'message' => self::MSG_PROVIDER_ID_REQUIRED,
                    ], 400);
                } else {
                    $manager = AIProviderManager::getInstance();
                    $activeProviderId = $manager->getActiveProviderId();

                    if (!empty($activeProviderId) && $activeProviderId !== $provider_id) {
                        $response = $this->respond([
                            'success' => false,
                            'message' => 'This provider is not currently active.',
                        ], 400);
                    } elseif (empty($activeProviderId)) {
                        $response = $this->respond([
                            'success' => true,
                            'message' => 'Provider is already deactivated.',
                            'provider' => null,
                        ]);
                    } else {
                        $manager->clearActiveProvider();
                        $response = $this->respond([
                            'success' => true,
                            'message' => 'Provider deactivated successfully.',
                            'provider' => null,
                        ]);
                    }
                }
            }
        } catch (\Exception $e) {
            $response = $this->respond([
                'success' => false,
                'message' => 'Error deactivating provider: ' . $e->getMessage(),
            ], 500);
        }

        return $response;
    }

    /**
     * Helper to build WP_REST_Response with status code.
     *
     * @param array $data
     * @param int $status
     * @return \WP_REST_Response
     */
    private function respond(array $data, int $status = 200)
    {
        $response = \rest_ensure_response($data);
        $response->set_status($status);

        return $response;
    }

    private function respondIfUnauthenticated(): ?\WP_REST_Response
    {
        $auth_check = AuthMiddleware::check('authenticated');
        if (!$auth_check['authenticated']) {
            return $this->respond([
                'success' => false,
                'message' => self::MSG_AUTHENTICATION_REQUIRED,
            ], 401);
        }

        return null;
    }
}
