<?php
include 'bd/myData.php';
require_once 'auth.php';
include 'cors.php';
setupCORS();

if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
    http_response_code(204);
    exit();
}

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

// Helper function to validate numeric values
function validateNumeric($value, $fallback = 0) {
    $parsed = floatval($value);
    return is_numeric($value) ? $parsed : $fallback;
}

// Helper function to check and update stock
function checkAndUpdateStock($id_produit, $quantite, $operation = 'decrease') {
    try {
        $queryCheck = "SELECT stock_actuel FROM produits WHERE id_produit = :id_produit";
        $resultCheck = metodGet($queryCheck, array(':id_produit' => $id_produit));
        $product = $resultCheck->fetch(PDO::FETCH_ASSOC);
        
        if (!$product) {
            throw new Exception("Product not found");
        }
        
        $currentStock = $product['stock_actuel'];
        
        if ($operation === 'decrease' && $currentStock < $quantite) {
            throw new Exception("Insufficient stock. Available: $currentStock, Requested: $quantite");
        }
        
        $newStock = $operation === 'decrease' ? $currentStock - $quantite : $currentStock + $quantite;
        
        $queryUpdate = "UPDATE produits 
                       SET stock_actuel = :new_stock,
                           date_upd = CURRENT_TIMESTAMP 
                       WHERE id_produit = :id_produit";
                       
        $params = array(
            ':new_stock' => $newStock,
            ':id_produit' => $id_produit
        );
        
        metodPut($queryUpdate, $params, 'produits');
        
        return array(
            'success' => true,
            'new_stock' => $newStock,
            'is_low_stock' => $newStock <= 0
        );
    } catch (Exception $e) {
        throw new Exception("Stock update failed: " . $e->getMessage());
    }
}

// Helper function to update sale total
function updateSaleTotal($id_vente) {
    try {
        // Calculate new total
        $query = "SELECT COALESCE(SUM(montant_total), 0) as new_total 
                 FROM details_ventes 
                 WHERE id_vente = :id_vente";
        
        $result = metodGet($query, array(':id_vente' => $id_vente));
        $data = $result->fetch(PDO::FETCH_ASSOC);
        $newTotal = $data['new_total'];
        
        // Update ventes table
        $updateQuery = "UPDATE ventes 
                       SET montant_total = :new_total,
                           date_upd = CURRENT_TIMESTAMP,
                           user_upd = 'SYSTEM'
                       WHERE id_vente = :id_vente";
        
        $params = array(
            ':new_total' => $newTotal,
            ':id_vente' => $id_vente
        );
        
        metodPut($updateQuery, $params, 'ventes');
        
        // Update payment plan if exists
        $planQuery = "UPDATE paiements_clients_tranches 
                     SET montant_total = :new_total,
                         date_upd = CURRENT_TIMESTAMP,
                         user_upd = 'SYSTEM'
                     WHERE id_vente = :id_vente";
                     
        metodPut($planQuery, $params, 'paiements_clients_tranches');
        
        return $newTotal;
    } catch (Exception $e) {
        throw new Exception("Failed to update sale total: " . $e->getMessage());
    }
}

// Handler for GET requests
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
    if (isset($_GET['id_vente'])) {
        $query = "SELECT dv.*, p.designation 
                 FROM details_ventes dv
                 LEFT JOIN produits p ON dv.id_produit = p.id_produit
                 WHERE dv.id_vente = :id_vente";
        $params = array(':id_vente' => $_GET['id_vente']);
        $result = metodGet($query, $params);
        echo json_encode($result->fetchAll(PDO::FETCH_ASSOC));
    } else {
        $query = "SELECT * FROM details_ventes";
        $result = metodGet($query);
        echo json_encode($result->fetchAll(PDO::FETCH_ASSOC));
    }
    exit();
}

