<?php
if (basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME'])) {
    die('No direct script access allowed');
}


function createOrder(int $user_id, string $province, string $city, string $address, array $cart_items, ?string $note, string $subtotal, string $initial_status = 'awaiting_online_payment', ?string $discount_code = null, ?string $discount_amount = '0.00', string $order_type = 'product', ?int $selected_user_card_id = null): array {
    $pdo = pdo();
    $full_address = "استان: {$province}, شهر: {$city}\n" . $address;
    
    $discount_amount_val = $discount_amount ?: '0.00';
    
    $total_partner_profit = '0.00';
    
    foreach ($cart_items as $item) {
        $item_profit = $item['pricing']['partner_profit'] ?? '0.00';
        $item_quantity = $item['quantity'] ?? '0';
        $total_partner_profit = bcadd($total_partner_profit, bcmul($item_profit, $item_quantity, BC_SCALE), BC_SCALE);
    }
    
    $shipping_fee = '-1.00';
    
    $total_amount = bcsub($subtotal, $discount_amount_val, BC_SCALE);

    if (bccomp($total_amount, '0', BC_SCALE) < 0) {
        $total_amount = '0.00';
    }
    
    try {
        $pdo->beginTransaction();
        $unavailable_products = [];
        $product_stock_info = [];
        $variation_stock_info = [];
        $stewards_to_notify = [];

        foreach ($cart_items as $item) {
            $product_id = $item['product_id'] ?? 0;
            $variation_id = $item['variation_id'] ?? 0;
            $item_name = $item['name'] ?? 'محصول ناشناخته';
            if ($product_id <= 0) continue;

            if ($variation_id > 0) {
                $stmt_check_var = $pdo->prepare("SELECT stock FROM product_variations WHERE id = ? AND product_id = ? FOR UPDATE");
                $stmt_check_var->execute([$variation_id, $product_id]);
                $variation = $stmt_check_var->fetch();
                
                if (!$variation) {
                    $unavailable_products[] = $item_name . " (ترکیب یافت نشد)";
                } elseif ($variation['stock'] !== null && bccomp((string)$variation['stock'], (string)$item['quantity'], 1) < 0) {
                    $unavailable_products[] = $item_name . " (موجودی: " . ($variation['stock'] ?? 0) . ")";
                }
                $variation_stock_info[$variation_id] = $variation;

            } else {
                $stmt_check_prod = $pdo->prepare("SELECT name, stock, steward_user_id FROM products WHERE id = ? AND is_active = TRUE FOR UPDATE");
                $stmt_check_prod->execute([$product_id]);
                $product = $stmt_check_prod->fetch();
                
                if (!$product) {
                    $unavailable_products[] = $item_name . " (یافت نشد)";
                } elseif ($product['stock'] !== null && bccomp((string)$product['stock'], (string)$item['quantity'], 1) < 0) {
                    $unavailable_products[] = $item_name . " (موجودی: " . ($product['stock'] ?? 0) . ")";
                }
                $product_stock_info[$product_id] = $product;
                
                if (!empty($product['steward_user_id'])) {
                    $stewards_to_notify[$product['steward_user_id']] = 1;
                }
            }

            if ($variation_id > 0 && !isset($product_stock_info[$product_id])) {
                $stmt_prod_steward = $pdo->prepare("SELECT steward_user_id FROM products WHERE id = ?");
                $stmt_prod_steward->execute([$product_id]);
                $steward_id = $stmt_prod_steward->fetchColumn();
                if ($steward_id) {
                    $stewards_to_notify[$steward_id] = 1;
                }
                $product_stock_info[$product_id] = ['steward_user_id' => $steward_id]; 
            }
        }
        
        if (!empty($unavailable_products)) {
            $pdo->rollBack();
            return ['success' => false, 'error' => 'out_of_stock', 'products' => $unavailable_products];
        }

        $order_stmt = $pdo->prepare(
            "INSERT INTO orders (user_id, subtotal_amount, total_amount, discount_code, discount_amount, shipping_fee, province, city, delivery_address, status, order_type, total_partner_profit, order_note, selected_user_card_id, created_at) 
             VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())"
        );
        $order_stmt->execute([
            $user_id, $subtotal, $total_amount, $discount_code, $discount_amount_val, 
            $shipping_fee, $province, $city, $full_address, $initial_status, 
            $order_type, 
            $total_partner_profit,
            $note,
            $selected_user_card_id
        ]);
        $order_id = $pdo->lastInsertId();

        $item_stmt = $pdo->prepare("INSERT INTO order_items (order_id, product_id, variation_id, quantity, price_per_unit, product_name, partner_profit) VALUES (?, ?, ?, ?, ?, ?, ?)");
        $stock_update_stmt_prod = $pdo->prepare("UPDATE products SET stock = stock - ? WHERE id = ? AND stock IS NOT NULL");
        $stock_update_stmt_var = $pdo->prepare("UPDATE product_variations SET stock = stock - ? WHERE id = ? AND stock IS NOT NULL");

        foreach ($cart_items as $item) {
            $product_id = $item['product_id'] ?? 0;
            $variation_id = $item['variation_id'] > 0 ? $item['variation_id'] : null;
            $quantity = $item['quantity'];
            
            $price_per_unit = $item['pricing']['final_price'] ?? '0.00';
            $partner_profit_per_unit = $item['pricing']['partner_profit'] ?? '0.00';
            $item_name = $item['name'] ?? 'محصول ناشناخته';

            $item_stmt->execute([
                $order_id, 
                $product_id, 
                $variation_id,
                $quantity, 
                $price_per_unit,
                $item_name,
                $partner_profit_per_unit
            ]);
            
            if ($variation_id) {
                $variation_info = $variation_stock_info[$variation_id] ?? null;
                if ($variation_info && $variation_info['stock'] !== null) {
                     $stock_update_stmt_var->execute([$quantity, $variation_id]);
                }
            } else {
                $product_info = $product_stock_info[$product_id] ?? null;
                if ($product_info && $product_info['stock'] !== null) {
                     $stock_update_stmt_prod->execute([$quantity, $product_id]);
                }
            }
        }
        
        if ($discount_code) {
            incrementDiscountUseCount($discount_code);
        }
        
        $pdo->commit();
        
        $steward_ids_array = array_keys($stewards_to_notify);
        return [
            'success' => true, 
            'order_id' => (int)$order_id, 
            'total_amount' => $total_amount,
            'stewards_to_notify' => $steward_ids_array
        ];
        
    } catch (Exception $e) {
        if ($pdo->inTransaction()) {
            $pdo->rollBack();
        }
        file_put_contents(ERROR_LOG_PATH, date('Y-m-d H:i:s') . " - Order Creation Error (User: {$user_id}): " . $e->getMessage() . "\n", FILE_APPEND);
        return ['success' => false, 'error' => 'exception', 'message' => 'خطا در ثبت سفارش: ' . $e->getMessage()];
    }
}

