<?php

namespace OtomaticAi\Controllers;

use Exception;
use OtomaticAi\Api\OtomaticAi\Client;
use OtomaticAi\Api\OtomaticAi\Exceptions\UnauthorizedException;
use OtomaticAi\Api\OtomaticAi\Exceptions\ValidationException;
use OtomaticAi\Utils\Auth;
use OtomaticAi\Utils\Settings;

class AuthController extends Controller
{
    /**
     * Login the user
     *
     * @return void
     */
    public function login()
    {
        $this->verifyNonce();

        $this->validate([
            "email" => ["required", "email"],
            "password" => ["required", "string"],
        ]);

        try {
            Auth::login($this->input("email"), $this->input("password"));
            $this->emptyResponse();
        } catch (ValidationException $e) {
            $this->response(["message" => $e->getMessage(), "errors" => $e->getErrors()], 422);
        } catch (Exception $e) {
            $this->response(["message" => "An error occurred", "error" => $e->getMessage()], 503);
        }
    }

    /**
     * Logout the user
     *
     * @return void
     */
    public function logout()
    {
        $this->verifyNonce();

        try {
            Auth::logout();
            $this->emptyResponse();
        } catch (Exception $e) {
            $this->response(["message" => "An error occurred", "error" => $e->getMessage()], 503);
        }
    }

    public function oauthAuthorize()
    {
        $this->verifyNonce();

        $this->response([
            "url" => Auth::buildAuthorizeUrl()
        ]);
    }

    public function oauthComplete()
    {
        $this->verifyNonce();

        $state = $this->input("state");
        $code = $this->input("code");

        $pkce = get_transient("otomatic_pkce_$state");
        if (!$pkce || empty($pkce['code_verifier'])) {
            $this->response(["message" => "An error occurred", "error" => "Expired or invalid"], 503);
        }
        delete_transient("otomatic_pkce_$state");

        $client_id    = defined('OTOMATIC_AI_OAUTH_CLIENT_ID') ? OTOMATIC_AI_OAUTH_CLIENT_ID : '';
        $saas_base    = rtrim(defined('OTOMATIC_AI_SAAS_URL') ? OTOMATIC_AI_SAAS_URL : '', '/');
        $redirect_uri = $saas_base . '/oauth/redirect';   // doit matcher EXACTEMENT le client

        $resp = wp_remote_post($saas_base . '/oauth/token', [
            'timeout' => 20,
            'headers' => ['Accept' => 'application/json'],
            'body'    => [
                'grant_type'    => 'authorization_code',
                'client_id'     => $client_id,
                'redirect_uri'  => $redirect_uri,
                'code_verifier' => $pkce['code_verifier'],
                'code'          => $code,
            ],
        ]);

        if (is_wp_error($resp)) {
            $this->response(["message" => "An error occurred", "error" => $resp->get_error_message()], 503);
        }

        $http = wp_remote_retrieve_response_code($resp);
        $body = json_decode(wp_remote_retrieve_body($resp), true) ?: [];

        if ($http !== 200 || empty($body['access_token'])) {
            // Mapping d’erreurs utile pour debug UI
            $err = $body['error'] ?? 'oauth_error';
            $desc = $body['error_description'] ?? 'Invalid token response';
            // Messages fréquents
            if ($err === 'invalid_grant') {
                if (stripos($desc, 'code_verifier') !== false) $desc = 'PKCE code_verifier invalide (mismatch).';
                if (stripos($desc, 'redirect_uri') !== false)  $desc = 'redirect_uri ne correspond pas au client.';
                if (stripos($desc, 'authorization code') !== false) $desc = 'Authorization code expiré ou déjà utilisé.';
            }
            return new \WP_Error($err, $desc, ['status' => 400]);
        }

        // login with the access token
        try {
            Auth::loginWithAccessToken($body['access_token']);
        } catch (Exception $e) {
            $this->response(["message" => "An error occurred", "error" => $e->getMessage()], 503);
        }

        $this->emptyResponse();
    }

    /**
     * Get the authenticated domain
     *
     * @return void
     */
    public function domain()
    {
        $this->verifyNonce();

        try {
            $this->response(Auth::domain());
        } catch (UnauthorizedException $e) {
            $this->emptyResponse();
        } catch (Exception $e) {
            $this->response(["message" => "An error occurred", "error" => $e->getMessage()], 503);
        }
    }

    /**
     * Get the authenticated user
     *
     * @return void
     */
    public function user()
    {
        $this->verifyNonce();

        try {
            $this->response(Auth::user());
        } catch (UnauthorizedException $e) {
            $this->emptyResponse();
        } catch (Exception $e) {
            $this->response(["message" => "An error occurred", "error" => $e->getMessage()], 503);
        }
    }

    /**
     * Get the required settings statuses
     *
     * @return void
     */
    public function requiredSettings()
    {
        $this->verifyNonce();

        $this->response([
            "openai" => !empty(Settings::get('api.openai.api_key')),
        ]);
    }

    /**
     * Set the domain to premium
     *
     * @return void
     */
    public function enablePremium()
    {
        $this->verifyNonce();

        try {
            $api = new Client;
            $response = $api->enablePremium();
            // Auth::refreshDomain();
            $this->response($response);
        } catch (UnauthorizedException $e) {
            $this->emptyResponse();
        } catch (Exception $e) {
            $this->response(["message" => "An error occurred", "error" => $e->getMessage()], 503);
        }
    }

    /**
     * Set the domain to free
     *
     * @return void
     */
    public function disablePremium()
    {
        $this->verifyNonce();

        try {
            $api = new Client;
            $response = $api->disablePremium();
            // Auth::refreshDomain();
            $this->response($response);
        } catch (UnauthorizedException $e) {
            $this->emptyResponse();
        } catch (Exception $e) {
            $this->response(["message" => "An error occurred", "error" => $e->getMessage()], 503);
        }
    }
}
