<?php
require_once __DIR__ . '/../config/db_config.php';

class Order {
    private $conn;
    private $table = 'orders';
    private $items_table = 'order_items';
    private $transactions_table = 'transactions';

    // Order properties
    public $order_id;
    public $order_code;
    public $user_id;
    public $name;
    public $email;
    public $phone;
    public $address;
    public $total_amount;
    public $status;
    public $payment_method;
    public $shipping_label; // Metode pengiriman (JNE, gojek, dll)
    public $resi; // Nomor resi pengiriman (hanya untuk JNE)
    public $midtrans_order_id;
    public $created_at;
    public $updated_at;
    public $items = [];

    /**
     * Constructor with DB connection
     */
    public function __construct() {
        $this->conn = getDbConnection();
    }

    /**
     * Check if database connection is available
     * 
     * @return boolean True if connection exists, false otherwise
     */
    private function checkConnection() {
        if ($this->conn === null) {
            error_log("Database connection failed in Order model");
            return false;
        }
        return true;
    }

    /**
     * Generate unique order code
     */
    public function generateOrderCode() {
        $prefix = 'BA';
        $date = date('Ymd');
        $random = strtoupper(substr(md5(uniqid(mt_rand(), true)), 0, 4));
        return $prefix . $date . $random;
    }

    /**
     * Create a new order
     */
    public function create() {
        if (!$this->checkConnection()) {
            return false;
        }

        // Begin transaction
        $this->conn->beginTransaction();
        
        try {
            // order_code dan midtrans_order_id sudah di-set dari luar (ORDER-...)
            
            // Insert order header
            $query = "INSERT INTO " . $this->table . " 
                    (order_code, user_id, name, email, phone, address, total_amount, status, payment_method, shipping_label, resi, midtrans_order_id) 
                    VALUES 
                    (:order_code, :user_id, :name, :email, :phone, :address, :total_amount, :status, :payment_method, :shipping_label, :resi, :midtrans_order_id)";
            
            $stmt = $this->conn->prepare($query);
            
            // Sanitize input
            $this->name = htmlspecialchars(strip_tags($this->name));
            $this->email = htmlspecialchars(strip_tags($this->email));
            $this->phone = htmlspecialchars(strip_tags($this->phone));
            $this->address = htmlspecialchars(strip_tags($this->address));
            
            // Set defaults
            $status = $this->status ?? 'pending';
            $payment_method = $this->payment_method ?? null;
            $shipping_label = $this->shipping_label ?? null;
            $resi = $this->resi ?? null;
            
            // Bind parameters
            $stmt->bindParam(':order_code', $this->order_code);
            $stmt->bindParam(':user_id', $this->user_id);
            $stmt->bindParam(':name', $this->name);
            $stmt->bindParam(':email', $this->email);
            $stmt->bindParam(':phone', $this->phone);
            $stmt->bindParam(':address', $this->address);
            $stmt->bindParam(':total_amount', $this->total_amount);
            $stmt->bindParam(':status', $status);
            $stmt->bindParam(':payment_method', $payment_method);
            $stmt->bindParam(':shipping_label', $shipping_label);
            $stmt->bindParam(':resi', $resi);
            $stmt->bindParam(':midtrans_order_id', $this->midtrans_order_id);
            
            $stmt->execute();
            
            // Get the new order ID
            $this->order_id = $this->conn->lastInsertId();
            
            // Insert order items if there are any
            if (!empty($this->items)) {
                $this->insertOrderItems();
            }
            
            // Commit transaction
            $this->conn->commit();
            return true;
            
        } catch (Exception $e) {
            // Rollback on failure
            $this->conn->rollBack();
            // Log error detail dari PDO
            $errorInfo = isset($stmt) ? $stmt->errorInfo() : [];
            $logMsg = "Error creating order: " . $e->getMessage() . ", PDO errorInfo: " . json_encode($errorInfo);
            error_log($logMsg);
            file_put_contents(__DIR__ . '/../payment_process.log', date('Y-m-d H:i:s') . " - " . $logMsg . "\n", FILE_APPEND);
            return false;
        }
    }
    
