<?php
if ( ! defined( 'ABSPATH' ) ) exit;

class ROS_Ajax {

    const COOKIE_PREFIX = 'ros_table_';

    public function __construct() {
        $actions = [
            'ros_get_menu'            => 'get_menu',
            'ros_get_tables'          => 'get_tables',
            'ros_place_order'         => 'place_order',
            'ros_get_table_status'    => 'get_table_status',
            'ros_check_table'         => 'check_table',
            'ros_customer_close'      => 'customer_close',
            'ros_kitchen_orders'      => 'kitchen_orders',
            'ros_update_status'       => 'update_status',
            'ros_kitchen_close_table' => 'kitchen_close_table',
            'ros_get_receipt'         => 'get_receipt',
            'ros_get_receipts'        => 'get_receipts',
            'ros_get_settings'        => 'get_settings',
            'ros_add_reservation'     => 'add_reservation',
            'ros_stripe_intent'       => 'stripe_create_intent',
            'ros_stripe_confirm'      => 'stripe_confirm',
            'ros_get_payment_config'  => 'get_payment_config',
            'ros_release_reservation' => 'release_reservation',
            'ros_get_reservations'    => 'get_reservations',
        ];
        foreach ( $actions as $action => $method ) {
            add_action( 'wp_ajax_' . $action,        [ $this, $method ] );
            add_action( 'wp_ajax_nopriv_' . $action, [ $this, $method ] );
        }
    }

    private function json( $data ) { wp_send_json( $data ); exit; }

    private function get_cookie( $table_id ) {
        $name = self::COOKIE_PREFIX . intval( $table_id );
        if ( empty( $_COOKIE[ $name ] ) ) return null;
        $parts = explode( ':', $_COOKIE[ $name ], 2 );
        if ( count( $parts ) !== 2 ) return null;
        return [ 'table_session' => $parts[0], 'session_key' => $parts[1] ];
    }

    private function set_cookie( $table_id, $table_session, $session_key ) {
        $name  = self::COOKIE_PREFIX . intval( $table_id );
        $value = $table_session . ':' . $session_key;
        $ttl   = time() + 8 * 3600;
        if ( PHP_VERSION_ID >= 70300 ) {
            setcookie( $name, $value, [ 'expires' => $ttl, 'path' => '/', 'samesite' => 'Lax' ] );
        } else {
            setcookie( $name, $value, $ttl, '/' );
        }
    }

    private function clear_cookie( $table_id ) {
        $name = self::COOKIE_PREFIX . intval( $table_id );
        setcookie( $name, '', time() - 3600, '/' );
        unset( $_COOKIE[ $name ] );
    }

    public function get_settings() {
        $this->json( [ 'success' => true, 'data' => ROS_DB::get_all_settings() ] );
    }

    public function get_tables() {
        $tables = ROS_DB::get_tables();
        foreach ( $tables as &$t ) {
            $active = ROS_DB::get_active_orders_for_table( $t['id'] );
            $t['has_active_order'] = count( $active ) > 0;
            $t['order_count']      = count( $active );
            $t['my_table']         = false;
            $t['reservation']      = null;

            // Check for active reservation (only if no active orders)
            if ( count( $active ) === 0 ) {
                $res = ROS_DB::get_reservation_for_table( $t['id'] );
                if ( $res ) {
                    $t['reservation']      = $res;
                    $t['has_active_order'] = true; // treat as occupied for customer
                }
            }

            if ( $t['has_active_order'] && count( $active ) > 0 ) {
                $cookie  = $this->get_cookie( $t['id'] );
                $session = ROS_DB::get_active_session( $t['id'] );
                if ( $cookie && $session && $cookie['table_session'] === $session ) {
                    $t['my_table'] = true;
                }
            }
        }
        $this->json( [ 'success' => true, 'data' => $tables ] );
    }

    public function get_menu() {
        $categories = ROS_DB::get_categories();
        foreach ( $categories as &$cat ) {
            $cat['dishes'] = ROS_DB::get_dishes( $cat['id'] );
        }
        $this->json( [ 'success' => true, 'data' => $categories ] );
    }

