<?php

namespace MetForm_Pro\Core\Analytics;

use MetForm_Pro\Core\Analytics\Helpers\Database;
use MetForm_Pro\Core\Analytics\Helpers\Quiz_Analytics;

defined('ABSPATH') || exit;

class Api extends \MetForm_Pro\Base\Api
{
    /**
     * Overrides the base class gate so all routes pass the WP permission_callback.
     * Each handler enforces its own nonce + capability checks internally,
     * allowing track_view to remain accessible to unauthenticated visitors.
     *
     * @return true
     */
    public function permission_check() {
        return true;
    }
    /**
     * Resolve form ID from request supporting both formId and form_id.
     *
     * @return int
     */
    private function resolve_form_id()
    {
        if (isset($this->request['formId']) && $this->request['formId'] !== '') {
            return intval($this->request['formId']);
        }

        if (isset($this->request['formID']) && $this->request['formID'] !== '') {
            return intval($this->request['formID']);
        }

        if (isset($this->request['form_id']) && $this->request['form_id'] !== '') {
            return intval($this->request['form_id']);
        }

        return 0;
    }

    /**
     * Resolve start date from request supporting both startDate and start_date.
     * Returns an empty string when missing or not a valid Y-m-d date.
     *
     * @return string
     */
    private function resolve_start_date()
    {
        if (isset($this->request['startDate']) && $this->request['startDate'] !== '') {
            return $this->sanitize_date($this->request['startDate']);
        }

        if (isset($this->request['start_date']) && $this->request['start_date'] !== '') {
            return $this->sanitize_date($this->request['start_date']);
        }

        return '';
    }

    /**
     * Resolve end date from request supporting both endDate and end_date.
     * Returns an empty string when missing or not a valid Y-m-d date.
     *
     * @return string
     */
    private function resolve_end_date()
    {
        if (isset($this->request['endDate']) && $this->request['endDate'] !== '') {
            return $this->sanitize_date($this->request['endDate']);
        }

        if (isset($this->request['end_date']) && $this->request['end_date'] !== '') {
            return $this->sanitize_date($this->request['end_date']);
        }

        return '';
    }

    /**
     * Sanitize and validate a date value as strict Y-m-d.
     * Invalid input is treated as "no date" (empty string) rather than passed to SQL.
     *
     * @param mixed $value Raw request value.
     * @return string Valid Y-m-d date or empty string.
     */
    private function sanitize_date($value)
    {
        $value = sanitize_text_field($value);

        if ($value === '' || ! preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) {
            return '';
        }

        // Reject impossible dates such as 2026-13-40.
        $parts = explode('-', $value);
        if (! checkdate((int) $parts[1], (int) $parts[2], (int) $parts[0])) {
            return '';
        }

        return $value;
    }

    public function config()
    {
        $this->prefix = 'analytics';
        $this->param = "/?(?P<id>[\\d]+)?";
    }

    /**
     * Get forms list with basic stats
     * Endpoint: GET /metform-pro/v1/analytics/forms
     * Form Type: GET /metform-pro/v1/analytics/forms?form_type=quiz (values: general, quiz, all; defaults to general)
     * @return \WP_REST_Response|\WP_Error Forms list with basic stats
     */
    public function get_forms()
    {
        if (!wp_verify_nonce($this->request->get_header('X-WP-Nonce'), 'wp_rest')) {
            return new \WP_Error(
                'rest_forbidden',
                esc_html__('Invalid or missing nonce.', 'metform-pro'),
                ['status' => 403]
            );
        }

        if (!is_user_logged_in() || !current_user_can('manage_options')) {
             return new \WP_Error(
                'rest_forbidden',
                esc_html__('You do not have permission to access this resource.', 'metform-pro'),
                ['status' => 403]
            );
        }

        $form_id = $this->resolve_form_id();
        $form_type = isset($this->request['form_type']) ? sanitize_text_field($this->request['form_type']) : 'general';
        $data = Database::get_forms( $form_id, $form_type );
        return rest_ensure_response($data);
    }

    /**
     * Get analytics logs data with filtering
     * Endpoint: GET /metform-pro/v1/analytics/logs
     * Form Type: GET /metform-pro/v1/analytics/logs?form_type=quiz (values: general, quiz, all; defaults to all)
     * @return \WP_REST_Response|\WP_Error Analytics data based on filters
     */
    public function get_logs()
    {
       if (!wp_verify_nonce($this->request->get_header('X-WP-Nonce'), 'wp_rest')) {
            return new \WP_Error(
                'rest_forbidden',
                esc_html__('Invalid or missing nonce.', 'metform-pro'),
                ['status' => 403]
            );
        }

        if (!is_user_logged_in() || !current_user_can('manage_options')) {
             return new \WP_Error(
                'rest_forbidden',
                esc_html__('You do not have permission to access this resource.', 'metform-pro'),
                ['status' => 403]
            );
        }

        $form_id = $this->resolve_form_id();
        $start_date = $this->resolve_start_date();
        $end_date = $this->resolve_end_date();
        $type = isset($this->request['type']) ? sanitize_text_field($this->request['type']) : 'conversion';
        // Defaults to 'all' (general + quiz combined) when the caller doesn't scope to a single form type,
        // e.g. the "All Forms" view on the general dashboard should include quiz form activity too.
        $form_type = isset($this->request['form_type']) ? sanitize_text_field($this->request['form_type']) : 'all';

        // Validate type
        $valid_types = ['conversion', 'devices', 'browsers', 'countries', 'referrers', 'sources'];
        if (!in_array($type, $valid_types)) {
            return new \WP_Error('invalid_type', 'Invalid type parameter.', ['status' => 400]);
        }

        // Validate form_type
        $valid_form_types = ['general', 'quiz', 'all'];
        if (!in_array($form_type, $valid_form_types)) {
            return new \WP_Error('invalid_form_type', 'Invalid form_type parameter.', ['status' => 400]);
        }

        $data = Database::get_logs($form_id, $start_date, $end_date, $type, $form_type);
        
        return rest_ensure_response($data);
    }