    /**
     * Insert order items
     */
    private function insertOrderItems() {
        if (!$this->checkConnection()) {
            return false;
        }

        try {
            $query = "INSERT INTO " . $this->items_table . " 
                    (order_id, product_id, product_name, product_price, quantity, subtotal, kode_pesanan) 
                    VALUES 
                    (:order_id, :product_id, :product_name, :product_price, :quantity, :subtotal, :kode_pesanan)";
            
            $stmt = $this->conn->prepare($query);
            
            foreach ($this->items as $item) {
                $stmt->bindParam(':order_id', $this->order_id);
                $stmt->bindParam(':product_id', $item['product_id']);
                $stmt->bindParam(':product_name', $item['product_name']);
                $stmt->bindParam(':product_price', $item['product_price']);
                $stmt->bindParam(':quantity', $item['quantity']);
                $stmt->bindParam(':subtotal', $item['subtotal']);
                $stmt->bindParam(':kode_pesanan', $this->order_code);
                $stmt->execute();
            }
            
            return true;
        } catch (PDOException $e) {
            error_log("Error inserting order items: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Get order by ID with its items
     */
    public function getOrderById($id) {
        if (!$this->checkConnection()) {
            return false;
        }

        try {
            $query = "SELECT * FROM " . $this->table . " WHERE order_id = :id LIMIT 1";
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':id', $id);
            $stmt->execute();
            
            $order = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if ($order) {
                // Set properties
                $this->order_id = $order['order_id'];
                $this->order_code = $order['order_code'];
                $this->user_id = $order['user_id'];
                $this->name = $order['name'];
                $this->email = $order['email'];
                $this->phone = $order['phone'];
                $this->address = $order['address'];
                $this->total_amount = $order['total_amount'];
                $this->status = $order['status'];
                $this->payment_method = $order['payment_method'];
                $this->shipping_label = $order['shipping_label'] ?? null;
                $this->resi = $order['resi'] ?? null;
                $this->midtrans_order_id = $order['midtrans_order_id'];
                $this->created_at = $order['created_at'];
                $this->updated_at = $order['updated_at'];
                
                // Get order items
                $this->getOrderItems();
                
                return true;
            }
            
            return false;
        } catch (PDOException $e) {
            error_log("Error getting order by ID: " . $e->getMessage());
            return false;
        }
    }

    public function getOrderByOrderCode($order_code) {
        if (!$this->checkConnection()) {
            return false;
        }
    
        try {
            $query = "SELECT * FROM {$this->table} WHERE order_code = :order_code LIMIT 1";
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':order_code', $order_code, PDO::PARAM_STR);
            $stmt->execute();
    
            $order = $stmt->fetch(PDO::FETCH_ASSOC);
    
            if ($order) {
                // Set properti objek
                foreach ($order as $key => $value) {
                    if (property_exists($this, $key)) {
                        $this->$key = $value;
                    }
                }
    
                // Ambil detail item pesanan jika method tersedia
                if (method_exists($this, 'getOrderItems')) {
                    $this->getOrderItems();
                }
    
                return true;
            }
    
            return false;
    
        } catch (PDOException $e) {
            error_log("Error getting order by order_code: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Get order by Midtrans order ID
     */
    public function getOrderByMidtransOrderId($midtrans_order_id) {
        if (!$this->checkConnection()) {
            return false;
        }

        try {
            $query = "SELECT * FROM " . $this->table . " WHERE midtrans_order_id = :midtrans_order_id LIMIT 1";
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':midtrans_order_id', $midtrans_order_id);
            $stmt->execute();
            
            $order = $stmt->fetch(PDO::FETCH_OBJ);

            if ($order) {
                $status = $order->status; // karena sudah object
                return $order;
            } else {
                return false;
            }
        } catch (PDOException $e) {
            error_log("Error getting order by Midtrans order ID: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Get items for current order
     */
    private function getOrderItems() {
        if (!$this->checkConnection()) {
            $this->items = [];
            return;
        }

        try {
            $query = "SELECT * FROM " . $this->items_table . " WHERE order_id = :order_id";
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':order_id', $this->order_id);
            $stmt->execute();
            
            $this->items = $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            error_log("Error getting order items: " . $e->getMessage());
            $this->items = [];
        }
    }
    
    /**
     * Update order status
     */
    public function updateStatus($status) {
        if (!$this->checkConnection()) {
            return false;
        }

        try {
            $query = "UPDATE " . $this->table . " SET status = :status WHERE order_id = :id";
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':status', $status);
            $stmt->bindParam(':id', $this->order_id);
            
            if ($stmt->execute()) {
                $this->status = $status;
                return true;
            }
            
            return false;
        } catch (PDOException $e) {
            error_log("Error updating order status: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Record a transaction for this order
     */
    public function recordTransaction($transaction_data) {
        if (!$this->checkConnection()) {
            return false;
        }

        try {
            $query = "INSERT INTO " . $this->transactions_table . " 
                    (order_id, payment_type, transaction_time, amount, 
                    midtrans_transaction_id, midtrans_transaction_status, midtrans_payment_type, additional_info) 
                    VALUES 
                    (:order_id, :payment_type, :transaction_time, :amount, 
                    :midtrans_transaction_id, :midtrans_transaction_status, :midtrans_payment_type, :additional_info)";
            
            $stmt = $this->conn->prepare($query);
            
            // Prepare data
            $transaction_time = isset($transaction_data['transaction_time']) 
                ? date('Y-m-d H:i:s', strtotime($transaction_data['transaction_time'])) 
                : date('Y-m-d H:i:s');
            
            $additional_info = isset($transaction_data['additional_info']) 
                ? json_encode($transaction_data['additional_info']) 
                : null;
            
            // Bind parameters
            $stmt->bindParam(':order_id', $this->order_id);
            $stmt->bindParam(':payment_type', $transaction_data['payment_type']);
            $stmt->bindParam(':transaction_time', $transaction_time);
            $stmt->bindParam(':amount', $transaction_data['amount']);
            $stmt->bindParam(':midtrans_transaction_id', $transaction_data['midtrans_transaction_id']);
            $stmt->bindParam(':midtrans_transaction_status', $transaction_data['midtrans_transaction_status']);
            $stmt->bindParam(':midtrans_payment_type', $transaction_data['midtrans_payment_type']);
            $stmt->bindParam(':additional_info', $additional_info);
            
            if ($stmt->execute()) {
                return $this->conn->lastInsertId();
            }
            
            return false;
        } catch (PDOException $e) {
            error_log("Error recording transaction: " . $e->getMessage());
            return false;
        }
    }
} 