// Handler for DELETE requests
if ($_SERVER['REQUEST_METHOD'] == 'POST' && $_POST['METHOD'] == 'DELETE') {
    try {
        if (!isset($_GET['id_detail_vente'])) {
            throw new Exception("Detail ID is required for deletion");
        }

        $id_detail_vente = $_GET['id_detail_vente'];
        
        // Get current detail info with related data
        $getDetailQuery = "SELECT dv.*, v.id_vente, v.montant_total as vente_total,
                                 pct.id_paiement_tranche, pct.montant_total as payment_total
                          FROM details_ventes dv
                          JOIN ventes v ON dv.id_vente = v.id_vente
                          LEFT JOIN paiements_clients_tranches pct ON v.id_vente = pct.id_vente
                          WHERE dv.id_detail_vente = :id_detail_vente";
        
        $detailResult = metodGet($getDetailQuery, array(':id_detail_vente' => $id_detail_vente));
        $detailData = $detailResult->fetch(PDO::FETCH_ASSOC);
        
        if (!$detailData) {
            throw new Exception("Sale detail not found");
        }

        // Calculate new total after deletion
        $newTotalQuery = "SELECT COALESCE(SUM(montant_total), 0) as new_total 
                         FROM details_ventes 
                         WHERE id_vente = :id_vente 
                         AND id_detail_vente != :id_detail_vente";
        
        $totalResult = metodGet($newTotalQuery, array(
            ':id_vente' => $detailData['id_vente'],
            ':id_detail_vente' => $id_detail_vente
        ));
        $newTotalData = $totalResult->fetch(PDO::FETCH_ASSOC);
        $newTotal = floatval($newTotalData['new_total']);

        // Handle payment plan and refund scenarios
        if ($detailData['id_paiement_tranche'] && $newTotal < $detailData['vente_total']) {
            $refundAmount = $detailData['vente_total'] - $newTotal;
            
            // Get pending payments
            $pendingQuery = "SELECT id_reglement, montant, date_echeance 
                           FROM reglements_tranches_clients 
                           WHERE id_paiement_tranche = :id_paiement_tranche 
                           AND statut_reglements = 'En attente'
                           ORDER BY date_echeance ASC";
            
            $pendingResult = metodGet($pendingQuery, array(
                ':id_paiement_tranche' => $detailData['id_paiement_tranche']
            ));
            $pendingPayments = $pendingResult->fetchAll(PDO::FETCH_ASSOC);
            
            // Calculate total pending amount
            $totalPending = array_reduce($pendingPayments, function($sum, $payment) {
                return $sum + floatval($payment['montant']);
            }, 0);

            // Scenario 1: Can handle through pending payments
            if ($refundAmount <= $totalPending) {
                $remainingRefund = $refundAmount;
                foreach ($pendingPayments as $payment) {
                    if ($remainingRefund <= 0) break;
                    
                    if ($remainingRefund >= $payment['montant']) {
                        // Delete this payment
                        $deleteQuery = "DELETE FROM reglements_tranches_clients 
                                      WHERE id_reglement = :id_reglement";
                        metodDelete($deleteQuery, 
                            array(':id_reglement' => $payment['id_reglement']),
                            'reglements_tranches_clients'
                        );
                        $remainingRefund -= $payment['montant'];
                    } else {
                        // Reduce this payment
                        $updateQuery = "UPDATE reglements_tranches_clients 
                                      SET montant = montant - :refund_amount,
                                          user_upd = :user_upd,
                                          date_upd = CURRENT_TIMESTAMP
                                      WHERE id_reglement = :id_reglement";
                        metodPut($updateQuery, array(
                            ':refund_amount' => $remainingRefund,
                            ':user_upd' => 'SYSTEM',
                            ':id_reglement' => $payment['id_reglement']
                        ), 'reglements_tranches_clients');
                        $remainingRefund = 0;
                    }
                }
            } 
            // Scenario 2: Need to create refund record
            else {
                // Delete all pending payments
                $deleteAllPendingQuery = "DELETE FROM reglements_tranches_clients 
                                        WHERE id_paiement_tranche = :id_paiement_tranche 
                                        AND statut_reglements = 'En attente'";
                metodDelete($deleteAllPendingQuery, 
                    array(':id_paiement_tranche' => $detailData['id_paiement_tranche']),
                    'reglements_tranches_clients'
                );
                
                // Create refund record for remaining amount
                $actualRefundAmount = $refundAmount - $totalPending;
                $refundQuery = "INSERT INTO refund_client (
                    id_vente, id_paiement_tranche, montant_refund,
                    motif, statut_refund, date_refund, user_cre
                ) VALUES (
                    :id_vente, :id_paiement_tranche, :montant_refund,
                    'Modification vente', 'En attente', CURRENT_DATE, :user_cre
                )";
                
                $queryAutoIncrement = "SELECT MAX(id_refund) as id FROM refund_client";
                metodPost($refundQuery, $queryAutoIncrement, array(
                    ':id_vente' => $detailData['id_vente'],
                    ':id_paiement_tranche' => $detailData['id_paiement_tranche'],
                    ':montant_refund' => $actualRefundAmount,
                    ':user_cre' => 'SYSTEM'
                ), 'refund_client');
            }
        }

        // Update product stock
        $stockResult = checkAndUpdateStock(
            $detailData['id_produit'], 
            $detailData['quantite'], 
            'increase'
        );
        
        // Delete the detail
        $deleteDetailQuery = "DELETE FROM details_ventes 
                            WHERE id_detail_vente = :id_detail_vente";
        metodDelete($deleteDetailQuery, 
            array(':id_detail_vente' => $id_detail_vente),
            'details_ventes'
        );
        
        // Update sale total
        $finalTotal = updateSaleTotal($detailData['id_vente']);
        
        echo json_encode([
            'success' => true,
            'message' => 'Sale detail deleted successfully',
            'new_total' => $finalTotal,
            'stock_update' => $stockResult
        ]);
        exit();
        
    } catch (Exception $e) {
        http_response_code(500);
        echo json_encode(['error' => $e->getMessage()]);
        exit();
    }
}

