<?php
session_start();
include 'layouts/dbconn.php';

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

if (!isset($_SESSION['user_id'])) {
    http_response_code(401);
    echo json_encode(['success' => false, 'error' => 'Not authenticated']);
    exit;
}

try {
    // Validate required fields
    $required_fields = ['receipt_no', 'receipt_date', 'corp_id', 'receipt_amount', 'payment_mode', 'payment_type'];
    foreach ($required_fields as $field) {
        if (empty($_POST[$field])) {
            throw new Exception("Missing required field: $field");
        }
    }

    // Extract main receipt data
    $receipt_no = $_POST['receipt_no'];
    $receipt_date = $_POST['receipt_date'];
    $corp_id = $_POST['corp_id'];
    $receipt_amount = floatval($_POST['receipt_amount']);
    $payment_mode = $_POST['payment_mode'];
    $payment_type = $_POST['payment_type'];

    // Validate bank details for non-cash payments
    $bank_id = null;
    $reference_no = null;
    if ($payment_mode != '1') {
        if (empty($_POST['bank_id']) || empty($_POST['reference_no'])) {
            throw new Exception('Bank details are required for non-cash payments');
        }
        $bank_id = $_POST['bank_id'];
        $reference_no = $_POST['reference_no'];
    }

    // Validate allocations
    if (empty($_POST['allocations']) || !is_array($_POST['allocations'])) {
        throw new Exception('No allocations provided');
    }

    $allocations = [];
    $total_allocated = 0;
    foreach ($_POST['allocations'] as $debit_no => $amount) {
        $allocation_amount = floatval($amount);
        if ($allocation_amount > 0) {
            $allocations[] = [
                'debit_no' => $debit_no,
                'amount' => $allocation_amount
            ];
            $total_allocated += $allocation_amount;
        }
    }

    if (empty($allocations)) {
        throw new Exception('No valid allocations found');
    }

    // Calculate payment difference
    $payment_difference = $receipt_amount - $total_allocated;

    // Validate payment type logic
    switch ($payment_type) {
        case 'exact':
            if (abs($payment_difference) > 0.01) {
                throw new Exception('Total allocations must match receipt amount for exact payment');
            }
            break;
        case 'over':
            if ($payment_difference <= 0) {
                throw new Exception('Receipt amount must be greater than allocations for overpayment');
            }
            break;
        case 'under':
            if ($payment_difference >= 0) {
                throw new Exception('Total allocations must be greater than receipt amount for underpayment');
            }
            break;
        default:
            throw new Exception('Invalid payment type');
    }

    // Start database transaction
    $conn->begin_transaction();

    try {
        // Save receipt record
        $sql = "INSERT INTO premium_receipt (
            receipt_no, receipt_date, receipt_amount, payment_mode, 
            receipt_bank, cheque_no, corp_id, payment_type, 
            payment_difference, user_id, date_entered
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURDATE())";

        $stmt = $conn->prepare($sql);
        $stmt->bind_param('ssdsisssdi', 
            $receipt_no, $receipt_date, $receipt_amount, $payment_mode, 
            $bank_id, $reference_no, $corp_id, $payment_type, 
            $payment_difference, $_SESSION['user_id']
        );

        if (!$stmt->execute()) {
            throw new Exception("Failed to save receipt: " . $stmt->error);
        }

        // Save overpayment as credit (if applicable)
        if ($payment_type === 'over' && $payment_difference > 0) {
            $sql = "INSERT INTO payment_credits (
                receipt_no, corp_id, amount, created_by, created_at, status
            ) VALUES (?, ?, ?, ?, NOW(), 'ACTIVE')";
            $stmt = $conn->prepare($sql);
            $stmt->bind_param('ssdi', $receipt_no, $corp_id, $payment_difference, $_SESSION['user_id']);
            if (!$stmt->execute()) {
                throw new Exception("Failed to save overpayment credit: " . $stmt->error);
            }
        }

        // Process allocations
        foreach ($allocations as &$allocation) {
            // Fetch `debit_id` for `debit_no`
            $stmt = $conn->prepare("SELECT debit_id, amount, allocated_amount FROM premium_debit_notes WHERE debit_no = ? FOR UPDATE");
            $stmt->bind_param('s', $allocation['debit_no']);
            $stmt->execute();
            $result = $stmt->get_result();

            if ($result->num_rows === 0) {
                throw new Exception("Debit note not found: " . $allocation['debit_no']);
            }

            $debit = $result->fetch_assoc();
            $allocation['debit_id'] = $debit['debit_id'];

            // Calculate new allocated amount
            $new_allocated = ($debit['allocated_amount'] ?? 0) + $allocation['amount'];
            $new_status = (abs($new_allocated - $debit['amount']) < 0.01) ? 'ALLOCATED' : 'PARTIAL';

            // Update debit note
            $sql = "UPDATE premium_debit_notes SET allocated_amount = ?, status = ? WHERE debit_id = ?";
            $stmt = $conn->prepare($sql);
            $stmt->bind_param('dsi', $new_allocated, $new_status, $allocation['debit_id']);
            if (!$stmt->execute()) {
                throw new Exception("Failed to update debit note: " . $stmt->error);
            }

            // Save allocation
            $sql = "INSERT INTO receipt_allocations (
                receipt_no, debit_id, amount, allocation_date, is_partial, user_id
            ) VALUES (?, ?, ?, ?, ?, ?)";
            $is_partial = ($new_status === 'PARTIAL') ? 1 : 0;
            $stmt = $conn->prepare($sql);
            $stmt->bind_param('ssdsii', 
                $receipt_no, $allocation['debit_id'], $allocation['amount'], 
                $receipt_date, $is_partial, $_SESSION['user_id']
            );
            if (!$stmt->execute()) {
                throw new Exception("Failed to save allocation: " . $stmt->error);
            }
        }

        // Commit transaction
        $conn->commit();
        echo json_encode(['success' => true, 'receipt_no' => $receipt_no, 'message' => 'Receipt saved successfully']);

    } catch (Exception $e) {
        $conn->rollback();
        throw $e;
    }
} catch (Exception $e) {
    error_log("Error: " . $e->getMessage());
    echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}

$conn->close();
?>