<?php

namespace BexioConnectorByHelvy;

/**
 * Admin API Auth
 *
 * @since 0.1.0
 */

defined('ABSPATH') || exit;

class AdminAPIAuth
{

    public function __construct()
    {

        add_action('rest_api_init', function () {
            // Auth
            register_rest_route(BEXIO_CONNECTOR_BY_HELVY_REST_API_ROUTE, '/auth/register/', array(
                'methods' => 'POST',
                'callback' => array($this, 'register_customer'),
                'permission_callback' => array($this, 'get_permission')
            ));
            register_rest_route(BEXIO_CONNECTOR_BY_HELVY_REST_API_ROUTE, '/auth/bexio/', array(
                'methods' => 'GET',
                'callback' => array($this, 'connect_to_bexio'),
                'permission_callback' => array($this, 'get_permission')
            ));
            register_rest_route(BEXIO_CONNECTOR_BY_HELVY_REST_API_ROUTE, '/auth/check-api-connection/', array(
                'methods' => 'GET',
                'callback' => array($this, 'check_api_connection'),
                'permission_callback' => array($this, 'get_permission')
            ));
            register_rest_route(BEXIO_CONNECTOR_BY_HELVY_REST_API_ROUTE, '/auth/re-register/', array(
                'methods' => 'POST',
                'callback' => array($this, 're_register_customer'),
                'permission_callback' => array($this, 'get_permission')
            ));
            register_rest_route(BEXIO_CONNECTOR_BY_HELVY_REST_API_ROUTE, '/health/connection/', array(
                'methods' => 'GET',
                'callback' => array($this, 'connection_health'),
                'permission_callback' => array($this, 'get_permission')
            ));
        });
    }

    public function register_customer($data)
    {
        $siteDomain = Utils::extract_domain(get_site_url());
        $body = $data->get_params();
        $customerData = [
            "hostname" => $siteDomain,
            "adminUrl" => get_admin_url(),
            "address" => $body["address"],
            "city" =>  $body["city"],
            "company" =>  $body["company"],
            "country" =>  $body["country"],
            "email" =>  $body["email"],
            "name" =>  $body["name"],
            "vatNumber" =>  $body["vatNumber"],
            "zip" =>  $body["zip"],
        ];
        $apiRes = API::instance()->register_customer($customerData);

        if ($apiRes instanceof \WP_Error) {
            return new \WP_REST_Response($apiRes, 500);
        }

        update_option( 'bexio_connector_by_helvy_api_access_token', sanitize_text_field( $apiRes["tokens"]["access"]["token"] ) );
        update_option( 'bexio_connector_by_helvy_api_refresh_token', sanitize_text_field( $apiRes["tokens"]["refresh"]["token"] ) );
        update_option( 'bexio_connector_by_helvy_api_hash', sanitize_text_field( $apiRes["user"]["newPassword"] ) );
        
        return new \WP_REST_Response($apiRes, 200);
    }

    public function connect_to_bexio()
    {
        $apiRes = API::instance()->connect_to_bexio();
        if ($apiRes instanceof \WP_Error) {
            return new \WP_REST_Response($apiRes, 500);
        }

        return new \WP_REST_Response($apiRes, 200);
    }

    /**
     * Check if the API connection is working.
     * Returns the connection status: "connected", "api_account_missing", or "error".
     */
    public function check_api_connection()
    {
        $has_api_tokens = !empty(get_option('bexio_connector_by_helvy_api_access_token'));
        if (!$has_api_tokens) {
            return new \WP_REST_Response(["status" => "api_account_missing"], 200);
        }

        // Try a lightweight API call (connect_to_bexio requires auth)
        $apiRes = API::instance()->connect_to_bexio();
        if ($apiRes instanceof \WP_Error) {
            $error_data = $apiRes->get_error_data();
            // Check if the error is an auth failure (401 = account missing or credentials invalid)
            if (isset($error_data['status_code']) && $error_data['status_code'] === 401) {
                return new \WP_REST_Response(["status" => "api_account_missing"], 200);
            }
            // Other errors might mean bexio token is expired but API account exists
            return new \WP_REST_Response(["status" => "connected"], 200);
        }

        return new \WP_REST_Response(["status" => "connected"], 200);
    }

