<?php
session_start();
require_once 'db.php';
require_once '../vendor/autoload.php';

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

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

if (!isset($_SESSION['user_id'])) {
    echo json_encode(['success' => false, 'message' => 'Unauthorized']);
    exit;
}

$action = $_GET['action'] ?? '';

if ($_SERVER['REQUEST_METHOD'] === 'POST' && $action === 'checkout') {
    $data = json_decode(file_get_contents("php://input"), true);
    if (!$data || empty($data['items'])) {
        echo json_encode(['success' => false, 'message' => 'Empty cart']);
        exit;
    }

    $shift_id = $data['shift_id'] ?? null;
    $payment_method = $data['payment_method'] ?? 'CASH';
    // Robustly standardize payment method names
    $pm_clean = strtoupper(preg_replace('/\s+/', ' ', trim($payment_method)));
    
    // Map various mobile money labels to 'LIPA KWA SIMU'
    $mobile_aliases = ['MOBILE MONEY', 'MOBILE', 'LIPA KWA SIMU', 'LIPAKWASIMU', 'PHONEMONEY', 'PHONE'];
    if (in_array($pm_clean, $mobile_aliases)) {
        $payment_method = 'LIPA KWA SIMU';
    } else {
        $payment_method = $pm_clean;
    }
    $amount_paid = $data['amount_paid'] ?? 0;
    $customer_id = $data['customer_id'] ?? null;
    
    if (!$shift_id) {
        echo json_encode(['success' => false, 'message' => 'No active shift provided']);
        exit;
    }
    
    try {
        $pdo->beginTransaction();
        
        // Calculate Total
        $total_amount = 0;
        foreach ($data['items'] as $item) {
            $total_amount += $item['quantity'] * $item['price'];
        }
        $change_amount = max(0, $amount_paid - $total_amount);
        
        $stmt = $pdo->prepare("INSERT INTO sales (shift_id, user_id, customer_id, total_amount, payment_method, amount_paid, change_amount) VALUES (?, ?, ?, ?, ?, ?, ?)");
        $stmt->execute([$shift_id, $_SESSION['user_id'], $customer_id, $total_amount, $payment_method, $amount_paid, $change_amount]);
        $sale_id = $pdo->lastInsertId();
        
        $itemStmt = $pdo->prepare("INSERT INTO sale_items (sale_id, product_id, quantity, price, subtotal, batch_id) VALUES (?, ?, ?, ?, ?, ?)");
        $stockStmt = $pdo->prepare("UPDATE products SET stock_quantity = stock_quantity - ? WHERE id = ?");
        $batchStockStmt = $pdo->prepare("UPDATE product_batches SET stock_quantity = stock_quantity - ? WHERE id = ?");
        
        foreach ($data['items'] as $item) {
            // Verify product exists and get its current stock info
            $checkStmt = $pdo->prepare("SELECT id, name, stock_quantity, track_batches FROM products WHERE id = ?");
            $checkStmt->execute([$item['id']]);
            $pData = $checkStmt->fetch();

            if (!$pData) {
                throw new Exception("Product ID " . $item['id'] . " (".$item['name'].") no longer exists in the database. Please clear your cart and refresh products.");
            }

            if ($pData['stock_quantity'] < $item['quantity']) {
                 // Throwing exception for stock - optional but good for strict pharmacies
                 // throw new Exception("Insufficient stock for product: " . $pData['name']);
            }

            $remaining_to_deduct = $item['quantity'];

            if ($pData['track_batches'] == 1) {
                // FEFO: Deduct from oldest batches first
                $bStmt = $pdo->prepare("SELECT id, stock_quantity FROM product_batches WHERE product_id = ? AND stock_quantity > 0 ORDER BY expiry_date ASC, created_at ASC");
                $bStmt->execute([$item['id']]);
                $batches = $bStmt->fetchAll();

                if (empty($batches)) {
                     // If no batch found but stock tracking enabled, we record without batch_id or fail
                     // For now, let's record without batch_id if none exists but stock > 0 (fallback)
                     $subtotal = $item['quantity'] * $item['price'];
                     $itemStmt->execute([$sale_id, $item['id'], $item['quantity'], $item['price'], $subtotal, null]);
                } else {
                    foreach ($batches as $batch) {
                        if ($remaining_to_deduct <= 0) break;

                        $deduct = min($remaining_to_deduct, $batch['stock_quantity']);
                        $subtotal_part = $deduct * $item['price'];
                        
                        // We record a sale item for each batch involved? 
                        // Or just record the first batch? 
                        // To be precise, multiple entries in sale_items might be needed if multiple batches used.
                        // But let's keep it simple: record the sale item with the PRIMARY batch used, or create multiple entries.
                        // Creating multiple entries is better for traceability.
                        $itemStmt->execute([$sale_id, $item['id'], $deduct, $item['price'], $subtotal_part, $batch['id']]);
                        $batchStockStmt->execute([$deduct, $batch['id']]);
                        
                        $remaining_to_deduct -= $deduct;
                    }
                    
                    if ($remaining_to_deduct > 0) {
                        // If still remaining (oversold), record the rest without batch or from a "general" batch
                        $subtotal_rest = $remaining_to_deduct * $item['price'];
                        $itemStmt->execute([$sale_id, $item['id'], $remaining_to_deduct, $item['price'], $subtotal_rest, null]);
                    }
                }
            } else {
                // Standard deduction
                $subtotal = $item['quantity'] * $item['price'];
                $itemStmt->execute([$sale_id, $item['id'], $item['quantity'], $item['price'], $subtotal, null]);
            }

            $stockStmt->execute([$item['quantity'], $item['id']]);
        }
        
        $pdo->commit();

        // --- NEW: AUTO-SAVE & ENQUEUE PRINT JOB ---
        try {
            // Fetch User Preferred Print Method
            $uStmt = $pdo->prepare("SELECT printing_method FROM users WHERE id = ?");
            $uStmt->execute([$_SESSION['user_id']]);
            $printing_method = $uStmt->fetchColumn() ?: 'Browser';

            // Only generate and save file if we are using LocalService or MobilePOS
            if ($printing_method === 'LocalService' || $printing_method === 'MobilePOS') {
                // Trick print_receipt.php into generating formatted output
                $_GET['id'] = $sale_id;
                
                // Get paper preference
                $stmt_size = $pdo->prepare("SELECT setting_value FROM settings WHERE setting_key = 'receipt_paper_size'");
                $stmt_size->execute();
                $pref_size = $stmt_size->fetchColumn() ?: '80mm';
                
                // For thermal printers on a Local Service, text format is often better/faster
                $is_thermal = ($pref_size === '58mm' || $pref_size === '80mm');
                $_GET['paper'] = $is_thermal ? ($pref_size . '-text') : $pref_size; 
                $ext = $is_thermal ? 'txt' : 'pdf';
                
                $return_content = true;
                
                ob_start();
                include 'print_receipt.php'; 
                $pdf_content = $pdf_output ?? null;
                ob_end_clean();
                
                if ($pdf_content) {
                    // Add IP if available to help identify terminal origin in logs/filename
                    $clientIP = $_SERVER['REMOTE_ADDR'] ?? 'local';
                    $clientIP = str_replace([':', '.'], '_', $clientIP); 
                    $fileName = "Receipt_{$sale_id}_" . date('Ymd_His') . "_IP_{$clientIP}." . $ext;
                    $savePath = __DIR__ . "/../receipts/" . $fileName;
                    if (!is_dir(__DIR__ . "/../receipts/")) {
                        mkdir(__DIR__ . "/../receipts/", 0777, true);
                    }
                    file_put_contents($savePath, $pdf_content);

                    // Add to the print_queue table
                    $qStmt = $pdo->prepare("INSERT INTO print_queue (user_id, sale_id, file_path) VALUES (?, ?, ?)");
                    $qStmt->execute([$_SESSION['user_id'], $sale_id, $fileName]);
                }
            }
        } catch (Throwable $e) {
            error_log("Failed to process server-side print for Sale #$sale_id: " . $e->getMessage());
        }
        // --- END AUTO-SAVE ---

        echo json_encode([
            'success' => true, 
            'message' => 'Sale completed', 
            'sale_id' => $sale_id,
            'change' => $change_amount,
            'print_file' => $fileName ?? null
        ]);
    } catch (Exception $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        echo json_encode(['success' => false, 'message' => 'Error processing sale: ' . $e->getMessage()]);
    }

} elseif ($_SERVER['REQUEST_METHOD'] === 'GET' && $action === 'receipt') {
    $sale_id = $_GET['id'] ?? null;
    if (!$sale_id) {
        echo json_encode(['success' => false, 'message' => 'Sale ID required']);
        exit;
    }
    
    $stmt = $pdo->prepare("SELECT s.*, u.username, c.name as customer_name, c.tin as customer_tin FROM sales s 
                           JOIN users u ON s.user_id = u.id 
                           LEFT JOIN customers c ON s.customer_id = c.id 
                           WHERE s.id = ?");
    $stmt->execute([$sale_id]);
    $sale = $stmt->fetch();
    
    if($sale) {
        $itemsStmt = $pdo->prepare("SELECT si.*, p.name,
                                   (SELECT SUM(quantity_refunded) FROM credit_note_items cni 
                                    JOIN credit_notes cn ON cni.credit_note_id = cn.id 
                                    WHERE cni.sale_item_id = si.id AND cn.status = 'Approved') as already_refunded,
                                   (SELECT SUM(quantity_refunded) FROM credit_note_items cni 
                                    JOIN credit_notes cn ON cni.credit_note_id = cn.id 
                                    WHERE cni.sale_item_id = si.id AND cn.status = 'Pending') as pending_refund
                                   FROM sale_items si 
                                   JOIN products p ON si.product_id = p.id 
                                   WHERE si.sale_id = ?");
        $itemsStmt->execute([$sale_id]);
        $items = $itemsStmt->fetchAll();
        $sale['items'] = $items;
        
        echo json_encode(['success' => true, 'data' => $sale]);
    } else {
        echo json_encode(['success' => false, 'message' => 'Sale not found']);
    }

} elseif ($_SERVER['REQUEST_METHOD'] === 'GET' && $action === 'list_shift_sales') {
    $shift_id = $_GET['shift_id'] ?? null;
    if (!$shift_id) {
        echo json_encode(['success' => false, 'message' => 'Shift ID required']);
        exit;
    }

    $stmt = $pdo->prepare("SELECT s.*, c.name as customer_name, 
                                  (SELECT SUM(total_refunded) FROM credit_notes WHERE sale_id = s.id AND status = 'Approved') as total_refunded,
                                  (SELECT id FROM credit_notes WHERE sale_id = s.id AND status = 'Pending' LIMIT 1) as pending_cn_id
                           FROM sales s 
                           LEFT JOIN customers c ON s.customer_id = c.id 
                           WHERE s.shift_id = ? ORDER BY s.sale_date DESC");
    $stmt->execute([$shift_id]);
    $sales = $stmt->fetchAll();

    // Fetch shift specific info for reconciliation
    $shiftStmt = $pdo->prepare("SELECT opening_balance FROM shifts WHERE id = ?");
    $shiftStmt->execute([$shift_id]);
    $shiftInfo = $shiftStmt->fetch();

    $cashStmt = $pdo->prepare("SELECT SUM(total_amount) as cash_total FROM sales WHERE shift_id = ? AND payment_method = 'CASH'");
    $cashStmt->execute([$shift_id]);
    $cashTotal = $cashStmt->fetch()['cash_total'] ?? 0;

    $refundStmt = $pdo->prepare("SELECT SUM(cn.total_refunded) as refund_total 
                                 FROM credit_notes cn
                                 JOIN sales s ON cn.sale_id = s.id
                                 WHERE cn.shift_id = ? AND s.payment_method = 'CASH' AND cn.status = 'Approved'");
    $refundStmt->execute([$shift_id]);
    $cashRefunds = $refundStmt->fetch()['refund_total'] ?? 0;

    $allRefundStmt = $pdo->prepare("SELECT SUM(total_refunded) as total FROM credit_notes WHERE shift_id = ? AND status = 'Approved'");
    $allRefundStmt->execute([$shift_id]);
    $totalRefunds = $allRefundStmt->fetch()['total'] ?? 0;

    $mobileStmt = $pdo->prepare("SELECT SUM(total_amount) as mobile_total FROM sales WHERE shift_id = ? AND payment_method = 'LIPA KWA SIMU'");
    $mobileStmt->execute([$shift_id]);
    $mobileTotal = $mobileStmt->fetch()['mobile_total'] ?? 0;

    $cardStmt = $pdo->prepare("SELECT SUM(total_amount) as card_total FROM sales WHERE shift_id = ? AND payment_method = 'CARD'");
    $cardStmt->execute([$shift_id]);
    $cardTotal = $cardStmt->fetch()['card_total'] ?? 0;

    echo json_encode([
        'success' => true, 
        'data' => $sales, 
        'opening_balance' => $shiftInfo['opening_balance'] ?? 0,
        'cash_total' => $cashTotal,
        'mobile_total' => $mobileTotal,
        'card_total' => $cardTotal,
        'cash_refunds' => $cashRefunds,
        'total_refunds' => $totalRefunds
    ]);

} elseif ($_SERVER['REQUEST_METHOD'] === 'POST' && $action === 'email_receipt') {
    $raw = file_get_contents('php://input');
    $data = json_decode($raw, true);
    
    $sale_id = $data['sale_id'] ?? null;
    $email = $data['email'] ?? null;

    if (!$sale_id || !$email) {
        echo json_encode(['success' => false, 'message' => 'Sale ID and Email are required']);
        exit;
    }
    
    try {
        $stmt = $pdo->query("SELECT setting_key, setting_value FROM settings");
        $settings = [];
        while ($row = $stmt->fetch()) {
            $settings[$row['setting_key']] = $row['setting_value'];
        }

        if (empty($settings['smtp_host'])) {
            throw new Exception("SMTP settings are not configured. Please configure them in the Admin Dashboard.");
        }

        // Trick print_receipt into giving us the PDF back instead of outputting it
        $_GET['id'] = $sale_id;
        $return_content = true;
        
        // Suppress session notices and echoes
        ob_start();
        require 'print_receipt.php'; 
        // Note: print_receipt.php sets $pdf_output
        $pdf_content = $pdf_output ?? null;
        ob_end_clean();

        if (!$pdf_content) {
            throw new Exception("Failed to statically generate PDF for email attachment.");
        }

        $mail = new PHPMailer(true);
        $mail->isSMTP();
        $mail->Host       = $settings['smtp_host'];
        $mail->SMTPAuth   = true;
        $mail->Username   = $settings['smtp_user'];
        $mail->Password   = $settings['smtp_pass'];
        $mail->SMTPSecure = ($settings['smtp_encryption'] === 'ssl') ? PHPMailer::ENCRYPTION_SMTPS : PHPMailer::ENCRYPTION_STARTTLS;
        $mail->Port       = $settings['smtp_port'];

        $mail->setFrom($settings['smtp_from_email'], $settings['smtp_from_name']);
        $mail->addAddress($email);

        $mail->addStringAttachment($pdf_content, "Receipt_#{$sale_id}.pdf", 'base64', 'application/pdf');

        $mail->isHTML(true);
        $mail->Subject = 'Your Receipt from ' . ($settings['company_name'] ?? 'JUSTSALE');
        
        $bodyHtml = "
        <div style='font-family: Arial, sans-serif; color: #333;'>
            <h2>Thank you for your business!</h2>
            <p>Dear Customer,</p>
            <p>Your transaction has been securely processed. Please find your official receipt attached to this email as a PDF document.</p>
            <br>
            <p>Best Regards,<br><strong>" . htmlspecialchars($settings['company_name'] ?? 'JUSTSALE') . "</strong></p>
        </div>";

        $mail->Body = $bodyHtml;
        $mail->AltBody = "Thank you for your business. Please find your official receipt attached to this email.";

        $mail->send();
        echo json_encode(['success' => true, 'message' => 'Receipt securely emailed to ' . htmlspecialchars($email)]);

    } catch (Exception $e) {
        echo json_encode(['success' => false, 'message' => 'Delivery Failed: ' . $e->getMessage()]);
    }

} else {
    echo json_encode(['success' => false, 'message' => 'Unknown action']);
}