    public function place_order() {
        global $wpdb;
        $table_id = intval( $_POST['table_id'] ?? 0 );
        $items    = json_decode( stripslashes( $_POST['items'] ?? '[]' ), true );
        $notes    = sanitize_textarea_field( $_POST['notes'] ?? '' );

        if ( ! $table_id || empty( $items ) ) {
            $this->json( [ 'success' => false, 'message' => 'Invalid order data.' ] );
        }

        $cookie           = $this->get_cookie( $table_id );
        $existing_session = ROS_DB::get_active_session( $table_id );
        $table_session    = ( $cookie && $existing_session && $cookie['table_session'] === $existing_session )
                          ? $existing_session
                          : wp_generate_password( 16, false );

        $session_key = wp_generate_password( 32, false );
        $total = 0;
        foreach ( $items as $item ) {
            $total += floatval( $item['price'] ) * intval( $item['qty'] );
        }

        $wpdb->insert( $wpdb->prefix . 'ros_orders', [
            'table_id'      => $table_id,
            'table_session' => $table_session,
            'session_key'   => $session_key,
            'status'        => 'pending',
            'total'         => $total,
            'notes'         => $notes,
        ] );
        $order_id = $wpdb->insert_id;

        foreach ( $items as $item ) {
            $qty   = intval( $item['qty'] );
            $price = floatval( $item['price'] );
            $wpdb->insert( $wpdb->prefix . 'ros_order_items', [
                'order_id'   => $order_id,
                'dish_id'    => intval( $item['id'] ),
                'dish_name'  => sanitize_text_field( $item['name'] ),
                'dish_price' => $price,
                'quantity'   => $qty,
                'subtotal'   => $price * $qty,
            ] );
        }

        $wpdb->update( $wpdb->prefix . 'ros_tables', [ 'status' => 'occupied' ], [ 'id' => $table_id ] );
        $this->set_cookie( $table_id, $table_session, $session_key );

        $this->json( [ 'success' => true, 'order_id' => $order_id, 'session_key' => $session_key, 'table_session' => $table_session ] );
    }

    public function get_table_status() {
        global $wpdb;
        $table_id = intval( $_POST['table_id'] ?? 0 );
        if ( ! $table_id ) { $this->json( [ 'success' => false ] ); }

        $cookie = $this->get_cookie( $table_id );
        if ( ! $cookie ) { $this->json( [ 'success' => false, 'reason' => 'no_cookie' ] ); }

        $table_session = $cookie['table_session'];
        $orders = $wpdb->get_results( $wpdb->prepare(
            "SELECT id, status, total FROM {$wpdb->prefix}ros_orders
             WHERE table_id = %d AND table_session = %s AND status NOT IN ('closed')
             ORDER BY id ASC",
            $table_id, $table_session
        ), ARRAY_A );

        $priority    = [ 'pending' => 0, 'accepted' => 1, 'preparing' => 2, 'ready' => 3, 'customer_closed' => 4 ];
        $overall     = 'ready';
        $grand_total = 0;
        foreach ( $orders as $o ) {
            $grand_total += floatval( $o['total'] );
            if ( isset( $priority[ $o['status'] ] ) && $priority[ $o['status'] ] < $priority[ $overall ] ) {
                $overall = $o['status'];
            }
        }

        $this->json( [ 'success' => true, 'orders' => $orders, 'overall' => $overall, 'grand_total' => $grand_total, 'count' => count( $orders ) ] );
    }