// Handle POST requests
if ($_SERVER['REQUEST_METHOD'] == 'POST' && (!isset($_POST['METHOD']) || $_POST['METHOD'] == 'POST')) {
    try {
        if (!isset($_POST['id_vente']) || !isset($_POST['id_produit']) || 
            !isset($_POST['quantite']) || !isset($_POST['prix_vente_unitaire'])) {
            throw new Exception("Missing required fields");
        }

        // Check stock before proceeding
        $stockResult = checkAndUpdateStock($_POST['id_produit'], $_POST['quantite'], 'decrease');
        
        $montant_total = validateNumeric($_POST['quantite']) * validateNumeric($_POST['prix_vente_unitaire']);
        
        $query = "INSERT INTO details_ventes(
                    id_vente, id_produit, quantite, prix_vente_unitaire,
                    montant_total, user_cre
                 ) VALUES (
                    :id_vente, :id_produit, :quantite, :prix_vente_unitaire,
                    :montant_total, :user_cre
                 )";
                 
        $queryAutoIncrement = "SELECT MAX(id_detail_vente) as id FROM details_ventes";
        
        $params = array(
            ':id_vente' => $_POST['id_vente'],
            ':id_produit' => $_POST['id_produit'],
            ':quantite' => $_POST['quantite'],
            ':prix_vente_unitaire' => $_POST['prix_vente_unitaire'],
            ':montant_total' => $montant_total,
            ':user_cre' => $_POST['user_cre'] ?? 'SYSTEM'
        );
        
        $result = metodPost($query, $queryAutoIncrement, $params, 'details_ventes');
        $newTotal = updateSaleTotal($_POST['id_vente']);
        
        echo json_encode([
            'success' => true,
            'message' => 'Sale detail created successfully',
            'data' => array_merge($result, ['new_total' => $newTotal]),
            'stock_info' => $stockResult
        ]);
        exit();
    } catch (Exception $e) {
        http_response_code(500);
        echo json_encode(['error' => $e->getMessage()]);
        exit();
    }
}


