<?php
// modules/sales/save_sale.php
session_start();

// Enable error reporting for debugging
error_reporting(E_ALL);
ini_set('display_errors', 1);

// Include database connection
require_once "../assets/db_connect.php";

header('Content-Type: application/json');

// Check if PDO connection exists
if (!isset($pdo)) {
    echo json_encode(['success' => false, 'message' => 'Database connection failed']);
    exit;
}

// Validate user session
if (!isset($_SESSION['user']['shop_id']) || !isset($_SESSION['user']['id'])) {
    echo json_encode(['success' => false, 'message' => 'Unauthorized access']);
    exit;
}

$shop_id = (int)$_SESSION['user']['shop_id'];
$user_id = (int)$_SESSION['user']['id'];

// Get POST data
$data = json_decode(file_get_contents('php://input'), true);

// For form data (if not using JSON)
if (empty($data)) {
    $data = $_POST;
    
    // Decode cart if it's JSON string
    if (isset($data['cart']) && is_string($data['cart'])) {
        $data['cart'] = json_decode($data['cart'], true);
    }
}

// Log incoming data for debugging
error_log("Save sale data received: " . print_r($data, true));

// Validate required data
if (empty($data['cart']) || !is_array($data['cart'])) {
    echo json_encode(['success' => false, 'message' => 'Cart is empty']);
    exit;
}

// Validate other required fields
$required_fields = ['invoice_no', 'shop_id', 'user_id', 'payment_method', 'amount_paid', 'total'];
foreach ($required_fields as $field) {
    if (!isset($data[$field]) || empty($data[$field])) {
        echo json_encode(['success' => false, 'message' => "Missing required field: $field"]);
        exit;
    }
}