    /**
     * Get date range for analytics
     * Endpoint: GET /metform-pro/v1/analytics/date_range
     *
     * @return \WP_REST_Response|\WP_Error Date range data
     */
    public function get_date_range()
    {
        if (!wp_verify_nonce($this->request->get_header('X-WP-Nonce'), 'wp_rest')) {
            return new \WP_Error(
                'rest_forbidden',
                esc_html__('Invalid or missing nonce.', 'metform-pro'),
                ['status' => 403]
            );
        }

        if (!is_user_logged_in() || !current_user_can('manage_options')) {
             return new \WP_Error(
                'rest_forbidden',
                esc_html__('You do not have permission to access this resource.', 'metform-pro'),
                ['status' => 403]
            );
        }

        $form_id = $this->resolve_form_id();

        $data = Database::get_date_range($form_id);
        
        return rest_ensure_response($data);
    }

    /**
     * Track form view via REST API
     * Endpoint: POST /metform-pro/v1/analytics/track_view/{id}
     *
     * Public endpoint (called by frontend JS) — guarded by the WP REST nonce.
     *
     * @return \WP_REST_Response|\WP_Error Success response
     */
    public function post_track_view()
    {
        // Public endpoint: accept the X-WP-Nonce header (fetch) or the _wpnonce param (sendBeacon).
        $nonce = $this->request->get_header('X-WP-Nonce');
        if (empty($nonce)) {
            $nonce = $this->request->get_param('_wpnonce');
        }

        if (!wp_verify_nonce($nonce, 'wp_rest')) {
            return new \WP_Error(
                'rest_forbidden',
                esc_html__('Invalid or missing nonce.', 'metform-pro'),
                ['status' => 403]
            );
        }

        $form_id = isset($this->request['id']) ? intval($this->request['id']) : 0;

        if ($form_id === 0) {
            return new \WP_Error('invalid_form_id', 'Invalid form ID provided.', ['status' => 400]);
        }

        // Get tracking data from request body (sent from JavaScript)
        $body = $this->request->get_json_params();

        $tracking_data = [
            // Clamp session_duration to a sane 24h ceiling so a spoofed payload cannot skew averages.
            'session_duration' => min(86400, max(0, isset($body['session_duration']) ? intval($body['session_duration']) : 0)),
            'is_update'        => !empty($body['is_update']),
            'device'           => isset($body['device']) ? sanitize_text_field($body['device']) : 'desktop',
            'browser'          => isset($body['browser']) ? sanitize_text_field($body['browser']) : 'other',
            'source'           => isset($body['source']) ? sanitize_text_field($body['source']) : 'direct',
            'referrer'         => isset($body['referrer']) ? esc_url_raw($body['referrer']) : '',
            'country'          => isset($body['country']) ? sanitize_text_field($body['country']) : '',
        ];

        // Log the view to database
        $log_id = Database::log_view($form_id, $tracking_data);

        return rest_ensure_response([
            'success' => true,
            'message' => 'View tracked successfully',
            'log_id' => $log_id
        ]);
    }

    
    /**
     * Delete analytics logs
     * Endpoint: DELETE /metform-pro/v1/analytics/logs
     *
     * @return \WP_REST_Response|\WP_Error Success response
     */
    public function delete_logs()
    {
        if (!wp_verify_nonce($this->request->get_header('X-WP-Nonce'), 'wp_rest')) {
            return new \WP_Error(
                'rest_forbidden',
                esc_html__('Invalid or missing nonce.', 'metform-pro'),
                ['status' => 403]
            );
        }

        if (!is_user_logged_in() || !current_user_can('manage_options')) {
             return new \WP_Error(
                'rest_forbidden',
                esc_html__('You do not have permission to access this resource.', 'metform-pro'),
                ['status' => 403]
            );
        }

        $form_id = $this->resolve_form_id();
        $start_date = $this->resolve_start_date();
        $end_date = $this->resolve_end_date();

        if (empty($start_date) || empty($end_date)) {
            return new \WP_Error('missing_params', 'Start date and end date are required.', ['status' => 400]);
        }

        $deleted = Database::delete_logs_range($form_id, $start_date, $end_date);

        return rest_ensure_response([
            'success' => true,
            'message' => 'Logs deleted successfully',
            'deleted_rows' => $deleted
        ]);
    }

