<?php

namespace Booktics\Cart;

use Booktics\Abstracts\Booktics_Database;

/**
 * Class Cart_Manager
 * Manages shopping cart operations including adding items, updating quantities, and calculating totals
 *
 * @package Booktics\Cart
 */
class Cart_Manager {
    /**
     * @var Booktics_Database The database instance
     */
    protected $db;

    /**
     * @var string The carts table name
     */
    protected $carts_table;

    /**
     * @var string The cart items table name
     */
    protected $cart_items_table;

    /**
     * Initialize CartManager with database connection
     */
    public function __construct() {
        $this->db = new Booktics_Database();
        $this->carts_table = booktics_get_table_name( 'booktics_carts' );
        $this->cart_items_table = booktics_get_table_name( 'booktics_cart_items' );
    }

    /**
     * Add item to the cart for guest users
     *
     * @param array $item
     *
     * @return array
     */
    public function add_to_cart_guest( array $item ): array {
        return Cart_Session::add_item( $item );
    }

    /**
     * Add item to the cart for both guest and registered users
     *
     * @param array $params Cart item parameters
     *
     * @return array Added cart item
     */
    public function add_to_cart( array $params ): array {
        $user_id        = get_current_user_id();
        $params['uuid'] = wp_generate_uuid4();
        if ( $user_id ) {
            return $this->add_to_cart_user( $user_id, $params );
        }

        return $this->add_to_cart_guest( $params );
    }

    /**
     * Add item to the cart for registered users
     *
     * @param int $user_id
     * @param array $item
     *
     * @return array
     */
    public function add_to_cart_user( int $user_id, array $item ): array {
        $carts = $this->db->select(
            $this->carts_table, array(
				'user_id' => $user_id,
            )
        );

        if ( ! count( $carts ) ) {
            $uuid = wp_generate_uuid4();
            $this->db->insert_batch(
                $this->carts_table, array(
					array(
						'uuid'       => $uuid,
						'user_id'    => $user_id,
						'total'      => 0,
						'created_at' => current_time( 'mysql' ),
						'updated_at' => current_time( 'mysql' ),
					),
                )
            );

            $carts = $this->db->select(
                $this->carts_table, array(
					'user_id' => $user_id,
                )
            );
        }

        // Check if the service_id already exists in the cart items for this cart
        if ( count( $carts ) ) {
            $cart = $carts[0];
            $existing_items = $this->db->select(
                $this->cart_items_table,
                array(
                    'cart_id'    => $cart->id,
                    'service_id' => $item['service_id'],
                )
            );
            if ( ! empty( $existing_items ) ) {
                // Delete existing items with the same service_id for this cart
                foreach ( $existing_items as $existing_item ) {
                    $this->db->delete(
                        $this->cart_items_table,
                        array(
                            'id' => $existing_item->id,
                        )
                    );
                }
            }
        }
        $cart           = count( $carts ) ? $carts[0] : array();
        $cart_item_data = array(
            'uuid'                   => $item['uuid'],
            'cart_id'                => $cart->id,
            'team_member_id'         => $item['team_member_id'],
            'service_id'             => $item['service_id'],
            'date'                   => $item['date'],
            'start_time'             => $item['start_time'],
            'end_time'               => $item['end_time'],
            'price'                  => $item['price'] ?? 0,
            'subtotal'               => $item['subtotal'] ?? $item['price'],
            'total'                  => $item['total'] ?? $item['subtotal'],
            'additional_duration_id' => $item['additional_duration_id'] ?? '',
            'created_at'             => current_time( 'mysql' ),
            'updated_at'             => current_time( 'mysql' ),
        );

        $cart_item_data = apply_filters( 'booktics_pro_cart_db', $cart_item_data, $item );
        $this->db->insert_batch( $this->cart_items_table, array( $cart_item_data ) );
        if ( isset( $cart->id ) ) {
            $this->update_cart_total( $cart->id );
        }

        if ( isset( $cart_item_data['extra_services'] ) ) {
            $cart_item_data['extra_services'] = json_decode( $cart_item_data['extra_services'], true );
        }

        return $cart_item_data;
    }