try {
    // Start transaction
    $pdo->beginTransaction();
    
    // 1. Create or get customer
    $customer_id = null;
    if (!empty($data['customer_id'])) {
        $customer_id = (int)$data['customer_id'];
    } elseif (!empty($data['new_customer_name'])) {
        // Insert new customer
        $stmt = $pdo->prepare("
            INSERT INTO customers (shop_id, name, phone, email, address, created_at) 
            VALUES (:shop_id, :name, :phone, :email, :address, NOW())
        ");
        $stmt->execute([
            ':shop_id' => $shop_id,
            ':name' => trim($data['new_customer_name']),
            ':phone' => $data['new_customer_phone'] ?? '',
            ':email' => $data['new_customer_email'] ?? '',
            ':address' => $data['new_customer_address'] ?? ''
        ]);
        $customer_id = $pdo->lastInsertId();
    }
    
    // 2. Validate cart items before processing
    $validated_cart = [];
    $grand_total = 0;
    
    foreach ($data['cart'] as $item) {
        // Validate required item fields
        $required_item_fields = ['product_id', 'batch_id', 'product_name', 'batch_no', 
                                 'current_qty', 'unit_price', 'vat_percent', 'qty', 'discount'];
        foreach ($required_item_fields as $field) {
            if (!isset($item[$field])) {
                throw new Exception("Missing item field: $field");
            }
        }
        
        // Convert to proper types
        $validated_item = [
            'product_id' => (int)$item['product_id'],
            'batch_id' => (int)$item['batch_id'],
            'product_name' => $item['product_name'],
            'batch_no' => $item['batch_no'],
            'current_qty' => (int)$item['current_qty'],
            'unit_price' => (float)$item['unit_price'],
            'vat_percent' => (float)$item['vat_percent'],
            'qty' => (int)$item['qty'],
            'discount' => (float)$item['discount']
        ];
        
        // Validate stock availability
        $stock_sql = "SELECT qty FROM product_batches WHERE id = :batch_id AND shop_id = :shop_id";
        $stock_stmt = $pdo->prepare($stock_sql);
        $stock_stmt->execute([':batch_id' => $validated_item['batch_id'], ':shop_id' => $shop_id]);
        $available_qty = $stock_stmt->fetchColumn();
        
        if ($available_qty === false) {
            throw new Exception("Batch not found: " . $validated_item['batch_id']);
        }
        
        if ($validated_item['qty'] > $available_qty) {
            throw new Exception("Insufficient stock for {$validated_item['product_name']}. Available: $available_qty, Requested: {$validated_item['qty']}");
        }
        
        // Calculate line total
        $line_total = $validated_item['qty'] * $validated_item['unit_price'];
        $discount_amount = $line_total * ($validated_item['discount'] / 100);
        $after_discount = $line_total - $discount_amount;
        $vat_amount = $after_discount * ($validated_item['vat_percent'] / 100);
        $final_total = $after_discount + $vat_amount;
        
        $validated_item['line_total'] = $final_total;
        $validated_cart[] = $validated_item;
        $grand_total += $final_total;
    }
    
    // 3. Insert sale record
    $paid_amount = (float)$data['amount_paid'];
    $payment_method = $data['payment_method'];
    $invoice_no = $data['invoice_no'];
    $sale_total = (float)$data['total'];
    
    // Determine status
    $status = 'paid';
    if ($paid_amount <= 0) {
        $status = 'open';
    } elseif ($paid_amount < $sale_total) {
        $status = 'partially_paid';
    }
    
    $stmt = $pdo->prepare("
        INSERT INTO sales (
            invoice_no, 
            sale_date, 
            customer_id, 
            total, 
            paid, 
            status, 
            created_by, 
            shop_id
        ) VALUES (
            :invoice_no,
            NOW(),
            :customer_id,
            :total,
            :paid,
            :status,
            :created_by,
            :shop_id
        )
    ");
    
    $stmt->execute([
        ':invoice_no' => $invoice_no,
        ':customer_id' => $customer_id,
        ':total' => $sale_total,
        ':paid' => $paid_amount,
        ':status' => $status,
        ':created_by' => $user_id,
        ':shop_id' => $shop_id
    ]);
    
    $sale_id = $pdo->lastInsertId();
    
    // 4. Insert sale lines and update inventory
    foreach ($validated_cart as $item) {
        // Insert sale line
        $stmt = $pdo->prepare("
            INSERT INTO sale_lines (
                sale_id,
                product_id,
                batch_id,
                qty,
                unit_price,
                discount,
                line_total,
                shop_id
            ) VALUES (
                :sale_id,
                :product_id,
                :batch_id,
                :qty,
                :unit_price,
                :discount,
                :line_total,
                :shop_id
            )
        ");
        
        $stmt->execute([
            ':sale_id' => $sale_id,
            ':product_id' => $item['product_id'],
            ':batch_id' => $item['batch_id'],
            ':qty' => $item['qty'],
            ':unit_price' => $item['unit_price'],
            ':discount' => $item['discount'],
            ':line_total' => $item['line_total'],
            ':shop_id' => $shop_id
        ]);
        
        // Create inventory movement (deduct stock)
        $stmt = $pdo->prepare("
            INSERT INTO inventory_movements (
                product_id,
                batch_id,
                change_qty,
                movement_type,
                reference_id,
                created_by,
                shop_id,
                created_at
            ) VALUES (
                :product_id,
                :batch_id,
                :change_qty,
                'SALE',
                :reference_id,
                :created_by,
                :shop_id,
                NOW()
            )
        ");
        
        $stmt->execute([
            ':product_id' => $item['product_id'],
            ':batch_id' => $item['batch_id'],
            ':change_qty' => $item['qty'],
            ':reference_id' => $sale_id,
            ':created_by' => $user_id,
            ':shop_id' => $shop_id
        ]);
    }
    
    // 5. Insert payment if paid
    if ($paid_amount > 0) {
        $stmt = $pdo->prepare("
            INSERT INTO payments (
                sale_id,
                amount,
                method,
                paid_at,
                created_by,
                shop_id
            ) VALUES (
                :sale_id,
                :amount,
                :method,
                NOW(),
                :created_by,
                :shop_id
            )
        ");
        
        $stmt->execute([
            ':sale_id' => $sale_id,
            ':amount' => $paid_amount,
            ':method' => $payment_method,
            ':created_by' => $user_id,
            ':shop_id' => $shop_id
        ]);
    }
    
    // 6. Commit transaction
    $pdo->commit();
    
    // Get the complete sale data for response
    $stmt = $pdo->prepare("
        SELECT s.*, c.name as customer_name 
        FROM sales s 
        LEFT JOIN customers c ON s.customer_id = c.id 
        WHERE s.id = :sale_id
    ");
    $stmt->execute([':sale_id' => $sale_id]);
    $sale_data = $stmt->fetch(PDO::FETCH_ASSOC);
    
    // Success response
    echo json_encode([
        'success' => true,
        'sale_id' => $sale_id,
        'invoice_no' => $sale_data['invoice_no'],
        'total' => number_format($sale_total, 2),
        'paid' => number_format($paid_amount, 2),
        'change' => number_format($paid_amount - $sale_total, 2),
        'customer_name' => $sale_data['customer_name'] ?? 'Walk-in Customer',
        'sale_date' => $sale_data['sale_date'],
        'message' => 'Sale completed successfully'
    ]);
    
} catch (PDOException $e) {
    // Rollback on error
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }
    error_log("Save sale PDO error: " . $e->getMessage());
    echo json_encode([
        'success' => false, 
        'message' => 'Database error: ' . $e->getMessage(),
        'error_code' => $e->getCode()
    ]);
} catch (Exception $e) {
    // Rollback on error
    if ($pdo && $pdo->inTransaction()) {
        $pdo->rollBack();
    }
    error_log("Save sale error: " . $e->getMessage());
    echo json_encode([
        'success' => false, 
        'message' => 'Error: ' . $e->getMessage()
    ]);
}
?>