<?php
/**
 * Class LSC_Ajax
 * Registers and handles all AJAX endpoints for the plugin.
 */
class LSC_Ajax {

    public function __construct() {
        // Visitor-side (no login required).
        add_action( 'wp_ajax_nopriv_lsc_visitor_send',       [ $this, 'visitor_send' ] );
        add_action( 'wp_ajax_nopriv_lsc_visitor_poll',       [ $this, 'visitor_poll' ] );
        add_action( 'wp_ajax_nopriv_lsc_get_status',         [ $this, 'get_status' ] );

        // Also allow logged-in users to chat as visitors.
        add_action( 'wp_ajax_lsc_visitor_send',              [ $this, 'visitor_send' ] );
        add_action( 'wp_ajax_lsc_visitor_poll',              [ $this, 'visitor_poll' ] );
        add_action( 'wp_ajax_lsc_get_status',                [ $this, 'get_status' ] );

        // Chatter / admin side (login required).
        add_action( 'wp_ajax_lsc_chatter_poll',              [ $this, 'chatter_poll' ] );
        add_action( 'wp_ajax_lsc_chatter_reply',             [ $this, 'chatter_reply' ] );
        add_action( 'wp_ajax_lsc_close_chat',                [ $this, 'close_chat' ] );
        add_action( 'wp_ajax_lsc_mark_read',                 [ $this, 'mark_read' ] );

        // Admin only.
        add_action( 'wp_ajax_lsc_toggle_status',             [ $this, 'toggle_status' ] );
        add_action( 'wp_ajax_lsc_delete_chat',               [ $this, 'delete_chat' ] );
    }

    /* ------------------------------------------------------------------
     * Helpers
     * ------------------------------------------------------------------ */

    private function send_success( $data = [] ) {
        wp_send_json_success( $data );
    }

    private function send_error( $message, $code = 400 ) {
        wp_send_json_error( [ 'message' => $message ], $code );
    }