// Handle PUT requests
if ($_SERVER['REQUEST_METHOD'] == 'POST' && $_POST['METHOD'] == 'PUT') {
    try {
        if (!isset($_GET['id_detail_vente'])) {
            throw new Exception("Detail ID is required for update");
        }

        // Get current detail info
        $getDetailQuery = "SELECT dv.id_vente, dv.id_produit, dv.quantite, dv.prix_vente_unitaire,
                                 pct.id_paiement_tranche, pct.montant_total as payment_total
                          FROM details_ventes dv
                          LEFT JOIN ventes v ON dv.id_vente = v.id_vente
                          LEFT JOIN paiements_clients_tranches pct ON v.id_vente = pct.id_vente
                          WHERE dv.id_detail_vente = :id_detail_vente";
        $detailResult = metodGet($getDetailQuery, array(':id_detail_vente' => $_GET['id_detail_vente']));
        $currentDetail = $detailResult->fetch(PDO::FETCH_ASSOC);

        if (!$currentDetail) {
            throw new Exception("Sale detail not found");
        }

        // Calculate current and new amounts
        $currentAmount = $currentDetail['quantite'] * $currentDetail['prix_vente_unitaire'];
        $newAmount = floatval($_POST['quantite']) * floatval($_POST['prix_vente_unitaire']);

        // Handle stock update
        $quantityDifference = floatval($_POST['quantite']) - $currentDetail['quantite'];
        if ($quantityDifference != 0) {
            $operation = $quantityDifference < 0 ? 'increase' : 'decrease';
            $stockResult = checkAndUpdateStock(
                $_POST['id_produit'],
                abs($quantityDifference),
                $operation
            );
        }

        // Handle refund if new amount is less
        if ($newAmount < $currentAmount && $currentDetail['id_paiement_tranche']) {
            $refundAmount = $currentAmount - $newAmount;

            // Get pending payments
            $pendingQuery = "SELECT id_reglement, montant
                           FROM reglements_tranches_clients
                           WHERE id_paiement_tranche = :id_paiement_tranche
                           AND statut_reglements = 'En attente'
                           ORDER BY date_echeance ASC";
            $pendingResult = metodGet($pendingQuery, array(':id_paiement_tranche' => $currentDetail['id_paiement_tranche']));
            $pendingPayments = $pendingResult->fetchAll(PDO::FETCH_ASSOC);

            $totalPending = array_reduce($pendingPayments, function($sum, $payment) {
                return $sum + floatval($payment['montant']);
            }, 0);

            // If difference is less than or equal to pending payments
            if ($refundAmount <= $totalPending) {
                $remainingRefund = $refundAmount;
                foreach ($pendingPayments as $payment) {
                    if ($remainingRefund <= 0) break;

                    if ($remainingRefund >= $payment['montant']) {
                        // Delete this payment
                        $deleteQuery = "DELETE FROM reglements_tranches_clients 
                                      WHERE id_reglement = :id_reglement";
                        metodDelete($deleteQuery, array(':id_reglement' => $payment['id_reglement']), 'reglements_tranches_clients');
                        $remainingRefund -= $payment['montant'];
                    } else {
                        // Reduce this payment
                        $newPaymentAmount = $payment['montant'] - $remainingRefund;
                        $updateQuery = "UPDATE reglements_tranches_clients 
                                      SET montant = :new_amount,
                                          user_upd = :user_upd,
                                          date_upd = CURRENT_TIMESTAMP
                                      WHERE id_reglement = :id_reglement";
                        metodPut($updateQuery, array(
                            ':new_amount' => $newPaymentAmount,
                            ':user_upd' => $_POST['user_upd'] ?? 'SYSTEM',
                            ':id_reglement' => $payment['id_reglement']
                        ), 'reglements_tranches_clients');
                        $remainingRefund = 0;
                    }
                }
            } else {
                // Create refund record
                if (!empty($pendingPayments)) {
                    // Delete all pending payments
                    $deleteQuery = "DELETE FROM reglements_tranches_clients 
                                  WHERE id_paiement_tranche = :id_paiement_tranche 
                                  AND statut_reglements = 'En attente'";
                    metodDelete($deleteQuery, 
                              array(':id_paiement_tranche' => $currentDetail['id_paiement_tranche']), 
                              'reglements_tranches_clients');
                }

                $actualRefundAmount = $refundAmount - $totalPending;
                $refundQuery = "INSERT INTO refund_client (
                    id_vente, id_paiement_tranche, montant_refund, motif,
                    statut_refund, date_refund, user_cre
                ) VALUES (
                    :id_vente, :id_paiement_tranche, :montant_refund,
                    'Modification vente', 'En attente', CURRENT_DATE, :user_cre
                )";
                
                $queryAutoIncrement = "SELECT MAX(id_refund) as id FROM refund_client";
                metodPost($refundQuery, $queryAutoIncrement, array(
                    ':id_vente' => $currentDetail['id_vente'],
                    ':id_paiement_tranche' => $currentDetail['id_paiement_tranche'],
                    ':montant_refund' => $actualRefundAmount,
                    ':user_cre' => $_POST['user_upd'] ?? 'SYSTEM'
                ), 'refund_client');
            }
        }

        // Update the detail itself
        $updateQuery = "UPDATE details_ventes 
                       SET id_produit = :id_produit,
                           quantite = :quantite,
                           prix_vente_unitaire = :prix_vente_unitaire,
                           montant_total = :montant_total,
                           user_upd = :user_upd,
                           date_upd = CURRENT_TIMESTAMP
                       WHERE id_detail_vente = :id_detail_vente";

        $params = array(
            ':id_detail_vente' => $_GET['id_detail_vente'],
            ':id_produit' => $_POST['id_produit'],
            ':quantite' => $_POST['quantite'],
            ':prix_vente_unitaire' => $_POST['prix_vente_unitaire'],
            ':montant_total' => $newAmount,
            ':user_upd' => $_POST['user_upd'] ?? 'SYSTEM'
        );

        metodPut($updateQuery, $params, 'details_ventes');

        // Update sale total
        $newTotal = updateSaleTotal($currentDetail['id_vente']);

        echo json_encode([
            'success' => true,
            'message' => 'Sale detail updated successfully',
            'data' => array_merge(['new_total' => $newTotal], $params),
            'stock_info' => $stockResult ?? null
        ]);
        exit();

    } catch (Exception $e) {
        http_response_code(500);
        echo json_encode(['error' => $e->getMessage()]);
        exit();
    }
}

// If no valid request method is matched
http_response_code(400);
echo json_encode(['error' => 'Invalid request method or parameters']);
exit();
?>