    /**
     * Connection health for the admin UI (single source of truth): broker / bexio / billing.
     * Proxies the broker's GET /v1/health/connection and degrades gracefully so the UI never
     * shows a false "reconnect" alarm — e.g. when an older broker has no health endpoint (404),
     * or on a transient error.
     */
    public function connection_health()
    {
        $has_api_tokens = !empty(get_option('bexio_connector_by_helvy_api_access_token'));
        if (!$has_api_tokens) {
            return new \WP_REST_Response(array(
                "broker"  => array("authenticated" => false),
                "bexio"   => array("connected" => false, "needsReconnect" => false),
                "billing" => array("status" => "unknown"),
                "degraded" => true,
            ), 200);
        }

        $apiRes = API::instance()->get_connection_health();
        if ($apiRes instanceof \WP_Error) {
            $error_data = $apiRes->get_error_data();
            $status_code = isset($error_data['status_code']) ? (int) $error_data['status_code'] : null;
            // 401 => broker auth is broken; anything else (404 old broker, 5xx, network) => unknown,
            // but never assert needsReconnect from a failed probe.
            $broker_ok = $status_code !== 401;
            return new \WP_REST_Response(array(
                "broker"  => array("authenticated" => $broker_ok),
                "bexio"   => array("connected" => $broker_ok, "needsReconnect" => false),
                "billing" => array("status" => "unknown"),
                "degraded" => true,
            ), 200);
        }

        return new \WP_REST_Response($apiRes, 200);
    }

    /**
     * Re-register the customer with the API.
     * Uses WooCommerce admin user info so the user doesn't need to fill a form again.
     */
    public function re_register_customer()
    {
        $siteDomain = Utils::extract_domain(get_site_url());
        $admin_email = get_option('admin_email');
        $admin_user = get_user_by('email', $admin_email);
        $first_name = $admin_user ? get_user_meta($admin_user->ID, 'first_name', true) : "";
        $last_name = $admin_user ? get_user_meta($admin_user->ID, 'last_name', true) : "";

        $store_address = get_option('woocommerce_store_address', '');
        $store_city = get_option('woocommerce_store_city', '');
        $store_postcode = get_option('woocommerce_store_postcode', '');
        $store_country_state = get_option('woocommerce_default_country', 'CH');
        $store_country = explode(':', $store_country_state)[0];

        $customerData = [
            "hostname" => $siteDomain,
            "adminUrl" => get_admin_url(),
            "address" => $store_address ?: "N/A",
            "city" => $store_city ?: "N/A",
            "company" => get_bloginfo('name') ?: "",
            "country" => $store_country,
            "email" => $admin_email,
            "name" => trim("$first_name $last_name") ?: $admin_email,
            "vatNumber" => "",
            "zip" => $store_postcode ?: "0000",
        ];
        $apiRes = API::instance()->recover_customer($customerData);

        if ($apiRes instanceof \WP_Error) {
            return new \WP_REST_Response([
                "success" => false,
                "error" => $apiRes->get_error_message(),
                "error_data" => $apiRes->get_error_data(),
            ], 500);
        }

        update_option('bexio_connector_by_helvy_api_access_token', sanitize_text_field($apiRes["tokens"]["access"]["token"]));
        update_option('bexio_connector_by_helvy_api_refresh_token', sanitize_text_field($apiRes["tokens"]["refresh"]["token"]));
        update_option('bexio_connector_by_helvy_api_hash', sanitize_text_field($apiRes["user"]["newPassword"]));

        return new \WP_REST_Response(["success" => true], 200);
    }

    /**
     * Permission Callback
     **/
    public function get_permission()
    {
        if (current_user_can('administrator') || current_user_can('manage_woocommerce')) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Cloning is forbidden.
     *
     * @since 1.0.0
     */
    public function __clone()
    {
        _doing_it_wrong(__FUNCTION__, __('Cheatin&#8217; huh?'), BEXIO_CONNECTOR_BY_HELVY_VERSION);
    }
}
