<?php
/**
 * Record offering. Personal funds (e.g. tithes) require selecting a member.
 * Supports AJAX POST: returns JSON and exits (no redirect) when X-Requested-With: XMLHttpRequest.
 */

$isAjax = !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
$errors = [];
require_once __DIR__ . '/../../includes/settings.php';
require_once __DIR__ . '/../../includes/receipts.php';
require_once __DIR__ . '/../../includes/audit.php';
try {
    $funds = $pdo->query('SELECT id, name, COALESCE(is_personal, 0) AS is_personal FROM funds ORDER BY name')->fetchAll();
} catch (PDOException $e) {
    $funds = $pdo->query('SELECT id, name FROM funds ORDER BY name')->fetchAll();
    foreach ($funds as &$f) { $f['is_personal'] = 0; }
    unset($f);
}
$members = $pdo->query('SELECT id, first_name, last_name FROM members ORDER BY last_name, first_name')->fetchAll();

// JSON member search for the Record Offering page (search-by-name, no full dropdown)
if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['search']) && isset($_GET['q'])) {
    header('Content-Type: application/json; charset=utf-8');
    $q = trim($_GET['q'] ?? '');
    $out = ['members' => []];
    if (strlen($q) >= 2) {
        $term = '%' . $q . '%';
        $stmt = $pdo->prepare("
            SELECT id, first_name, last_name
            FROM members
            WHERE (status != 'deceased' OR status IS NULL) AND (date_of_death IS NULL)
            AND (first_name LIKE ? OR last_name LIKE ? OR CONCAT(COALESCE(first_name,''), ' ', COALESCE(last_name,'')) LIKE ? OR CONCAT(COALESCE(last_name,''), ' ', COALESCE(first_name,'')) LIKE ?)
            ORDER BY last_name, first_name
            LIMIT 25
        ");
        $stmt->execute([$term, $term, $term, $term]);
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            $name = trim(($row['first_name'] ?? '') . ' ' . ($row['last_name'] ?? ''));
            $out['members'][] = ['id' => (int)$row['id'], 'name' => $name];
        }
    }
    echo json_encode($out);
    exit;
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Ensure transactions.member_id exists for personal offerings
    try {
        $pdo->query('SELECT member_id FROM transactions LIMIT 1');
    } catch (PDOException $e) {
        if (strpos($e->getMessage(), 'Unknown column') !== false) {
            $pdo->exec('ALTER TABLE transactions ADD COLUMN member_id INT NULL AFTER fund_id');
        } else {
            throw $e;
        }
    }
    // Ensure transactions.service exists (1st / 2nd service)
    try {
        $pdo->query('SELECT service FROM transactions LIMIT 1');
    } catch (PDOException $e) {
        if (strpos($e->getMessage(), 'Unknown column') !== false) {
            $pdo->exec("ALTER TABLE transactions ADD COLUMN service VARCHAR(20) NULL DEFAULT NULL AFTER transaction_date");
        } else {
            throw $e;
        }
    }

    $fund_id_raw = trim($_POST['fund_id'] ?? '');
    $fund_other_name = trim($_POST['fund_other_name'] ?? '');
    $fund_id = null;
    if ($fund_id_raw === 'other') {
        if ($fund_other_name === '') {
            $errors[] = 'Please specify the offering type for "Others".';
        } else {
            $stmt = $pdo->prepare('SELECT id FROM funds WHERE name = ?');
            $stmt->execute([$fund_other_name]);
            $row = $stmt->fetch();
            if ($row) {
                $fund_id = (int) $row['id'];
            } else {
                $pdo->prepare('INSERT INTO funds (name, description) VALUES (?, ?)')->execute([$fund_other_name, 'Other (user-specified)']);
                $fund_id = (int) $pdo->lastInsertId();
            }
        }
    } else {
        $fund_id = (int) $fund_id_raw;
    }

    $member_id = !empty($_POST['member_id']) ? (int) $_POST['member_id'] : null;
    $amount = trim($_POST['amount'] ?? '');
    $transaction_date = trim($_POST['transaction_date'] ?? '');
    $service = trim($_POST['service'] ?? '');
    if ($service !== '1st' && $service !== '2nd') $service = null;
    $note = trim($_POST['note'] ?? '');

    if (($fund_id === null || $fund_id <= 0) && $fund_id_raw !== 'other') {
        $errors[] = 'Please select a fund or specify an offering type under Others.';
    }
    $selectedFund = null;
    foreach ($funds as $f) {
        if ((int)$f['id'] === $fund_id) { $selectedFund = $f; break; }
    }
    if ($selectedFund === null && $fund_id > 0) {
        $stmt = $pdo->prepare('SELECT id, name, COALESCE(is_personal, 0) AS is_personal FROM funds WHERE id = ?');
        $stmt->execute([$fund_id]);
        $selectedFund = $stmt->fetch();
    }
    if ($selectedFund && !empty($selectedFund['is_personal'])) {
        if (!$member_id) $errors[] = 'Please select the member for this personal offering.';
    }
    if (!is_numeric($amount) || (float)$amount <= 0) $errors[] = 'Please enter a valid amount.';
    if (empty($transaction_date)) $errors[] = 'Date is required.';

    if (empty($errors)) {
        $usedMemberId = $member_id ?: null;
        try {
            $stmt = $pdo->prepare('INSERT INTO transactions (fund_id, member_id, amount, transaction_date, service, note, created_by) VALUES (?, ?, ?, ?, ?, ?, ?)');
            $stmt->execute([
                $fund_id,
                $usedMemberId,
                (float)$amount,
                $transaction_date,
                $service,
                $note ?: null,
                currentUserId()
            ]);
        } catch (PDOException $e) {
            $usedMemberId = null;
            try {
                $stmt = $pdo->prepare('INSERT INTO transactions (fund_id, amount, transaction_date, service, note, created_by) VALUES (?, ?, ?, ?, ?, ?)');
                $stmt->execute([
                    $fund_id,
                    (float)$amount,
                    $transaction_date,
                    $service,
                    $note ?: null,
                    currentUserId()
                ]);
            } catch (PDOException $e2) {
                $stmt = $pdo->prepare('INSERT INTO transactions (fund_id, amount, transaction_date, note, created_by) VALUES (?, ?, ?, ?, ?)');
                $stmt->execute([
                    $fund_id,
                    (float)$amount,
                    $transaction_date,
                    $note ?: null,
                    currentUserId()
                ]);
            }
        }

        $transactionId = $pdo->lastInsertId();
        
        // Generate receipt before redirect so we can pass receipt_id to show in modal (personal offerings)
        $generatedReceiptId = null;
        $isPersonalOffering = $member_id && $selectedFund && !empty($selectedFund['is_personal']);
        $autoReceipt = getSetting('finance_auto_receipt', '0') === '1';
        $shouldGenerateReceipt = $isPersonalOffering || $autoReceipt;
        if ($shouldGenerateReceipt) {
            require_once __DIR__ . '/../../includes/receipts.php';
            $autoEmailReceipt = getSetting('finance_auto_email_receipt', '0') === '1';
            try {
                $generatedReceiptId = generateReceipt($transactionId, $autoEmailReceipt);
            } catch (Exception $e) {
                error_log('Receipt generation error: ' . $e->getMessage());
            }
        }

        // Audit log (best-effort)
        try {
            $fundName = $selectedFund['name'] ?? null;
            if (!$fundName && $fund_id) {
                $s = $pdo->prepare('SELECT name FROM funds WHERE id=?');
                $s->execute([$fund_id]);
                $fundName = $s->fetchColumn() ?: null;
            }
            logActivity(
                'finance_transaction_recorded',
                'Recorded offering' . ($fundName ? " for {$fundName}" : '') . ' on ' . $transaction_date,
                [
                    'transaction_id' => (int)$transactionId,
                    'fund_id' => (int)$fund_id,
                    'fund_name' => $fundName,
                    'member_id' => $usedMemberId ? (int)$usedMemberId : null,
                    'amount' => (float)$amount,
                    'transaction_date' => $transaction_date,
                    'service' => $service,
                    'receipt_id' => $generatedReceiptId ? (int)$generatedReceiptId : null,
                ]
            );
        } catch (Throwable $e) {}
        
        // Return response immediately for better performance
        if ($isAjax) {
            header('Content-Type: application/json; charset=utf-8');
            echo json_encode([
                'success' => true,
                'message' => 'Offering recorded successfully.',
                'receipt_id' => $generatedReceiptId ? (int)$generatedReceiptId : null
            ]);
            // Close connection to browser but continue processing
            if (function_exists('fastcgi_finish_request')) {
                fastcgi_finish_request();
            } elseif (function_exists('apache_setenv')) {
                apache_setenv('no-gzip', 1);
            }
        } else {
            $redirectUrl = BASE_PATH . '/finance?toast=' . urlencode('Offering recorded successfully.');
            if ($generatedReceiptId && $isPersonalOffering) {
                $redirectUrl .= '&receipt_id=' . (int)$generatedReceiptId;
            }
            header('Location: ' . $redirectUrl);
            // Close connection to browser but continue processing
            if (function_exists('fastcgi_finish_request')) {
                fastcgi_finish_request();
            } elseif (function_exists('apache_setenv')) {
                apache_setenv('no-gzip', 1);
            }
        }
        
        // Notifications in background (non-blocking)

        // Send SMS and email for personal offerings (non-blocking)
        if ($member_id && $selectedFund) {
            try {
                $member = $pdo->prepare('SELECT first_name, last_name, phone, email FROM members WHERE id = ?');
                $member->execute([$member_id]);
                $member = $member->fetch();
                if ($member) {
                    require_once __DIR__ . '/../../includes/settings.php';
                    require_once __DIR__ . '/../../includes/sms.php';
                    require_once __DIR__ . '/../../includes/mail.php';

                    $fundName = $selectedFund['name'];
                    $amountFormatted = number_format((float)$amount, 2);
                    $churchName = defined('SITE_FULL_NAME') ? SITE_FULL_NAME : 'PCG Nazareth';
                    $shortName = defined('SITE_NAME') ? SITE_NAME : 'Nazareth';
                    $memberName = trim(($member['first_name'] ?? '') . ' ' . ($member['last_name'] ?? '')) ?: ($member['first_name'] ?? '');

                    $replace = [
                        '{member_name}' => $memberName,
                        '{fund_name}'   => $fundName,
                        '{amount}'      => $amountFormatted,
                        '{church}'      => $shortName,
                    ];

                    $smsTpl = getSetting('finance_receipt_sms', '');
                    $smsMessage = $smsTpl !== ''
                        ? str_replace(array_keys($replace), array_values($replace), $smsTpl)
                        : "Your {$fundName} of GH¢ {$amountFormatted} has been received. Thank you. — {$shortName}";
                    $smsMessage = mb_substr($smsMessage, 0, 160);

                    $subjTpl = getSetting('finance_receipt_email_subject', '');
                    $emailSubject = $subjTpl !== ''
                        ? str_replace(array_keys($replace), array_values($replace), $subjTpl)
                        : "Your {$fundName} has been received";

                    $bodyTpl = getSetting('finance_receipt_email_body', '');
                    $emailBody = $bodyTpl !== ''
                        ? str_replace(array_keys($replace), array_values($replace), $bodyTpl)
                        : "Dear {$memberName},\n\nYour {$fundName} of GH¢ {$amountFormatted} has been received with thanks.\n\n— {$churchName}";
                    $bodyEscaped = htmlspecialchars($emailBody, ENT_QUOTES, 'UTF-8');
                    $bodyWithBreaks = nl2br($bodyEscaped, false);
                    $contentHtml = '<div style="margin:0;">' . $bodyWithBreaks . '</div>';
                    $emailBodyHtml = wrapReceiptEmailHtml($contentHtml, $churchName);

                    $sendSms = getSetting('finance_receipt_send_sms', '1') === '1';
                    $sendEmail = getSetting('finance_receipt_send_email', '1') === '1';

                    // Send SMS and email (non-blocking with timeouts)
                    if ($sendSms && !empty($member['phone'])) {
                        try {
                            sendSms($member['phone'], $smsMessage);
                        } catch (Exception $e) {
                            error_log('SMS sending error: ' . $e->getMessage());
                        }
                    }
                    if ($sendEmail && !empty($member['email'])) {
                        try {
                            sendMail($member['email'], $emailSubject, $emailBodyHtml, $emailBody);
                        } catch (Exception $e) {
                            error_log('Email sending error: ' . $e->getMessage());
                        }
                    }
                }
            } catch (Exception $e) {
                error_log('Notification sending error: ' . $e->getMessage());
            }
        }
        
        exit;
    }
    if ($isAjax && !empty($errors)) {
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode(['success' => false, 'errors' => $errors]);
        exit;
    }
}