    /**
     * Get quiz analytics data
     * Endpoint: GET /metform-pro/v1/analytics/quiz
     *
     * @return \WP_REST_Response|\WP_Error Quiz analytics data
     */
    public function get_quiz()
    {
        if (!wp_verify_nonce($this->request->get_header('X-WP-Nonce'), 'wp_rest')) {
            return new \WP_Error(
                'rest_forbidden',
                esc_html__('Invalid or missing nonce.', 'metform-pro'),
                ['status' => 403]
            );
        }

        if (!is_user_logged_in() || !current_user_can('manage_options')) {
             return new \WP_Error(
                'rest_forbidden',
                esc_html__('You do not have permission to access this resource.', 'metform-pro'),
                ['status' => 403]
            );
        }

        // formId is optional, but if provided (formId/formID), it must be valid.
        $form_id = $this->resolve_form_id();
        $start_date = $this->resolve_start_date();
        $end_date = $this->resolve_end_date();

        $result = Quiz_Analytics::get_quiz_analytics($form_id, $start_date, $end_date);

        // Check if result is a WP_Error
        if (is_wp_error($result)) {
            return $result;
        }

        return rest_ensure_response($result);
    }

    /**
     * Get quiz question-wise answer statistics data
     * Endpoint: GET /metform-pro/v1/analytics/quiz_answer_statistics
     *
     * @return \WP_REST_Response|\WP_Error Quiz answer statistics data
     */
    public function get_quiz_answer_statistics()
    {
        if (!wp_verify_nonce($this->request->get_header('X-WP-Nonce'), 'wp_rest')) {
            return new \WP_Error(
                'rest_forbidden',
                esc_html__('Invalid or missing nonce.', 'metform-pro'),
                ['status' => 403]
            );
        }

        if (!is_user_logged_in() || !current_user_can('manage_options')) {
             return new \WP_Error(
                'rest_forbidden',
                esc_html__('You do not have permission to access this resource.', 'metform-pro'),
                ['status' => 403]
            );
        }

        // formId is optional, but if provided (formId/formID), it must be valid.
        $form_id = $this->resolve_form_id();

        $start_date = $this->resolve_start_date();
        $end_date = $this->resolve_end_date();
        // Clamp to a sane range to avoid unbounded result building.
        $common_limit = isset($this->request['commonLimit']) ? min(100, max(1, intval($this->request['commonLimit']))) : 6;

        $result = Quiz_Analytics::get_quiz_answer_statistics($form_id, $start_date, $end_date, $common_limit);

        if (is_wp_error($result)) {
            return $result;
        }

        return rest_ensure_response($result);
    }

    /**
     * Get quiz difficulty analysis data
     * Endpoint: GET /metform-pro/v1/analytics/quiz_difficulty_analysis
     *
     * @return \WP_REST_Response|\WP_Error Quiz difficulty analysis data
     */
    public function get_quiz_difficulty_analysis()
    {
        if (!wp_verify_nonce($this->request->get_header('X-WP-Nonce'), 'wp_rest')) {
            return new \WP_Error(
                'rest_forbidden',
                esc_html__('Invalid or missing nonce.', 'metform-pro'),
                ['status' => 403]
            );
        }

        if (!is_user_logged_in() || !current_user_can('manage_options')) {
             return new \WP_Error(
                'rest_forbidden',
                esc_html__('You do not have permission to access this resource.', 'metform-pro'),
                ['status' => 403]
            );
        }

        // formId is optional, but if provided (formId/formID), it must be valid.
        $form_id = $this->resolve_form_id();

        $start_date = $this->resolve_start_date();
        $end_date = $this->resolve_end_date();

        $result = Quiz_Analytics::get_quiz_difficulty_analysis($form_id, $start_date, $end_date);

        if (is_wp_error($result)) {
            return $result;
        }

        return rest_ensure_response($result);
    }

    /**
     * Get quiz score distribution (percentage buckets).
     * Endpoint: GET /metform-pro/v1/analytics/quiz_score_distribution
     *
     * @return \WP_REST_Response|\WP_Error
     */
    public function get_quiz_score_distribution()
    {
        if (!wp_verify_nonce($this->request->get_header('X-WP-Nonce'), 'wp_rest')) {
            return new \WP_Error(
                'rest_forbidden',
                esc_html__('Invalid or missing nonce.', 'metform-pro'),
                ['status' => 403]
            );
        }

        if (!is_user_logged_in() || !current_user_can('manage_options')) {
             return new \WP_Error(
                'rest_forbidden',
                esc_html__('You do not have permission to access this resource.', 'metform-pro'),
                ['status' => 403]
            );
        }

        $form_id = $this->resolve_form_id();
        $start_date = $this->resolve_start_date();
        $end_date = $this->resolve_end_date();

        $result = Quiz_Analytics::get_quiz_score_distribution($form_id, $start_date, $end_date);

        if (is_wp_error($result)) {
            return $result;
        }

        return rest_ensure_response($result);
    }

}