function createVerificationOrder(int $user_id, string $amount_toman, string $description): array {
    $pdo = pdo();
    $verification_amount = $amount_toman;
    $subtotal_amount = '0.00'; 
    $total_amount = $verification_amount;
    try {
        $pdo->beginTransaction();
        $order_stmt = $pdo->prepare(
            "INSERT INTO orders (user_id, subtotal_amount, total_amount, status, order_type, order_note, created_at) 
             VALUES (?, ?, ?, 'awaiting_online_payment', 'verification', ?, NOW())"
        );
        $order_stmt->execute([
            $user_id, $subtotal_amount, $total_amount, $description
         ]);
        $order_id = $pdo->lastInsertId();
        $pdo->commit();
        return ['success' => true, 'order_id' => (int)$order_id, 'total_amount' => $total_amount];
    } catch (Exception $e) {
        if ($pdo->inTransaction()) {
            $pdo->rollBack();
        }
        if (defined('ERROR_LOG_PATH')) { file_put_contents(ERROR_LOG_PATH, date('Y-m-d H:i:s') . " - Verification Order Creation Error (User: {$user_id}): " . $e->getMessage() . "\n", FILE_APPEND); }
        return ['success' => false, 'error' => 'exception', 'message' => 'خطا در ثبت سفارش احراز هویت: ' . $e->getMessage()];
    }
}