$pageTitle = 'Record Offering';
require_once __DIR__ . '/../../includes/header.php';
?>

<div class="header">
    <h1>Record Offering</h1>
    <div class="header-actions">
        <a href="<?= BASE_PATH ?>/finance">Back to Finance</a>
        <a href="<?= BASE_PATH ?>/logout">Logout</a>
    </div>
</div>

<?php if (!empty($errors)): ?>
    <div data-toast="error" data-toast-msg="<?= htmlspecialchars(implode(' ', $errors)) ?>" style="display:none"></div>
<?php endif; ?>

<div class="card" style="max-width: 420px; margin-left: auto; margin-right: auto;">
    <form method="post">
        <div class="form-group">
            <label for="fund_id">Fund *</label>
            <select id="fund_id" name="fund_id" required>
                <option value="">-- Select Fund --</option>
                <?php foreach ($funds as $f): ?>
                    <option value="<?= $f['id'] ?>" data-personal="<?= !empty($f['is_personal']) ? '1' : '0' ?>" <?= (isset($_POST['fund_id']) && $_POST['fund_id'] == $f['id']) ? 'selected' : '' ?>>
                        <?= htmlspecialchars($f['name']) ?><?= !empty($f['is_personal']) ? ' (personal)' : '' ?>
                    </option>
                <?php endforeach; ?>
                <option value="other" data-personal="0" <?= (isset($_POST['fund_id']) && $_POST['fund_id'] === 'other') ? 'selected' : '' ?>>Others (specify)</option>
            </select>
        </div>
        <div id="fund_other_group" class="form-group" style="display: none;">
            <label for="fund_other_name">Specify offering type *</label>
            <input type="text" id="fund_other_name" name="fund_other_name" placeholder="Easter offering, Harvest"
                value="<?= htmlspecialchars($_POST['fund_other_name'] ?? '') ?>">
            <small class="text-muted">Enter the name of the offering. It will be saved as a new offering type if it doesn’t exist.</small>
        </div>
        <div id="member_group" class="form-group" style="display: none;">
            <label for="member_search">Member *</label>
            <div class="member-search-wrap" style="max-width: 100%;">
                <input type="text" id="member_search" class="member-search-input" autocomplete="off" placeholder="Search by name (type at least 2 characters)..." aria-label="Search member">
                <input type="hidden" id="member_id" name="member_id" value="<?= htmlspecialchars($_POST['member_id'] ?? '') ?>">
                <div id="member_search_results" class="member-search-dropdown member-search-results-record" role="listbox" aria-label="Search results" hidden></div>
            </div>
            <p id="member_selected_display" class="text-muted" style="display: none; margin-top: 0.5rem; font-size: 0.875rem;">
                <span id="member_selected_name"></span>
                <button type="button" id="member_clear_btn" class="btn btn-sm btn-ghost" style="margin-left: 0.5rem;">Change</button>
            </p>
            <small class="text-muted">Required for personal offerings (e.g. tithes).</small>
        </div>
        <div class="form-group">
            <label for="amount">Amount (GH&#8373;) *</label>
            <input type="number" id="amount" name="amount" step="0.01" min="0.01" required
                value="<?= htmlspecialchars($_POST['amount'] ?? '') ?>">
        </div>
        <div class="form-group">
            <label for="transaction_date">Date *</label>
            <input type="date" id="transaction_date" name="transaction_date" required
                value="<?= htmlspecialchars($_POST['transaction_date'] ?? date('Y-m-d')) ?>">
        </div>
        <div class="form-group">
            <label for="service">Service</label>
            <select id="service" name="service">
                <option value="">— Select service —</option>
                <option value="1st" <?= (isset($_POST['service']) && $_POST['service'] === '1st') ? 'selected' : '' ?>>1st service</option>
                <option value="2nd" <?= (isset($_POST['service']) && $_POST['service'] === '2nd') ? 'selected' : '' ?>>2nd service</option>
            </select>
            <small class="text-muted">Which service this offering is for.</small>
        </div>
        <div class="form-group">
            <label for="note">Note</label>
            <textarea id="note" name="note"><?= htmlspecialchars($_POST['note'] ?? '') ?></textarea>
        </div>
        <button type="submit" class="btn">Record Offering</button>
        <a href="<?= BASE_PATH ?>/finance" class="btn btn-secondary">Cancel</a>
    </form>
</div>

<script>
(function() {
    var fundSelect = document.getElementById('fund_id');
    var memberGroup = document.getElementById('member_group');
    var memberIdInput = document.getElementById('member_id');
    var memberSearchInput = document.getElementById('member_search');
    var resultsEl = document.getElementById('member_search_results');
    var selectedDisplay = document.getElementById('member_selected_display');
    var selectedNameEl = document.getElementById('member_selected_name');
    var clearBtn = document.getElementById('member_clear_btn');
    var basePath = '<?= addslashes(BASE_PATH) ?>';
    var debounceTimer = null;

    var fundOtherGroup = document.getElementById('fund_other_group');
    var fundOtherName = document.getElementById('fund_other_name');

    function toggleMember() {
        var opt = fundSelect.options[fundSelect.selectedIndex];
        var val = opt ? opt.value : '';
        var personal = opt && opt.getAttribute('data-personal') === '1';
        var isOther = val === 'other';
        memberGroup.style.display = personal ? 'block' : 'none';
        memberIdInput.required = personal;
        if (fundOtherGroup && fundOtherName) {
            fundOtherGroup.style.display = isOther ? 'block' : 'none';
            fundOtherName.required = isOther;
            if (!isOther) fundOtherName.value = '';
        }
        if (!personal) {
            memberIdInput.value = '';
            memberSearchInput.value = '';
            selectedDisplay.style.display = 'none';
            resultsEl.hidden = true;
        }
    }

    function showResults(items) {
        resultsEl.innerHTML = '';
        resultsEl.classList.add('is-open');
        resultsEl.removeAttribute('hidden');
        if (!items || items.length === 0) {
            resultsEl.innerHTML = '<div class="autocomplete-item" style="color:#64748b;">No members found. Try another search.</div>';
            return;
        }
        items.forEach(function(m) {
            var btn = document.createElement('button');
            btn.type = 'button';
            btn.className = 'autocomplete-item';
            btn.setAttribute('role', 'option');
            btn.setAttribute('data-id', m.id);
            btn.setAttribute('data-name', m.name);
            btn.textContent = m.name;
            btn.style.cssText = 'display:block; width:100%; text-align:left; padding:0.5rem 0.875rem; border:none; background:transparent; cursor:pointer; font-size:0.9375rem;';
            btn.addEventListener('click', function() {
                memberIdInput.value = m.id;
                selectedNameEl.textContent = 'Selected: ' + m.name;
                selectedDisplay.style.display = 'block';
                memberSearchInput.value = '';
                memberSearchInput.placeholder = 'Change member (search again)';
                hideResults();
            });
            btn.addEventListener('mouseenter', function() { btn.style.background = '#f1f5f9'; });
            btn.addEventListener('mouseleave', function() { btn.style.background = 'transparent'; });
            resultsEl.appendChild(btn);
        });
    }

    function hideResults() {
        resultsEl.classList.remove('is-open');
        resultsEl.setAttribute('hidden', '');
        resultsEl.innerHTML = '';
    }

    function doSearch() {
        var q = (memberSearchInput.value || '').trim();
        if (q.length < 2) {
            resultsEl.hidden = true;
            resultsEl.innerHTML = '';
            return;
        }
        var xhr = new XMLHttpRequest();
        xhr.open('GET', basePath + '/finance/record?search=1&q=' + encodeURIComponent(q), true);
        xhr.onreadystatechange = function() {
            if (xhr.readyState !== 4) return;
            if (xhr.status === 200) {
                try {
                    var data = JSON.parse(xhr.responseText);
                    showResults(data.members || []);
                } catch (e) {
                    showResults([]);
                }
            } else {
                showResults([]);
            }
        };
        xhr.send();
    }

    memberSearchInput.addEventListener('input', function() {
        if (debounceTimer) clearTimeout(debounceTimer);
        if ((memberSearchInput.value || '').trim().length < 2) {
            hideResults();
            return;
        }
        debounceTimer = setTimeout(doSearch, 250);
    });

    memberSearchInput.addEventListener('focus', function() {
        if ((memberSearchInput.value || '').trim().length >= 2 && resultsEl.children.length) resultsEl.classList.add('is-open');
    });

    memberSearchInput.addEventListener('blur', function() {
        setTimeout(function() {
            var active = document.activeElement;
            if (active && resultsEl.contains(active)) return;
            hideResults();
        }, 200);
    });

    if (clearBtn) {
        clearBtn.addEventListener('click', function() {
            memberIdInput.value = '';
            selectedDisplay.style.display = 'none';
            memberSearchInput.placeholder = 'Search by name (type at least 2 characters)...';
            memberSearchInput.focus();
        });
    }

    fundSelect.addEventListener('change', toggleMember);
    toggleMember(); // init: show/hide Others field and member group

    // If we have a preselected member (e.g. form re-display after validation error), show "Selected" and hide search until Change
    var postMemberId = '<?= (isset($_POST['member_id']) && $_POST['member_id']) ? (int)$_POST['member_id'] : 0 ?>';
    if (postMemberId && memberGroup.style.display !== 'none') {
        var membersData = <?= json_encode(array_map(function($m) { return ['id' => (int)$m['id'], 'name' => trim($m['first_name'] . ' ' . $m['last_name'])]; }, $members)) ?>;
        var found = membersData.filter(function(m) { return String(m.id) === String(postMemberId); })[0];
        if (found) {
            memberIdInput.value = found.id;
            selectedNameEl.textContent = 'Selected: ' + found.name;
            selectedDisplay.style.display = 'block';
            memberSearchInput.placeholder = 'Change member (search again)';
        }
    }
})();
</script>

<?php require_once __DIR__ . '/../../includes/footer.php'; ?>
