<?php
/**
 * Dakidarts Numerology Core - API Wrapper
 *
 * Handles all communication with the Numerology API via RapidAPI or the NumerologyAPI Gateway.
 *
 * @package Dakidarts_Numerology_Core
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class Dakidarts_API {

    private static $rapidapi_base = 'https://the-numerology-api.p.rapidapi.com';
    private static $gateway_base  = 'https://api.numerologyapi.com/api/v1';

    private static $endpoints = [
    'life-path' => [
        'path' => '/life_path/post',
        'params' => [ 'birth_year', 'birth_month', 'birth_day' ],
        'param_desc' => [
            'birth_year'  => 'Year of Birth (YYYY)',
            'birth_month' => 'Month of Birth (01-12)',
            'birth_day'   => 'Day of Birth (01-31)'
        ],
        'label' => 'Life Path'
    ],
    'sun-number' => [
        'path' => '/attitude_number/post',
        'params' => [ 'birth_day', 'birth_month' ],
        'param_desc' => [
            'birth_day'   => 'Day of Birth (01-31)',
            'birth_month' => 'Month of Birth (01-12)'
        ],
        'label' => 'Sun Number'
    ],
    'challenge-number' => [
        'path' => '/challenge_number/post',
        'params' => [ 'birth_day', 'birth_month', 'birth_year' ],
        'param_desc' => [
            'birth_day'   => 'Day of Birth (01-31)',
            'birth_month' => 'Month of Birth (01-12)',
            'birth_year'  => 'Year of Birth (YYYY)'
        ],
        'label' => 'Challenge Number'
    ],
    'karmic-debt' => [
        'path' => '/karmic_debt/post',
        'params' => [ 'birth_year', 'birth_month', 'birth_day' ],
        'param_desc' => [
            'birth_year'  => 'Year of Birth (YYYY)',
            'birth_month' => 'Month of Birth (01-12)',
            'birth_day'   => 'Day of Birth (01-31)'
        ],
        'label' => 'Karmic Debt'
    ],
    'karmic-lesson' => [
        'path' => '/karmic_lessons/post',
        'params' => [ 'full_name' ],
        'param_desc' => [
            'full_name' => 'Full Name as on Birth Certificate'
        ],
        'label' => 'Karmic Lesson'
    ],
    'personality-number' => [
        'path' => '/personality_number/post',
        'params' => [ 'first_name', 'middle_name', 'last_name' ],
        'param_desc' => [
            'first_name'  => 'First Name',
            'middle_name' => 'Middle Name (optional)',
            'last_name'   => 'Last Name'
        ],
        'label' => 'Personality Number'
    ],
    'personal-year' => [
        'path' => '/personal_year/post',
        'params' => [ 'prediction_year', 'birth_month', 'birth_day' ],
        'param_desc' => [
            'prediction_year' => 'Year for Prediction (YYYY)',
            'birth_month'     => 'Month of Birth (01-12)',
            'birth_day'       => 'Day of Birth (01-31)'
        ],
        'label' => 'Personal Year'
    ],
    'personal-month' => [
        'path' => '/personal-month',
        'params' => [ 'dob' ],
        'param_desc' => [
            'dob' => 'Date of Birth (YYYY-MM-DD)'
        ],
        'label' => 'Personal Month'
    ],
    'personal-day' => [
        'path' => '/personal-day',
        'params' => [ 'dob' ],
        'param_desc' => [
            'dob' => 'Date of Birth (YYYY-MM-DD)'
        ],
        'label' => 'Personal Day'
    ],
    'phone-number' => [
        'path' => '/analyze_phone/post',
        'params' => [ 'phone_number' ],
        'param_desc' => [
            'phone_number' => 'Phone Number with Country Code (e.g., +1234567890)'
        ],
        'label' => 'Phone Number'
    ],
    'soul-expression' => [
        'path' => '/destiny_number/post',
        'params' => [ 'first_name', 'middle_name', 'last_name' ],
        'param_desc' => [
            'first_name'  => 'First Name',
            'middle_name' => 'Middle Name (optional)',
            'last_name'   => 'Last Name'
        ],
        'label' => 'Soul Expression'
    ],
    'soul-urge' => [
        'path' => '/heart_desire/post',
        'params' => [ 'first_name', 'middle_name', 'last_name' ],
        'param_desc' => [
            'first_name'  => 'First Name',
            'middle_name' => 'Middle Name (optional)',
            'last_name'   => 'Last Name'
        ],
        'label' => 'Soul Urge'
    ],
    'subconscious-self' => [
        'path' => '/subconscious_number/post',
        'params' => [ 'name' ],
        'param_desc' => [
            'name' => 'Full Name to Analyze'
        ],
        'label' => 'Subconscious Number'
    ],
    'balance-number' => [
        'path' => '/balance_number/post',
        'params' => [ 'initials' ],
        'param_desc' => [
            'initials' => 'Initials of Full Name'
        ],
        'label' => 'Balance Number'
    ],
    'lucky-numbers' => [
        'path' => '/lucky_numbers/post',
        'params' => [ 'birthdate', 'name' ],
        'param_desc' => [
            'birthdate' => 'Date of Birth (YYYY-MM-DD)',
            'name'      => 'Full Name'
        ],
        'label' => 'Lucky Numbers'
    ],
    'rational-thought' => [
        'path' => '/thought_number/post',
        'params' => [ 'first_name', 'birth_day' ],
        'param_desc' => [
            'first_name' => 'First Name',
            'birth_day'  => 'Day of Birth (01-31)'
        ],
        'label' => 'Rational Thought'
    ],
    'life-period' => [
        'path' => '/period_cycles/post',
        'params' => [ 'birth_year', 'birth_month', 'birth_day' ],
        'param_desc' => [
            'birth_year'  => 'Year of Birth (YYYY)',
            'birth_month' => 'Month of Birth (01-12)',
            'birth_day'   => 'Day of Birth (01-31)'
        ],
        'label' => 'Life Period Cycles'
    ],
    'birth-day-number' => [
        'path' => '/birth-day-number',
        'params' => [ 'dob' ],
        'param_desc' => [
            'dob' => 'Date of birth in YYYY-MM-DD format (e.g., 1997-05-17)'
        ],
        'label' => 'Birth Day Number'
    ],
    'hidden-passion' => [
        'path' => '/hidden-passion',
        'params' => [ 'fullname' ],
        'param_desc' => [
            'fullname' => 'Full birth name (e.g., "John Alexander Doe")'
        ],
        'label' => 'Hidden Passion'
    ],
    'hidden-passion-positions' => [
        'path' => '/hidden-passion-positions',
        'params' => [ 'name', 'reduce', 'include_gaps' ],
        'param_desc' => [
            'name' => 'Full name (e.g., "Jesus Christ")',
            'reduce' => 'Reduce sums: true or false',
            'include_gaps' => 'Include gap resonance: true or false'
        ],
        'label' => 'Hidden Passion Positions'
    ],
    'minor-personality' => [
        'path' => '/minor-personality',
        'params' => [ 'short_name' ],
        'param_desc' => [
            'short_name' => 'Full short name (e.g., "Alex Chen")'
        ],
        'label' => 'Minor Personality'
    ],
    'minor-heart-desire' => [
        'path' => '/minor-heart-desire',
        'params' => [ 'short_name' ],
        'param_desc' => [
            'short_name' => 'Full short name (e.g., "Emma Brown")'
        ],
        'label' => 'Minor Heart Desire'
    ],
    'minor-expression' => [
        'path' => '/minor-expression',
        'params' => [ 'current_name' ],
        'param_desc' => [
            'current_name' => 'Full current name (e.g., "Emma Brown"). Must include first + last.'
        ],
        'label' => 'Minor Expression'
    ],
    'ancestor-reading' => [
        'path' => '/ancestor-reading',
        'params' => [ 'family_name' ],
        'param_desc' => [
            'family_name' => 'Family or last name (e.g., "Brown" or "Martinez")'
        ],
        'label' => 'Ancestor Reading'
    ],
    'capstone-letter' => [
        'path' => '/capstone-letter',
        'params' => [ 'name' ],
        'param_desc' => [
            'name' => 'Full name or first name (e.g., "John" or "John Smith"). Capstone is last letter of first word.'
        ],
        'label' => 'Capstone Letter'
    ],
    'cornerstone-letter' => [
        'path' => '/cornerstone-letter',
        'params' => [ 'name' ],
        'param_desc' => [
            'name' => 'The person\'s name (first alphabetic letter is used)'
        ],
        'label' => 'Cornerstone Letter'
    ],
    'compatibility-score' => [
        'path' => '/compatibility-score',
        'params' => [
            'first_name_1', 'middle_name_1', 'last_name_1', 'dob_1',
            'first_name_2', 'middle_name_2', 'last_name_2', 'dob_2'
        ],
        'required' => [
            'first_name_1', 'last_name_1', 'dob_1',
            'first_name_2', 'last_name_2', 'dob_2'
        ],
        'param_desc' => [
            'first_name_1' => 'Person 1: First name',
            'middle_name_1' => 'Person 1: Middle name(s) (optional)',
            'last_name_1' => 'Person 1: Last name',
            'dob_1' => 'Person 1: DOB in YYYY-MM-DD',
            'first_name_2' => 'Person 2: First name',
            'middle_name_2' => 'Person 2: Middle name(s) (optional)',
            'last_name_2' => 'Person 2: Last name',
            'dob_2' => 'Person 2: DOB in YYYY-MM-DD'
        ],
        'label' => 'Compatibility Score'
    ],
    'angel-number-sync' => [
        'path' => '/angel-number-sync',
        'params' => [ 'number' ],
        'param_desc' => [
            'number' => 'Any numeric string (e.g., "111", "1234", "1221")'
        ],
        'label' => 'Angel Number Sync'
    ],
    'date-meaning' => [
        'path' => '/date-meaning',
        'params' => [ 'date' ],
        'param_desc' => [
            'date' => 'Date in YYYY-MM-DD format (e.g., 2025-11-11)'
        ],
        'label' => 'Date Meaning'
    ],
    'email-numerology' => [
        'path' => '/email-numerology',
        'params' => [ 'email' ],
        'param_desc' => [
            'email' => 'Any valid email (e.g., hi@numerologyapi.com)'
        ],
        'label' => 'Email Numerology'
    ],
    'mirror-path' => [
        'path' => '/mirror-path',
        'params' => [ 'dob', 'expanded', 'allow_masters' ],
        'required' => [ 'dob' ],
        'param_desc' => [
            'dob' => 'Date of birth (YYYY-MM-DD or YYYYMMDD)',
            'expanded' => 'If true, returns full mirror cycle and detailed meanings. Default: false',
            'allow_masters' => 'Reserved for future support of master numbers without reduction'
        ],
        'label' => 'Mirror Path & Circles'
    ],
    'mirror-numbers' => [
        'path' => '/mirror-numbers',
        'params' => [ 'base', 'expanded' ],
        'required' => [],
        'param_desc' => [
            'base' => 'Number to analyze (1–9, 11, 22, 33, or any reducible number). If omitted, returns full grid',
            'expanded' => 'When true, adds detailed meanings, mirror cycles, and keyword chains. Default: false'
        ],
        'label' => 'Mirror Numbers Grid'
    ],
    'essence-cycle' => [
        'path' => '/essence-cycle',
        'params' => [ 'full_name', 'dob', 'start_year' ],
        'required' => [ 'full_name', 'dob', 'start_year' ],
        'param_desc' => [
            'full_name' => 'Full birth name (e.g., "Alexander Graham Bell")',
            'dob' => 'Date of birth in YYYY-MM-DD format',
            'start_year' => 'Calendar year to start table (1800–2100)'
        ],
        'label' => 'Essence Cycle (10-Year Table)'
    ],
    'life-essence' => [
        'path' => '/life-essence',
        'params' => [ 'full_name', 'dob' ],
        'required' => [ 'full_name', 'dob' ],
        'param_desc' => [
            'full_name' => 'Full name of the person (e.g., "Alexander Graham Bell")',
            'dob' => 'Date of birth in YYYY-MM-DD format'
        ],
        'label' => 'Life Essence – Unified Core Blueprint'
    ],
    'transits' => [
        'path' => '/transits',
        'params' => [ 'full_name', 'dob', 'age' ],
        'required' => [ 'full_name' ],
        'param_desc' => [
            'full_name' => 'Full name of the person (e.g., "Alexander Graham Bell")',
            'dob' => 'Date of birth in YYYY-MM-DD format (used to calculate age if age not provided)',
            'age' => 'Current age. Overrides age derived from dob. Must be non-negative'
        ],
        'label' => 'Transits – Physical, Mental & Spiritual Cycles'
    ]
];


    /**
     * Get endpoints with labels
     */
    public static function get_endpoints() {
        return apply_filters( 'dakidarts_numerology_endpoints', self::$endpoints );
    }

    /**
     * Make an API POST request
     */
    public static function request( $endpoint_key, $params = [] ) {
        $endpoints = self::get_endpoints();

        if ( ! isset( $endpoints[ $endpoint_key ] ) ) {
            return new WP_Error( 'invalid_endpoint', __( 'Invalid API endpoint requested.', 'dakidarts-numerology-core' ) );
        }

        $endpoint = $endpoints[ $endpoint_key ];

        // Validate required params
        $required_params = isset( $endpoint['required'] ) && is_array( $endpoint['required'] )
            ? $endpoint['required']
            : $endpoint['params'];

        foreach ( $required_params as $p ) {
            if ( ! isset( $params[ $p ] ) || $params[ $p ] === '' ) {
                // translators: %s: missing parameter name.
                return new WP_Error( 'missing_param', sprintf( __( 'Missing required parameter: %s', 'dakidarts-numerology-core' ), $p ) );
            }
        }

        $settings = self::get_settings();
        $route    = isset( $settings['route'] ) ? sanitize_key( $settings['route'] ) : 'rapidapi';
        $lang     = isset( $settings['lang'] ) ? sanitize_key( $settings['lang'] ) : 'en';
        $allowed_langs = [ 'en', 'fr', 'es', 'de', 'pt' ];
        if ( ! in_array( $lang, $allowed_langs, true ) ) {
            $lang = 'en';
        }

        $base_url = ( $route === 'gateway' ) ? self::$gateway_base : self::$rapidapi_base;
        $path     = $endpoint['path'];
        $url      = rtrim( $base_url, '/' ) . '/' . ltrim( $path, '/' );

        if ( $route === 'gateway' ) {
            $url = add_query_arg( 'lang', $lang, $url );
        }

        $api_key = self::get_api_key();
        if ( ! $api_key ) {
            return new WP_Error( 'missing_api_key', __( 'API key not configured. Please set it in plugin settings.', 'dakidarts-numerology-core' ) );
        }

        if ( $route === 'gateway' ) {
            $headers = [
                'x-api-key'    => $api_key,
                'Content-Type' => 'application/json',
            ];
        } else {
            $headers = [
                'x-rapidapi-host' => 'the-numerology-api.p.rapidapi.com',
                'x-rapidapi-key'  => $api_key,
                'Content-Type'    => 'application/json',
            ];
        }

        $response = self::execute_request( $url, $headers, $params, 'POST', $route );

        if ( is_wp_error( $response ) ) {
            return new WP_Error( 'api_request_failed', __( 'API request failed.', 'dakidarts-numerology-core' ), $response->get_error_message() );
        }

        $code = wp_remote_retrieve_response_code( $response );
        $body = wp_remote_retrieve_body( $response );

        $data = json_decode( $body, true );

        // Fallback: some endpoints may only accept GET on certain routes.
        if ( (int) $code === 405 || ( (int) $code >= 400 && $route === 'rapidapi' ) ) {
            $response = self::execute_request( $url, $headers, $params, 'GET', $route );

            if ( is_wp_error( $response ) ) {
                return new WP_Error( 'api_request_failed', __( 'API request failed.', 'dakidarts-numerology-core' ), $response->get_error_message() );
            }

            $code = wp_remote_retrieve_response_code( $response );
            $body = wp_remote_retrieve_body( $response );
            $data = json_decode( $body, true );
        }

        if ( $code < 200 || $code >= 300 ) {
            // translators: %d: HTTP status code.
            return new WP_Error( 'api_error', sprintf( __( 'API request failed with status %d.', 'dakidarts-numerology-core' ), $code ), $body );
        }

        return $data;
    }

    /**
     * Retrieve decrypted API key from settings
     */
    public static function get_api_key() {
        $options = get_option( 'dakidarts_numerology_core_settings', [] );

        if ( empty( $options['api_key'] ) ) {
            return false;
        }

        // Decrypt if helper exists
        if ( method_exists( 'Dakidarts_Helpers', 'decrypt' ) ) {
            $encryption_key = defined( 'DAKIDARTS_SECRET_KEY' ) ? DAKIDARTS_SECRET_KEY : '';
            return Dakidarts_Helpers::decrypt( $options['api_key'], $encryption_key );
        }

        return $options['api_key'];
    }

    /**
     * Get saved plugin settings
     */
    private static function get_settings() {
        return get_option( 'dakidarts_numerology_core_settings', [] );
    }

    /**
     * Execute API request with method fallback support.
     *
     * @param string $url Base URL (already includes lang when needed).
     * @param array  $headers Request headers.
     * @param array  $params Request params.
     * @param string $method HTTP method.
     * @param string $route Selected route.
     * @return array|WP_Error
     */
    private static function execute_request( $url, $headers, $params, $method, $route ) {
        $method = strtoupper( $method );
        $args = [
            'headers' => $headers,
            'timeout' => 20,
            'method'  => $method,
        ];

        if ( $method === 'POST' ) {
            $args['body'] = wp_json_encode( $params );
            return wp_remote_post( $url, $args );
        }

        $existing_query = [];
        $parsed_url = wp_parse_url( $url );
        if ( isset( $parsed_url['query'] ) ) {
            parse_str( $parsed_url['query'], $existing_query );
        }

        $base_url = $parsed_url['scheme'] . '://' . $parsed_url['host'];
        if ( isset( $parsed_url['port'] ) ) {
            $base_url .= ':' . $parsed_url['port'];
        }
        $base_url .= isset( $parsed_url['path'] ) ? $parsed_url['path'] : '';

        if ( substr( $base_url, -5 ) === '/post' ) {
            $base_url = substr( $base_url, 0, -5 );
        }

        $url = add_query_arg( array_merge( $existing_query, $params ), $base_url );
        return wp_remote_get( $url, $args );
    }
}
