<?php
/**
 * CRM Export Endpoint for BoostBot REST API.
 *
 * Provides API endpoints for external CRM integration with API Key authentication.
 *
 * @package BoostBot
 * @since   1.0.0
 */

// Prevent direct access.
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * BoostBot_CRM_Export_Endpoint class.
 *
 * Provides REST API endpoints for CRM integration.
 * Supports both API Key and WordPress Admin authentication.
 *
 * @since 1.0.0
 */
class BoostBot_CRM_Export_Endpoint extends BoostBot_Base_Endpoint {

    /**
     * The base path for this endpoint.
     *
     * @var string
     */
    protected $rest_base = 'crm';

    /**
     * Register the routes for this endpoint.
     *
     * @since 1.0.0
     */
    public function register() {
        // GET /wp-json/boostbot/v1/crm/leads - Leads with conversations.
        $this->register_route(
            '/leads',
            'GET',
            array( $this, 'get_leads_with_conversations' ),
            array( $this, 'check_crm_permission' )
        );

        // GET /wp-json/boostbot/v1/crm/leads/{id} - Single lead with conversation.
        $this->register_route(
            '/leads/(?P<id>\d+)',
            'GET',
            array( $this, 'get_lead_with_conversation' ),
            array( $this, 'check_crm_permission' )
        );

        // GET /wp-json/boostbot/v1/crm/conversations - Conversations only.
        $this->register_route(
            '/conversations',
            'GET',
            array( $this, 'get_conversations' ),
            array( $this, 'check_crm_permission' )
        );

        // GET /wp-json/boostbot/v1/crm/meetings - Meetings.
        $this->register_route(
            '/meetings',
            'GET',
            array( $this, 'get_meetings' ),
            array( $this, 'check_crm_permission' )
        );

        // GET /wp-json/boostbot/v1/crm/meetings/{id} - Single meeting.
        $this->register_route(
            '/meetings/(?P<id>\d+)',
            'GET',
            array( $this, 'get_meeting' ),
            array( $this, 'check_crm_permission' )
        );
    }

    /**
     * Check CRM API permission.
     *
     * Supports API Key header OR WordPress Admin login.
     *
     * @since 1.0.0
     * @param WP_REST_Request $request The request.
     * @return bool True if authorized, false otherwise.
     */
    public function check_crm_permission( $request ) {
        // Option 1: API Key in header.
        $api_key = $request->get_header( 'X-BoostBot-API-Key' );
        if ( $api_key && $this->validate_api_key( $api_key ) ) {
            return true;
        }

        // Option 2: WordPress admin logged in.
        if ( current_user_can( 'manage_options' ) ) {
            return true;
        }

        return false;
    }

    /**
     * Validate API Key.
     *
     * @since 1.0.0
     * @param string $key The API key to validate.
     * @return bool True if valid, false otherwise.
     */
    private function validate_api_key( $key ) {
        $stored_key = get_option( 'boostbot_crm_api_key', '' );

        if ( empty( $stored_key ) ) {
            return false;
        }

        return hash_equals( $stored_key, $key );
    }

    /**
     * GET /crm/leads - Get leads with their conversation history.
     *
     * @since 1.0.0
     * @param WP_REST_Request $request The request.
     * @return WP_REST_Response The response.
     */
    public function get_leads_with_conversations( $request ) {
        $lead_model         = new BoostBot_Lead_Model();
        $conversation_model = new BoostBot_Conversation_Model();

        // Pagination.
        $pagination = $this->get_pagination_params( $request );

        // Filters.
        $where = array();
        if ( $request->has_param( 'status' ) ) {
            $where['lead_status'] = sanitize_text_field( $request->get_param( 'status' ) );
        }

        // Date filters.
        $from_date = $request->get_param( 'from_date' );
        $to_date   = $request->get_param( 'to_date' );

        // Include messages?
        $include_messages = $request->get_param( 'include_messages' ) !== 'false';

        // Get leads.
        $leads = $lead_model->get_all(
            array(
                'where'    => $where,
                'order_by' => 'created_at',
                'order'    => 'DESC',
                'limit'    => $pagination['per_page'],
                'offset'   => $pagination['offset'],
            )
        );

        $total = $lead_model->count( $where );

        // Enhance with conversations.
        $result = array();
        foreach ( $leads as $lead ) {
            $lead_data = (array) $lead;

            // Parse JSON fields.
            $lead_data['utm_data']  = ! empty( $lead->utm_data ) ? json_decode( $lead->utm_data, true ) : null;
            $lead_data['form_data'] = ! empty( $lead->form_data ) ? json_decode( $lead->form_data, true ) : null;
            $lead_data['metadata']  = ! empty( $lead->metadata ) ? json_decode( $lead->metadata, true ) : null;

            if ( $include_messages && ! empty( $lead->conversation_id ) ) {
                $conversation = $conversation_model->get_by_conversation_id( $lead->conversation_id );
                if ( $conversation ) {
                    $messages                   = json_decode( $conversation->session_data, true );
                    $lead_data['conversation'] = array(
                        'id'            => $conversation->id,
                        'messages'      => $this->format_messages( $messages ),
                        'message_count' => $conversation->total_messages,
                        'started_at'    => $conversation->started_at,
                        'last_message'  => $conversation->last_message_at,
                    );
                }
            }

            $result[] = $lead_data;
        }

        return $this->success(
            array(
                'leads' => $result,
                'meta'  => array(
                    'total'       => $total,
                    'page'        => $pagination['page'],
                    'per_page'    => $pagination['per_page'],
                    'total_pages' => (int) ceil( $total / $pagination['per_page'] ),
                ),
            )
        );
    }