function createInvoiceOrder(int $user_id, string $amount_toman, string $description): array {
    $pdo = pdo();
    $total_amount = $amount_toman;
    $subtotal_amount = $amount_toman; 

    try {
        $pdo->beginTransaction();
        $order_stmt = $pdo->prepare(
            "INSERT INTO orders (user_id, subtotal_amount, total_amount, status, order_type, order_note, created_at) 
             VALUES (?, ?, ?, 'awaiting_online_payment', 'invoice', ?, NOW())"
        );
        $order_stmt->execute([
            $user_id, $subtotal_amount, $total_amount, $description
         ]);
         $order_id = $pdo->lastInsertId();
        $pdo->commit();
        return ['success' => true, 'order_id' => (int)$order_id, 'total_amount' => $total_amount];
    } catch (Exception $e) {
        if ($pdo->inTransaction()) {
            $pdo->rollBack();
        }
        if (defined('ERROR_LOG_PATH')) { file_put_contents(ERROR_LOG_PATH, date('Y-m-d H:i:s') . " - Invoice Order Creation Error (User: {$user_id}): " . $e->getMessage() . "\n", FILE_APPEND); }
        return ['success' => false, 'error' => 'exception', 'message' => 'خطا در ثبت فاکتور آزاد: ' . $e->getMessage()];
    }
}