    private function verify_nonce( $action ) {
        if ( ! isset( $_REQUEST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ) ), $action ) ) {
            $this->send_error( __( 'Security check failed.', 'live-support-chat' ), 403 );
        }
    }

    private function require_capability( $cap ) {
        if ( ! current_user_can( $cap ) ) {
            $this->send_error( __( 'Insufficient permissions.', 'live-support-chat' ), 403 );
        }
    }

    private function get_visitor_id() {
        if ( isset( $_COOKIE['lsc_visitor_id'] ) ) {
            return sanitize_text_field( wp_unslash( $_COOKIE['lsc_visitor_id'] ) );
        }
        return '';
    }

    /* ------------------------------------------------------------------
     * Public endpoint: get online/offline status
     * ------------------------------------------------------------------ */

    public function get_status() {
        $this->send_success( [
            'status' => get_option( 'lsc_chat_status', 'offline' ),
        ] );
    }

    /* ------------------------------------------------------------------
     * Visitor: send message
     * ------------------------------------------------------------------ */

    public function visitor_send() {
        $this->verify_nonce( 'lsc_visitor_nonce' );

        $visitor_id    = $this->get_visitor_id();
        $message       = isset( $_POST['message'] ) ? sanitize_textarea_field( wp_unslash( $_POST['message'] ) ) : '';
        $visitor_name  = isset( $_POST['visitor_name'] ) ? sanitize_text_field( wp_unslash( $_POST['visitor_name'] ) ) : '';
        $visitor_email = isset( $_POST['visitor_email'] ) ? sanitize_email( wp_unslash( $_POST['visitor_email'] ) ) : '';

        if ( empty( $visitor_id ) ) {
            $this->send_error( __( 'Session not found.', 'live-support-chat' ) );
        }

        if ( empty( $message ) ) {
            $this->send_error( __( 'Message cannot be empty.', 'live-support-chat' ) );
        }

        // Get or create chat.
        $chat = LSC_DB::get_chat_by_visitor( $visitor_id );
        if ( ! $chat ) {
            $chat_id = LSC_DB::create_chat( $visitor_id, $visitor_name, $visitor_email );
            if ( ! $chat_id ) {
                $this->send_error( __( 'Could not create chat session.', 'live-support-chat' ) );
            }
        } else {
            $chat_id = (int) $chat->id;
        }

        $msg_id = LSC_DB::add_message( $chat_id, 'visitor', $message );
        if ( ! $msg_id ) {
            $this->send_error( __( 'Could not save message.', 'live-support-chat' ) );
        }

        // Send email notification when support is offline (only on the FIRST message in a chat).
        $chat_obj = LSC_DB::get_chat( $chat_id );
        $msg_count = LSC_DB::count_chat_messages( $chat_id );
        if ( 'offline' === get_option( 'lsc_chat_status', 'offline' ) && $msg_count <= 1 ) {
            $this->send_offline_email( $message, $visitor_name, $visitor_email, $chat_id );
        }

        $this->send_success( [
            'chat_id' => $chat_id,
            'msg_id'  => $msg_id,
        ] );
    }

    /* ------------------------------------------------------------------
     * Send email notification when offline
     * ------------------------------------------------------------------ */

    private function send_offline_email( $message, $visitor_name, $visitor_email, $chat_id ) {
        $to = get_option( 'lsc_notification_email', get_option( 'admin_email' ) );
        if ( empty( $to ) ) {
            return;
        }

        $site_name = get_bloginfo( 'name' );

        $subject_tpl = get_option(
            'lsc_notification_email_subject',
            __( 'New offline chat message – {site_name}', 'live-support-chat' )
        );
        $subject = str_replace( '{site_name}', $site_name, $subject_tpl );

        $from_name  = $visitor_name  ?: __( 'Anonymous Visitor', 'live-support-chat' );
        $from_email = $visitor_email ?: __( '(no email provided)', 'live-support-chat' );

        $body  = "You received a new chat message while support was offline.

";
        $body .= "Site:         " . $site_name . "
";
        $body .= "Visitor name: " . $from_name . "
";
        $body .= "Visitor email:" . $from_email . "
";
        $body .= "Chat ID:      " . $chat_id . "
";
        $body .= "Date/time:    " . current_time( 'mysql' ) . "

";
        $body .= "--- Message ---
";
        $body .= $message . "

";
        $body .= "---
";
        $body .= "Log in to the chat dashboard to reply:
";

        $dashboard_page = (int) get_option( 'lsc_chatter_dashboard_page', 0 );
        if ( $dashboard_page ) {
            $body .= get_permalink( $dashboard_page ) . "
";
        } else {
            $body .= admin_url( 'admin.php?page=lsc-chats' ) . "
";
        }

        wp_mail(
            sanitize_email( $to ),
            sanitize_text_field( $subject ),
            $body,
            [ 'Content-Type: text/plain; charset=UTF-8' ]
        );
    }

    /* ------------------------------------------------------------------
     * Visitor: poll for new messages
     * ------------------------------------------------------------------ */

    public function visitor_poll() {
        $this->verify_nonce( 'lsc_visitor_nonce' );

        $visitor_id = $this->get_visitor_id();
        $since_id   = isset( $_POST['since_id'] ) ? (int) $_POST['since_id'] : 0;

        if ( empty( $visitor_id ) ) {
            $this->send_success( [ 'messages' => [] ] );
        }

        $chat = LSC_DB::get_chat_by_visitor( $visitor_id );
        if ( ! $chat ) {
            $this->send_success( [ 'messages' => [] ] );
        }

        $messages = LSC_DB::get_messages( (int) $chat->id, $since_id );
        $output   = [];
        foreach ( $messages as $msg ) {
            $output[] = [
                'id'      => (int) $msg->id,
                'sender'  => $msg->sender,
                'content' => wp_kses_post( $msg->content ),
                'time'    => mysql2date( 'H:i', $msg->created_at ),
            ];
        }

        $this->send_success( [ 'messages' => $output, 'chat_id' => (int) $chat->id ] );
    }

    /* ------------------------------------------------------------------
     * Chatter: poll all open chats and their latest messages
     * ------------------------------------------------------------------ */

    public function chatter_poll() {
        $this->verify_nonce( 'lsc_chatter_nonce' );
        $this->require_capability( 'lsc_view_chats' );

        $since_id = isset( $_POST['since_id'] ) ? (int) $_POST['since_id'] : 0;
        $chat_id  = isset( $_POST['chat_id'] )  ? (int) $_POST['chat_id']  : 0;

        $data = [
            'chats'    => [],
            'messages' => [],
        ];

        // Always return fresh chat list.
        $chats = LSC_DB::get_chats( [ 'status' => 'open' ] );
        foreach ( $chats as $chat ) {
            $unread = LSC_DB::count_unread_for_chat( (int) $chat->id );
            $data['chats'][] = [
                'id'            => (int) $chat->id,
                'visitor_name'  => esc_html( $chat->visitor_name ?: __( 'Visitor', 'live-support-chat' ) ),
                'visitor_email' => esc_html( $chat->visitor_email ),
                'status'        => $chat->status,
                'updated_at'    => mysql2date( 'd M H:i', $chat->updated_at ),
                'unread'        => $unread,
            ];
        }

        // If a specific chat is active, return its new messages.
        if ( $chat_id > 0 ) {
            $messages = LSC_DB::get_messages( $chat_id, $since_id );
            foreach ( $messages as $msg ) {
                $data['messages'][] = [
                    'id'      => (int) $msg->id,
                    'sender'  => $msg->sender,
                    'content' => wp_kses_post( $msg->content ),
                    'time'    => mysql2date( 'H:i', $msg->created_at ),
                ];
            }
            LSC_DB::mark_messages_read( $chat_id );
        }

        $this->send_success( $data );
    }

    /* ------------------------------------------------------------------
     * Chatter: reply to a chat
     * ------------------------------------------------------------------ */

    public function chatter_reply() {
        $this->verify_nonce( 'lsc_chatter_nonce' );
        $this->require_capability( 'lsc_reply_chats' );

        $chat_id = isset( $_POST['chat_id'] ) ? (int) $_POST['chat_id'] : 0;
        $message = isset( $_POST['message'] ) ? sanitize_textarea_field( wp_unslash( $_POST['message'] ) ) : '';

        if ( ! $chat_id || empty( $message ) ) {
            $this->send_error( __( 'Invalid data.', 'live-support-chat' ) );
        }

        $chat = LSC_DB::get_chat( $chat_id );
        if ( ! $chat || 'closed' === $chat->status ) {
            $this->send_error( __( 'Chat not found or closed.', 'live-support-chat' ) );
        }

        $msg_id = LSC_DB::add_message( $chat_id, 'chatter', $message );
        if ( ! $msg_id ) {
            $this->send_error( __( 'Could not save reply.', 'live-support-chat' ) );
        }

        $this->send_success( [ 'msg_id' => $msg_id ] );
    }

    /* ------------------------------------------------------------------
     * Close a chat
     * ------------------------------------------------------------------ */

    public function close_chat() {
        $this->verify_nonce( 'lsc_chatter_nonce' );
        $this->require_capability( 'lsc_reply_chats' );

        $chat_id = isset( $_POST['chat_id'] ) ? (int) $_POST['chat_id'] : 0;
        if ( ! $chat_id ) {
            $this->send_error( __( 'Invalid chat ID.', 'live-support-chat' ) );
        }

        LSC_DB::update_chat_status( $chat_id, 'closed' );
        $this->send_success();
    }

    /* ------------------------------------------------------------------
     * Mark messages as read
     * ------------------------------------------------------------------ */

    public function mark_read() {
        $this->verify_nonce( 'lsc_chatter_nonce' );
        $this->require_capability( 'lsc_view_chats' );

        $chat_id = isset( $_POST['chat_id'] ) ? (int) $_POST['chat_id'] : 0;
        LSC_DB::mark_messages_read( $chat_id );
        $this->send_success();
    }

    /* ------------------------------------------------------------------
     * Admin: toggle online/offline
     * ------------------------------------------------------------------ */

    public function toggle_status() {
        $this->verify_nonce( 'lsc_admin_nonce' );
        $this->require_capability( 'lsc_manage_chat' );

        $status = isset( $_POST['status'] ) ? sanitize_text_field( wp_unslash( $_POST['status'] ) ) : '';
        if ( ! in_array( $status, [ 'online', 'offline' ], true ) ) {
            $this->send_error( __( 'Invalid status.', 'live-support-chat' ) );
        }

        update_option( 'lsc_chat_status', $status );
        $this->send_success( [ 'status' => $status ] );
    }

    /* ------------------------------------------------------------------
     * Admin: delete chat
     * ------------------------------------------------------------------ */

    public function delete_chat() {
        $this->verify_nonce( 'lsc_admin_nonce' );
        $this->require_capability( 'lsc_manage_chat' );

        $chat_id = isset( $_POST['chat_id'] ) ? (int) $_POST['chat_id'] : 0;
        if ( ! $chat_id ) {
            $this->send_error( __( 'Invalid chat ID.', 'live-support-chat' ) );
        }

        LSC_DB::delete_chat( $chat_id );
        $this->send_success();
    }
}