    /**
     * GET /crm/leads/{id} - Get single lead with full conversation.
     *
     * @since 1.0.0
     * @param WP_REST_Request $request The request.
     * @return WP_REST_Response|WP_Error The response.
     */
    public function get_lead_with_conversation( $request ) {
        $lead_id = absint( $request->get_param( 'id' ) );

        $lead_model         = new BoostBot_Lead_Model();
        $conversation_model = new BoostBot_Conversation_Model();

        $lead = $lead_model->get( $lead_id );

        if ( ! $lead ) {
            return $this->not_found( 'Lead' );
        }

        $lead_data = (array) $lead;

        // Parse JSON fields.
        $lead_data['utm_data']  = ! empty( $lead->utm_data ) ? json_decode( $lead->utm_data, true ) : null;
        $lead_data['form_data'] = ! empty( $lead->form_data ) ? json_decode( $lead->form_data, true ) : null;
        $lead_data['metadata']  = ! empty( $lead->metadata ) ? json_decode( $lead->metadata, true ) : null;

        // Get conversation.
        if ( ! empty( $lead->conversation_id ) ) {
            $conversation = $conversation_model->get_by_conversation_id( $lead->conversation_id );
            if ( $conversation ) {
                $messages = json_decode( $conversation->session_data, true );
                
                // Decode context_data to extract page info (page_url is NOT a column)
                $context_data = ! empty( $conversation->context_data ) ? json_decode( $conversation->context_data, true ) : array();
                $page_url     = $context_data['page_url'] ?? $context_data['url'] ?? null;
                $page_title   = $context_data['page_title'] ?? $context_data['title'] ?? null;

                $lead_data['conversation'] = array(
                    'id'              => $conversation->id,
                    'conversation_id' => $conversation->conversation_id,
                    'messages'        => $this->format_messages( $messages ),
                    'message_count'   => $conversation->total_messages,
                    'started_at'      => $conversation->started_at,
                    'last_message'    => $conversation->last_message_at,
                    'page_url'        => $page_url,
                    'page_title'      => $page_title,
                );
            }
        }

        return $this->success(
            array(
                'lead' => $lead_data,
            )
        );
    }

    /**
     * GET /crm/conversations - Get conversations with optional lead data.
     *
     * @since 1.0.0
     * @param WP_REST_Request $request The request.
     * @return WP_REST_Response The response.
     */
    public function get_conversations( $request ) {
        $conversation_model = new BoostBot_Conversation_Model();
        $lead_model         = new BoostBot_Lead_Model();

        // Pagination.
        $pagination = $this->get_pagination_params( $request );

        // Filter option.
        $with_lead_only = $request->get_param( 'with_lead_only' ) === 'true';

        $conversations = $conversation_model->get_all(
            array(
                'order_by' => 'started_at',
                'order'    => 'DESC',
                'limit'    => $pagination['per_page'],
                'offset'   => $pagination['offset'],
            )
        );

        $total = $conversation_model->count();

        // Enhance with lead data and messages.
        $result = array();
        foreach ( $conversations as $conv ) {
            // Decode context_data to extract page info (page_url, page_title are NOT columns)
            $context_data = ! empty( $conv->context_data ) ? json_decode( $conv->context_data, true ) : array();
            $page_url     = $context_data['page_url'] ?? $context_data['url'] ?? null;
            $page_title   = $context_data['page_title'] ?? $context_data['title'] ?? null;

            $conv_data = array(
                'id'              => $conv->id,
                'conversation_id' => $conv->conversation_id,
                'visitor_id'      => $conv->visitor_id,
                'started_at'      => $conv->started_at,
                'last_message_at' => $conv->last_message_at,
                'message_count'   => $conv->total_messages,
                'conversion'      => (bool) $conv->conversion_achieved,
                'page_url'        => $page_url,
                'page_title'      => $page_title,
                'referrer'        => $context_data['referrer'] ?? null,
            );

            // Get messages.
            $messages              = json_decode( $conv->session_data, true );
            $conv_data['messages'] = $this->format_messages( $messages );

            // Get associated lead.
            $lead = $lead_model->get_by_conversation_id( $conv->conversation_id );
            if ( $lead ) {
                $conv_data['lead'] = array(
                    'id'     => $lead->id,
                    'name'   => $lead->name,
                    'email'  => $lead->email,
                    'phone'  => $lead->phone,
                    'status' => $lead->lead_status,
                );
            }

            // Filter: with_lead_only.
            if ( $with_lead_only && ! $lead ) {
                continue;
            }

            $result[] = $conv_data;
        }

        return $this->success(
            array(
                'conversations' => $result,
                'meta'          => array(
                    'total'       => count( $result ),
                    'page'        => $pagination['page'],
                    'per_page'    => $pagination['per_page'],
                    'total_pages' => (int) ceil( $total / $pagination['per_page'] ),
                ),
            )
        );
    }