function getOrderDetails(int $order_id): ?array {
    try {
          $stmt_order = pdo()->prepare("
           SELECT 
                o.*, 
                u.first_name, u.phone_number, u.telegram_user_id, u.bale_user_id, 
                u.telegram_chat_id, u.bale_chat_id, u.id as user_id, u.is_admin, u.referred_by_user_id,
                u.national_id_code,
                p.first_name AS partner_first_name,
                p.phone_number AS partner_phone_number,
                p.id AS partner_user_id
           FROM orders o 
            JOIN users u ON o.user_id = u.id 
            LEFT JOIN users p ON u.referred_by_user_id = p.id
            WHERE o.id = ?");
        $stmt_order->execute([$order_id]);
   
         $order = $stmt_order->fetch();

        if (!$order) return null;
        
        $stmt_items = pdo()->prepare("
            SELECT oi.*
            FROM order_items oi
            WHERE oi.order_id = ?
        ");
         $stmt_items->execute([$order_id]);
        $order['items'] = $stmt_items->fetchAll();
        return $order;
    } catch (PDOException $e) {
        file_put_contents(ERROR_LOG_PATH, date('Y-m-d H:i:s') . " - DB Error getting order details ({$order_id}): " . $e->getMessage() . "\n", FILE_APPEND);
         return null;
    }
}

function updateOrderStatus(int $order_id, string $new_status): bool {
    try {
        $stmt = pdo()->prepare("UPDATE orders SET status = ? WHERE id = ?");
       
        return $stmt->execute([$new_status, $order_id]);
    } catch (PDOException $e) {
        file_put_contents(ERROR_LOG_PATH, date('Y-m-d H:i:s') . " - DB Error updating order status for order {$order_id} to {$new_status}: " . $e->getMessage() . "\n", FILE_APPEND);
        return false;
    }
}

function setOrderTrackingCode(int $order_id, string $tracking_code): bool {
    try {
        $stmt = pdo()->prepare("UPDATE orders SET tracking_code = ?, status = 'shipped' WHERE id = ? AND status NOT IN ('completed', 'canceled', 'refunded')");
        
  return $stmt->execute([$tracking_code, $order_id]);
    } catch (PDOException $e) {
       file_put_contents(ERROR_LOG_PATH, date('Y-m-d H:i:s') . " - DB Error setting tracking code for order {$order_id}: " . $e->getMessage() . "\n", FILE_APPEND);
 
       return false;
    }
}

function getOrderOwner(int $order_id): ?array {
    try {
        $stmt = pdo()->prepare("SELECT u.id, u.telegram_chat_id, u.bale_chat_id, u.telegram_user_id, u.bale_user_id 
                                FROM orders o 
                                           JOIN users u ON o.user_id = u.id 
                                    WHERE o.id = ?");
  
           $stmt->execute([$order_id]);
        return $stmt->fetch() ?: null;

    } catch (PDOException $e) {
        file_put_contents(ERROR_LOG_PATH, date('Y-m-d H:i:s') . " - DB Error getting order owner for order {$order_id}: " . $e->getMessage() . "\n", FILE_APPEND);
        return null;
    }
}

function setOrderShippingFee(int $order_id, string $fee, ?string $note): bool {
    $pdo = pdo();
    try {
        $pdo->beginTransaction();
        
        $new_status = 'awaiting_shipping_fee';
        if (bccomp($fee, '0.00', BC_SCALE) == 0) {
            $new_status = 'processing';
        }

        $stmt_update = $pdo->prepare("UPDATE orders SET shipping_fee = ?, shipping_fee_note = ?, status = ? WHERE id = ?");
        $stmt_update->execute([$fee, $note, $new_status, $order_id]);
      
        $pdo->commit();
   
         return true;
    } catch (Exception $e) {

        if ($pdo->inTransaction()) {
             $pdo->rollBack();
        }
  
        file_put_contents(ERROR_LOG_PATH, date('Y-m-d H:i:s') . " - DB Error setting shipping fee for order {$order_id}: " . $e->getMessage() . "\n", FILE_APPEND);


        return false;

    }
}

function countOrdersByUser(int $user_id, string $type = 'product'): int {
    try {
       $stmt = pdo()->prepare("SELECT COUNT(*) FROM orders WHERE user_id = ? AND order_type = ?");
        
 
         $stmt->execute([$user_id, $type]);
         return (int)$stmt->fetchColumn();
   } catch (PDOException $e) {
        file_put_contents(ERROR_LOG_PATH, date('Y-m-d H:i:s') . " - DB Error counting user orders ({$user_id}): " . $e->getMessage() . "\n", FILE_APPEND);
        return 0;
    }
}

function getOrdersByUserPaginated(int $user_id, int $limit, int $offset, string $type = 'product'): array {
    try {
        $stmt = pdo()->prepare("SELECT * FROM orders WHERE user_id = :user_id AND order_type = :order_type ORDER BY created_at DESC LIMIT :limit OFFSET :offset");
        
        $stmt->bindValue(':user_id', $user_id, PDO::PARAM_INT);
        $stmt->bindValue(':order_type', $type, PDO::PARAM_STR);
        $stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
 
       $stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
        $stmt->execute();
           return $stmt->fetchAll();
    } catch (PDOException $e) {
   
         file_put_contents(ERROR_LOG_PATH, date('Y-m-d H:i:s') . " - DB Error getting user orders paginated ({$user_id}): " . $e->getMessage() . "\n", FILE_APPEND);
        return [];
    }
}


function countOrdersByFilter(string $status_filter = 'all', string $order_view_type = 'normal'): int {
    try {
       
        $sql = "SELECT COUNT(o.id) FROM orders o JOIN users u ON o.user_id = u.id WHERE (o.order_type = 'product' OR o.order_type = 'invoice')";
        
        $params = [];
        if (!empty($status_filter) && $status_filter !== 'all') {
         $sql .= " AND o.status = :status";
                   $params[':status'] = $status_filter;
        }

        if ($order_view_type === 'referral') {
            $sql .= " AND u.referred_by_user_id IS NOT NULL";
        } else {
            $sql .= " AND u.referred_by_user_id IS NULL";
        }

         $stmt = pdo()->prepare($sql);
  
   
       $stmt->execute($params);

        return (int)$stmt->fetchColumn();
    } catch (PDOException $e) {
        file_put_contents(ERROR_LOG_PATH, date('Y-m-d H:i:s') . " - DB Error counting orders by filter '{$status_filter}' / type '{$order_view_type}': " . $e->getMessage() . "\n", FILE_APPEND);
 
          
        return 0;
    }
}



function getOrdersByFilterPaginated(string $status_filter, int $limit, int $offset, string $order_view_type = 'normal'): array {
    try {
        
        $fields = "o.*, u.first_name";
        $sql = " FROM orders o JOIN users u ON o.user_id = u.id";
        $params = [];

        if ($order_view_type === 'referral') {
            $fields .= ", p.first_name AS partner_first_name";
            $sql .= " LEFT JOIN users p ON u.referred_by_user_id = p.id";
            $sql .= " WHERE (o.order_type = 'product' OR o.order_type = 'invoice') AND u.referred_by_user_id IS NOT NULL";
        } else {
            $sql .= " WHERE (o.order_type = 'product' OR o.order_type = 'invoice') AND u.referred_by_user_id IS NULL";
        }
        
        if (!empty($status_filter) && $status_filter !== 'all') {
             $sql .= " AND o.status = :status";
    
                     $params[':status'] = $status_filter;
             }
         
        $sql_final = "SELECT " . $fields . $sql . " ORDER BY o.created_at DESC LIMIT :limit OFFSET :offset";
        
         $stmt = pdo()->prepare($sql_final);
        
        if (isset($params[':status'])) {
         
           $stmt->bindValue(':status', $params[':status']);
        }
         $stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
        $stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
       
          $stmt->execute();
      
  return $stmt->fetchAll();
    } catch (PDOException $e) {
      file_put_contents(ERROR_LOG_PATH, date('Y-m-d H:i:s') . " - DB Error getting orders by filter paginated '{$status_filter}' / type '{$order_view_type}': " . $e->getMessage() . "\n", FILE_APPEND);
        return [];
    }
}

function updateOrderPaymentDetails(int $order_id, ?string $authority = null, ?string $ref_id = null, ?string $card_mask = null): bool {
  try {
        $params = [];
        $sql_parts = [];
        if ($authority !== null) {
            $sql_parts[] = "payment_authority = ?";
 
             $params[] = $authority;

      }
        if ($ref_id !== null) {
            $sql_parts[] = "payment_ref_id = ?";
            $params[] = $ref_id;
       
 }
   
          if ($card_mask !== null) {
             $sql_parts[] = "payment_card_mask = ?";
         
             $params[] = $card_mask;
             }
        if (empty($sql_parts)) {
      
      
 return true;
        }
        $sql = "UPDATE orders SET " . implode(', ', $sql_parts) . " WHERE id = ?";
          
              $params[] = $order_id;
    
         
         $stmt = pdo()->prepare($sql);
        return $stmt->execute($params);
    } catch (PDOException $e) {
        file_put_contents(ERROR_LOG_PATH, date('Y-m-d H:i:s') . " - DB Error updating payment details for order {$order_id}: " . $e->getMessage() . "\n", FILE_APPEND);
        return false;
    }
}

function getOrderByAuthority(string $authority): ?array {
    try {
        $stmt = pdo()->prepare("SELECT o.id, o.user_id, o.total_amount, o.status, o.order_type, o.order_note, o.shipping_fee_note,
                                      u.telegram_chat_id, u.bale_chat_id, u.first_name, u.national_id_code
                                     FROM orders o 
                                       JOIN users u ON o.user_id = u.id 
                                   WHERE o.payment_authority = ?");
    
    
        $stmt->execute([$authority]);
        $order = $stmt->fetch();
        if ($order && isset($order['total_amount'])) {
            
             $order['total_amount_rial'] = (int) bcmul((string)$order['total_amount'], '10', 0);
        }
 
        return $order ?: null;
 
   } catch (PDOException $e) {
        file_put_contents(ERROR_LOG_PATH, date('Y-m-d H:i:s') . " - DB Error getting order by authority ({$authority}): " . $e->getMessage() . "\n", FILE_APPEND);
        return null;
    }
}
?>