    public function check_table() {
        global $wpdb;
        $table_id = intval( $_POST['table_id'] ?? 0 );
        if ( ! $table_id ) { $this->json( [ 'success' => false ] ); }

        $active = ROS_DB::get_active_orders_for_table( $table_id );

        if ( empty( $active ) ) {
            // Check for reservation — reserved tables are blocked for customers
            $res = ROS_DB::get_reservation_for_table( $table_id );
            if ( $res ) {
                $this->json( [ 'success' => true, 'result' => 'reserved', 'guest_name' => $res['guest_name'], 'arrival_time' => $res['arrival_time'], 'persons' => $res['persons'] ] );
            }
            $this->clear_cookie( $table_id );
            $this->json( [ 'success' => true, 'result' => 'free' ] );
        }

        $cookie  = $this->get_cookie( $table_id );
        $session = ROS_DB::get_active_session( $table_id );

        if ( $cookie && $session && $cookie['table_session'] === $session ) {
            $orders = $wpdb->get_results( $wpdb->prepare(
                "SELECT id, status, total FROM {$wpdb->prefix}ros_orders
                 WHERE table_id=%d AND table_session=%s AND status NOT IN ('closed') ORDER BY id ASC",
                $table_id, $session
            ), ARRAY_A );

            $priority    = [ 'pending' => 0, 'accepted' => 1, 'preparing' => 2, 'ready' => 3, 'customer_closed' => 4 ];
            $overall     = 'ready';
            $grand_total = 0;
            foreach ( $orders as $o ) {
                $grand_total += floatval( $o['total'] );
                if ( isset( $priority[ $o['status'] ] ) && $priority[ $o['status'] ] < $priority[ $overall ] ) {
                    $overall = $o['status'];
                }
            }

            $this->json( [
                'success'       => true,
                'result'        => 'mine',
                'session_key'   => $cookie['session_key'],
                'table_session' => $session,
                'overall'       => $overall,
                'grand_total'   => $grand_total,
                'order_count'   => count( $orders ),
            ] );
        }

        $this->json( [ 'success' => true, 'result' => 'occupied' ] );
    }

    public function customer_close() {
        global $wpdb;
        $table_id       = intval( $_POST['table_id'] ?? 0 );
        $payment_method = sanitize_text_field( $_POST['payment_method'] ?? 'unknown' );
        if ( ! $table_id ) { $this->json( [ 'success' => false ] ); }

        $cookie = $this->get_cookie( $table_id );
        if ( ! $cookie ) { $this->json( [ 'success' => false, 'reason' => 'no_session' ] ); }

        // Mark all session orders as customer_closed, store chosen payment method
        $wpdb->query( $wpdb->prepare(
            "UPDATE {$wpdb->prefix}ros_orders
             SET status='customer_closed', payment_method=%s
             WHERE table_id=%d AND table_session=%s AND status NOT IN ('closed')",
            $payment_method, $table_id, $cookie['table_session']
        ) );

        $this->clear_cookie( $table_id );
        $this->json( [ 'success' => true ] );
    }

    public function kitchen_orders() {
        global $wpdb;
        $orders = $wpdb->get_results(
            "SELECT o.*, t.name as table_name FROM {$wpdb->prefix}ros_orders o
             LEFT JOIN {$wpdb->prefix}ros_tables t ON t.id = o.table_id
             WHERE o.status NOT IN ('closed')
             ORDER BY o.table_id ASC, o.id ASC",
            ARRAY_A
        );
        foreach ( $orders as &$order ) {
            $order['items'] = ROS_DB::get_order_items( $order['id'] );
        }
        $tables = ROS_DB::get_tables();

        $table_summary = [];
        foreach ( $orders as $o ) {
            $tid = $o['table_id'];
            if ( ! isset( $table_summary[ $tid ] ) ) {
                $table_summary[ $tid ] = [ 'orders' => [], 'grand_total' => 0, 'customer_closed' => false, 'table_session' => $o['table_session'] ];
            }
            $table_summary[ $tid ]['orders'][]    = $o;
            $table_summary[ $tid ]['grand_total'] += floatval( $o['total'] );
            if ( $o['status'] === 'customer_closed' ) {
                $table_summary[ $tid ]['customer_closed'] = true;
            }
        }

        $this->json( [ 'success' => true, 'orders' => $orders, 'tables' => $tables, 'table_summary' => $table_summary ] );
    }