    /**
     * Synchronize session cart items to a database
     *
     * @param int $user_id
     */
    public function sync_session_to_db( int $user_id ): void {
        $session_cart = Cart_Session::get();
        if ( empty( $session_cart['items'] ) ) {
            return;
        }

        foreach ( $session_cart['items'] as $item ) {
            $this->add_to_cart_user( $user_id, $item );
        }

        Cart_Session::clear();
    }

    /**
     * Update cart total based on items
     *
     * @param int $cart_id
     */
    protected function update_cart_total( int $cart_id ): void {
        $items = $this->db->select(
            $this->cart_items_table, array(
				'cart_id' => $cart_id,
            )
        );

        if ( empty( $items ) ) {
            $this->db->delete( $this->carts_table, array( 'id' => $cart_id ) );

            return;
        }

        $total = 0;
        foreach ( $items as $item ) {
            $total += (float) ( $item->total ?? $item->subtotal ?? 0 );
        }

        $this->db->update(
            $this->carts_table,
            array(
                'total'      => $total,
                'updated_at' => current_time( 'mysql' ),
            ),
            array( 'id' => $cart_id )
        );
    }

    /**
     * Get a cart and its items for a user
     *
     * @return array
     */
    public function get_cart(): array {
        $user_id = get_current_user_id();

        if ( ! $user_id ) {
            return Cart_Session::get();
        }

        $carts = $this->db->select(
            $this->carts_table, array(
				'user_id' => $user_id,
            )
        );
        $cart  = count( $carts ) ? $carts[0] : null;

        if ( ! $cart ) {
            return array( 'items' => array() );
        }

        $items = $this->db->select(
            $this->cart_items_table, array(
				'cart_id' => $cart->id,
            )
        );
        foreach ( $items as $i => $item ) {
            if ( isset( $item->extra_services ) ) {
                $item->extra_services = json_decode( $item->extra_services, true );
            }
        }

        return array_merge( (array) $cart, array( 'items' => $items ) );
    }

    /**
     * Remove item from the cart
     *
     * @param string|null $id
     */
    public function remove_cart_item( $id = null ): void {
        $user_id = get_current_user_id();
        if ( ! $user_id ) {
            if ( ! $id ) {
                Cart_Session::clear();
            } else {
                Cart_Session::delete_item( $id );
            }
        }

        $carts = $this->db->select(
            $this->carts_table, array(
				'user_id' => $user_id,
            )
        );

        $cart = count( $carts ) ? $carts[0] : null;

        if ( ! $cart ) {
            return;
        }

        $conditions = array( 'cart_id' => $cart->id );
        if ( ! empty( $id ) ) {
            $conditions['uuid'] = $id;
        }

        $this->db->delete( $this->cart_items_table, $conditions );

        $this->update_cart_total( $cart->id );
    }

    /**
     * Edit item in the cart
     *
     * @param string $uuid
     * @param array $new_data
     *
     * @return array Updated item data or empty array if item not found
     */
    public function edit_cart_item( string $uuid, array $new_data ): array {
        if ( ! is_user_logged_in() ) {
            Cart_Session::edit_item( $uuid, $new_data );
            $cart = Cart_Session::get();
            foreach ( $cart['items'] as $item ) {
                if ( $item['uuid'] === $uuid ) {
                    return $item;
                }
            }

            return array();
        }

        $user_id = get_current_user_id();
        $carts   = $this->db->select(
            $this->carts_table, array(
				'user_id' => $user_id,
            )
        );

        $cart = count( $carts ) ? $carts[0] : null;

        if ( ! $cart ) {
            return array();
        }

        $cart_item_data = array_merge( $new_data, array( 'updated_at' => current_time( 'mysql' ) ) );
        $cart_item_data = apply_filters( 'booktics_pro_cart_db', $cart_item_data, $new_data );
        $this->db->update(
            $this->cart_items_table, $cart_item_data,
            array(
                'cart_id' => $cart->id,
                'uuid'    => $uuid,
            )
        );

        $this->update_cart_total( $cart->id );

        $updated_item = $this->db->select(
            $this->cart_items_table, array(
				'cart_id' => $cart->id,
				'uuid'    => $uuid,
            )
        );

        foreach ( $updated_item as $i => $item ) {
            if ( isset( $item->extra_services ) ) {
                $item->extra_services = json_decode( $item->extra_services, true );
            }
        }

        return count( $updated_item ) ? (array) $updated_item[0] : array();
    }
}