    /**
     * GET /crm/meetings - Get meetings with pagination and optional date filters.
     *
     * @param WP_REST_Request $request The request.
     * @return WP_REST_Response
     */
    public function get_meetings( $request ) {
        $model = new BoostBot_Meeting_Model();

        $pagination = $this->get_pagination_params( $request );

        $start_date = $request->get_param( 'start_date' );
        $end_date   = $request->get_param( 'end_date' );

        $start_date = ! empty( $start_date ) ? sanitize_text_field( $start_date ) : '1970-01-01';
        $end_date   = ! empty( $end_date ) ? sanitize_text_field( $end_date ) : '2999-12-31';

        // Meeting model returns array; best-effort pagination by slice.
        $all = $model->get_by_date_range( $start_date, $end_date, null );
        $total = is_array( $all ) ? count( $all ) : 0;
        $meetings_raw = is_array( $all ) ? array_slice( $all, $pagination['offset'], $pagination['per_page'] ) : array();

        // Enhance meetings with decoded custom_fields and expose page_url at top level
        $meetings = array();
        foreach ( $meetings_raw as $meeting ) {
            $meeting_data = (array) $meeting;
            
            // Decode custom_fields to extract page context
            $custom_fields = array();
            if ( ! empty( $meeting->custom_fields ) ) {
                $custom_fields = is_string( $meeting->custom_fields ) 
                    ? json_decode( $meeting->custom_fields, true ) 
                    : $meeting->custom_fields;
            }
            
            // Expose page_url and page_title at top level for CRM consumption
            $meeting_data['page_url']      = $custom_fields['page_url'] ?? null;
            $meeting_data['page_title']    = $custom_fields['page_title'] ?? null;
            $meeting_data['custom_fields'] = $custom_fields;
            
            $meetings[] = $meeting_data;
        }

        return $this->success( array(
            'meetings' => $meetings,
            'meta'     => array(
                'total'       => $total,
                'page'        => $pagination['page'],
                'per_page'    => $pagination['per_page'],
                'total_pages' => (int) ceil( max( 1, $total ) / $pagination['per_page'] ),
            ),
        ) );
    }

    /**
     * GET /crm/meetings/{id} - Get a single meeting.
     *
     * @param WP_REST_Request $request The request.
     * @return WP_REST_Response|WP_Error
     */
    public function get_meeting( $request ) {
        $id = absint( $request->get_param( 'id' ) );
        $model = new BoostBot_Meeting_Model();
        $meeting = $model->get_with_details( $id );

        if ( ! $meeting ) {
            return $this->not_found( 'Meeting' );
        }

        return $this->success( array( 'meeting' => $meeting ) );
    }

    /**
     * Format messages for export.
     *
     * @since 1.0.0
     * @param mixed $messages Raw messages data.
     * @return array Formatted messages.
     */
    private function format_messages( $messages ) {
        if ( ! is_array( $messages ) ) {
            return array();
        }

        // Handle both formats: direct array or { messages: [...] }.
        if ( isset( $messages['messages'] ) ) {
            $messages = $messages['messages'];
        }

        return array_map(
            function ( $msg ) {
                return array(
                    'role'      => isset( $msg['role'] ) ? $msg['role'] : 'user',
                    'content'   => isset( $msg['content'] ) ? $msg['content'] : '',
                    'timestamp' => isset( $msg['timestamp'] ) ? $msg['timestamp'] : null,
                );
            },
            $messages
        );
    }
}