    public function update_status() {
        global $wpdb;
        $order_id   = intval( $_POST['order_id'] ?? 0 );
        $new_status = sanitize_text_field( $_POST['status'] ?? '' );
        $allowed    = [ 'accepted', 'preparing', 'ready' ];

        if ( ! $order_id )                        { $this->json( [ 'success' => false, 'message' => 'No order ID.' ] ); }
        if ( ! in_array( $new_status, $allowed ) ) { $this->json( [ 'success' => false, 'message' => 'Invalid status.' ] ); }

        $order = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}ros_orders WHERE id=%d", $order_id ), ARRAY_A );
        if ( ! $order ) { $this->json( [ 'success' => false, 'message' => 'Order not found.' ] ); }

        $wpdb->update( $wpdb->prefix . 'ros_orders', [ 'status' => $new_status ], [ 'id' => $order_id ] );
        $this->json( [ 'success' => true ] );
    }

    public function kitchen_close_table() {
        global $wpdb;
        $table_id       = intval( $_POST['table_id'] ?? 0 );
        $payment_method = sanitize_text_field( $_POST['payment_method'] ?? 'cash' );
        if ( ! $table_id ) { $this->json( [ 'success' => false ] ); }

        // Get the current session + table name before closing
        $session = $wpdb->get_var( $wpdb->prepare(
            "SELECT table_session FROM {$wpdb->prefix}ros_orders WHERE table_id=%d AND status NOT IN ('closed') ORDER BY id ASC LIMIT 1",
            $table_id
        ) );
        $table_name = $wpdb->get_var( $wpdb->prepare( "SELECT name FROM {$wpdb->prefix}ros_tables WHERE id=%d", $table_id ) );

        // Get all orders for this session to build receipt data
        $session_orders = [];
        $grand_total    = 0;
        $order_ids      = [];
        $all_items      = [];
        if ( $session ) {
            $session_orders = $wpdb->get_results( $wpdb->prepare(
                "SELECT * FROM {$wpdb->prefix}ros_orders WHERE table_id=%d AND table_session=%s AND status NOT IN ('closed')",
                $table_id, $session
            ), ARRAY_A );
            foreach ( $session_orders as $o ) {
                $order_ids[] = $o['id'];
                $grand_total += floatval( $o['total'] );
                $items = ROS_DB::get_order_items( $o['id'] );
                foreach ( $items as $item ) { $all_items[] = $item; }
            }
        }

        // Close all orders
        $wpdb->query( $wpdb->prepare(
            "UPDATE {$wpdb->prefix}ros_orders SET status='closed', paid_at=%s, payment_method=%s
             WHERE table_id=%d AND status NOT IN ('closed')",
            current_time( 'mysql' ), $payment_method, $table_id
        ) );
        $wpdb->update( $wpdb->prefix . 'ros_tables', [ 'status' => 'free' ], [ 'id' => $table_id ] );

        // Save receipt to archive
        $receipt_data = [
            'table_id'       => $table_id,
            'table_name'     => $table_name,
            'table_session'  => $session,
            'payment_method' => $payment_method,
            'grand_total'    => $grand_total,
            'orders'         => $session_orders,
            'items'          => $all_items,
            'settings'       => ROS_DB::get_all_settings(),
            'closed_at'      => current_time( 'mysql' ),
        ];

        $receipt_id = ROS_DB::save_receipt(
            $table_id, $table_name, $session,
            $payment_method, $grand_total,
            implode( ',', $order_ids ),
            $receipt_data
        );

        $this->json( [ 'success' => true, 'receipt_id' => $receipt_id, 'receipt_data' => $receipt_data ] );
    }

    /**
     * Get receipt data for a specific table session (current open orders only).
     * Used by kitchen print button before payment.
     */
    public function get_receipts() {
        $receipts = ROS_DB::get_receipts( 200 );
        $this->json( [ 'success' => true, 'receipts' => $receipts ] );
    }

    public function get_receipt() {
        global $wpdb;
        $table_id = intval( $_POST['table_id'] ?? 0 );
        if ( ! $table_id ) { $this->json( [ 'success' => false ] ); }

        // Only get the CURRENT active session orders
        $session = $wpdb->get_var( $wpdb->prepare(
            "SELECT table_session FROM {$wpdb->prefix}ros_orders
             WHERE table_id=%d AND status NOT IN ('closed')
             ORDER BY id ASC LIMIT 1",
            $table_id
        ) );

        if ( ! $session ) {
            // Fallback: get latest closed session
            $session = $wpdb->get_var( $wpdb->prepare(
                "SELECT table_session FROM {$wpdb->prefix}ros_orders
                 WHERE table_id=%d ORDER BY id DESC LIMIT 1",
                $table_id
            ) );
        }

        $orders = $wpdb->get_results( $wpdb->prepare(
            "SELECT o.*, t.name as table_name FROM {$wpdb->prefix}ros_orders o
             LEFT JOIN {$wpdb->prefix}ros_tables t ON t.id = o.table_id
             WHERE o.table_id=%d AND o.table_session=%s
             ORDER BY o.id ASC",
            $table_id, $session
        ), ARRAY_A );

        $all_items   = [];
        $grand_total = 0;
        foreach ( $orders as $o ) {
            $items = ROS_DB::get_order_items( $o['id'] );
            foreach ( $items as $item ) { $all_items[] = $item; }
            $grand_total += floatval( $o['total'] );
        }

        $this->json( [
            'success'     => true,
            'orders'      => $orders,
            'items'       => $all_items,
            'grand_total' => $grand_total,
            'table_name'  => $orders[0]['table_name'] ?? 'Tafel',
            'settings'    => ROS_DB::get_all_settings(),
        ] );
    }
    /* ══════════════════════════════
       RESERVATIONS
       ══════════════════════════════ */

    public function add_reservation() {
        global $wpdb;
        $table_id    = intval( $_POST['table_id'] ?? 0 );
        $guest_name  = sanitize_text_field( $_POST['guest_name'] ?? '' );
        $arrival     = sanitize_text_field( $_POST['arrival_time'] ?? '' );
        $persons     = intval( $_POST['persons'] ?? 1 );
        $notes       = sanitize_textarea_field( $_POST['notes'] ?? '' );

        if ( ! $table_id || ! $guest_name || ! $arrival ) {
            $this->json( [ 'success' => false, 'message' => 'Vul alle verplichte velden in.' ] );
        }

        // Check if table already has an active order or reservation
        $active_orders = ROS_DB::get_active_orders_for_table( $table_id );
        if ( ! empty( $active_orders ) ) {
            $this->json( [ 'success' => false, 'message' => 'Tafel heeft al een actieve order.' ] );
        }

        // Release any previous reservation for this table first
        $wpdb->update( $wpdb->prefix . 'ros_reservations',
            [ 'status' => 'released' ],
            [ 'table_id' => $table_id, 'status' => 'active' ]
        );

        $wpdb->insert( $wpdb->prefix . 'ros_reservations', [
            'table_id'    => $table_id,
            'guest_name'  => $guest_name,
            'arrival_time'=> $arrival,
            'persons'     => $persons,
            'notes'       => $notes,
            'status'      => 'active',
        ] );

        // Mark table as occupied (reserved)
        $wpdb->update( $wpdb->prefix . 'ros_tables', [ 'status' => 'occupied' ], [ 'id' => $table_id ] );

        $this->json( [ 'success' => true, 'id' => $wpdb->insert_id ] );
    }

    public function release_reservation() {
        global $wpdb;
        $reservation_id = intval( $_POST['reservation_id'] ?? 0 );
        $table_id       = intval( $_POST['table_id'] ?? 0 );

        if ( $reservation_id ) {
            $res = $wpdb->get_row( $wpdb->prepare(
                "SELECT * FROM {$wpdb->prefix}ros_reservations WHERE id = %d", $reservation_id
            ), ARRAY_A );
            if ( $res ) {
                $wpdb->update( $wpdb->prefix . 'ros_reservations', [ 'status' => 'released' ], [ 'id' => $reservation_id ] );
                $table_id = $res['table_id'];
            }
        } elseif ( $table_id ) {
            $wpdb->update( $wpdb->prefix . 'ros_reservations',
                [ 'status' => 'released' ],
                [ 'table_id' => $table_id, 'status' => 'active' ]
            );
        }

        // Free the table only if no active orders
        if ( $table_id ) {
            $active = ROS_DB::get_active_orders_for_table( $table_id );
            if ( empty( $active ) ) {
                $wpdb->update( $wpdb->prefix . 'ros_tables', [ 'status' => 'free' ], [ 'id' => $table_id ] );
            }
        }

        $this->json( [ 'success' => true ] );
    }

    public function get_reservations() {
        $reservations = ROS_DB::get_active_reservations();
        $this->json( [ 'success' => true, 'reservations' => $reservations ] );
    }

    /* ══════════════════════════════
       STRIPE & PAYMENT CONFIG
       ══════════════════════════════ */

    public function get_payment_config() {
        $s              = ROS_DB::get_all_settings();
        $stripe_enabled = ( $s['stripe_enabled'] ?? '0' ) === '1' && ! empty( $s['stripe_pk'] );
        $this->json( [
            'success'        => true,
            'stripe_enabled' => $stripe_enabled,
            'stripe_pk'      => $stripe_enabled ? ( $s['stripe_pk'] ?? '' ) : '',
            'currency'       => strtolower( $s['currency_code'] ?? 'usd' ),
        ] );
    }

    public function stripe_create_intent() {
        $s = ROS_DB::get_all_settings();
        if ( empty( $s['stripe_sk'] ) ) {
            $this->json( [ 'success' => false, 'message' => 'Stripe niet geconfigureerd.' ] );
        }

        $table_id = intval( $_POST['table_id'] ?? 0 );
        $amount   = intval( round( floatval( $_POST['amount'] ?? 0 ) * 100 ) ); // cents

        if ( $amount < 50 ) {
            $this->json( [ 'success' => false, 'message' => 'Bedrag te laag.' ] );
        }

        $currency = strtolower( $s['currency_code'] ?? 'usd' );

        // Call Stripe API via wp_remote_post
        $response = wp_remote_post( 'https://api.stripe.com/v1/payment_intents', [
            'headers' => [
                'Authorization' => 'Bearer ' . $s['stripe_sk'],
                'Content-Type'  => 'application/x-www-form-urlencoded',
            ],
            'body' => [
                'amount'                    => $amount,
                'currency'                  => $currency,
                'payment_method_types[]'    => 'card',
                'metadata[table_id]'        => $table_id,
                'metadata[restaurant]'      => $s['restaurant_name'] ?? 'Restaurant',
            ],
            'timeout' => 15,
        ] );

        if ( is_wp_error( $response ) ) {
            $this->json( [ 'success' => false, 'message' => 'Verbindingsfout: ' . $response->get_error_message() ] );
        }

        $body = json_decode( wp_remote_retrieve_body( $response ), true );

        if ( empty( $body['client_secret'] ) ) {
            $this->json( [ 'success' => false, 'message' => 'Stripe fout: ' . ( $body['error']['message'] ?? 'Onbekend' ) ] );
        }

        $this->json( [
            'success'       => true,
            'client_secret' => $body['client_secret'],
            'intent_id'     => $body['id'],
        ] );
    }

    public function stripe_confirm() {
        global $wpdb;
        $table_id  = intval( $_POST['table_id'] ?? 0 );
        $intent_id = sanitize_text_field( $_POST['intent_id'] ?? '' );

        if ( ! $table_id ) { $this->json( [ 'success' => false ] ); }

        // Mark session as customer_closed with stripe payment method
        $cookie = $this->get_cookie( $table_id );
        if ( $cookie ) {
            $wpdb->query( $wpdb->prepare(
                "UPDATE {$wpdb->prefix}ros_orders SET status='customer_closed'
                 WHERE table_id=%d AND table_session=%s AND status NOT IN ('closed')",
                $table_id, $cookie['table_session']
            ) );
            $this->clear_cookie( $table_id );
        }

        // Store payment method preference as stripe on orders
        $wpdb->query( $wpdb->prepare(
            "UPDATE {$wpdb->prefix}ros_orders SET payment_method='stripe'
             WHERE table_id=%d AND status='customer_closed'",
            $table_id
        ) );

        $this->json( [ 'success' => true ] );
    }

}
