<?php

require_once __DIR__ . '/Include/Config.php';
require_once __DIR__ . '/Include/PageInit.php';

use ChurchCRM\Authentication\AuthenticationManager;
use ChurchCRM\model\ChurchCRM\PersonQuery;
use ChurchCRM\model\ChurchCRM\PersonVolunteerOpportunityQuery;
use ChurchCRM\model\ChurchCRM\VolunteerOpportunity;
use ChurchCRM\model\ChurchCRM\VolunteerOpportunityQuery;
use ChurchCRM\Utils\CSRFUtils;
use ChurchCRM\Utils\InputUtils;
use ChurchCRM\Utils\RedirectUtils;
use ChurchCRM\view\PageHeader;

// Security: User must have proper permission
// For now ... require $bAdmin
// Future ... $bManageVol
AuthenticationManager::redirectHomeIfNotAdmin();

// top down design....
// title line
// separator line
// warning line
// first input line: [ Save Changes ] [ Exit ]
// column titles
// first record: text box with order, up, down, delete ; Name, Desc, Active radio buttons
// and so on
// action is change of order number, up, down, delete, Name, Desc, or Active, or Add New

$iOpp = -1;
$sAction = '';
$iRowNum = -1;
$bErrorFlag = false;
$aNameErrors = [];
$bNewNameError = false;

if (array_key_exists('act', $_GET) || array_key_exists('act', $_POST)) {
    $sAction = InputUtils::legacyFilterInput($_GET['act'] ?? $_POST['act'] ?? '');
}
if (array_key_exists('Opp', $_GET) || array_key_exists('Opp', $_POST)) {
    $iOpp = InputUtils::filterInt($_GET['Opp'] ?? $_POST['Opp'] ?? -1);
}
if (array_key_exists('row_num', $_GET)) {
    $iRowNum = InputUtils::filterInt($_GET['row_num']);
}

$sDeleteError = '';

if ($sAction === 'delete' && $iOpp > 0) {
    // Delete Confirmation Page

    // Security: User must have Delete records permission
    // Otherwise, redirect to the main menu
    AuthenticationManager::redirectHomeIfFalse(AuthenticationManager::getCurrentUser()->isDeleteRecordsEnabled(), 'DeleteRecords');

    $opp = VolunteerOpportunityQuery::create()->findPk((int) $iOpp);
    if ($opp === null) {
        RedirectUtils::redirect('VolunteerOpportunityEditor.php');
    }
    $vol_Order = $opp->getOrder();
    $vol_Name = $opp->getName();
    $vol_Description = $opp->getDescription();

    $sPageTitle = gettext('Volunteer Opportunity Delete Confirmation');
    require_once __DIR__ . '/Include/Header.php';
?>
    <div class="row justify-content-center mt-2">
        <div class="col-md-6">
                <div class="card border-danger">
                    <div class="card-status-top bg-danger"></div>
                    <div class="card-header">
                        <h5 class="mb-0">
                            <i class="fa-solid fa-triangle-exclamation"></i>
                            <?= gettext('Confirm Volunteer Opportunity Deletion') ?>
                        </h5>
                    </div>
                    <div class="card-body">
                        <div class="alert alert-warning" role="alert">
                            <i class="fa-solid fa-triangle-exclamation"></i>
                            <?= gettext('Please confirm deletion of') ?>:
                        </div>
                        <table class="table table-sm">
                            <tr>
                                <th><?= gettext('Order') ?></th>
                                <th><?= gettext('Name') ?></th>
                                <th><?= gettext('Description') ?></th>
                            </tr>
                            <tr>
                                <td><span class="badge bg-light text-dark"><?= $vol_Order ?></span></td>
                                <td><?= InputUtils::escapeHTML($vol_Name) ?></td>
                                <td><?= InputUtils::escapeHTML($vol_Description) ?></td>
                            </tr>
                        </table>
                        <?php
                        $assignments = PersonVolunteerOpportunityQuery::create()
                            ->filterByVolunteerOpportunityId((int) $iOpp)
                            ->find();
                        $assignedPersonIds = [];
                        foreach ($assignments as $assignment) {
                            $assignedPersonIds[] = $assignment->getPersonId();
                        }
                        if (!empty($assignedPersonIds)) {
                            $assignedPeople = PersonQuery::create()
                                ->filterById($assignedPersonIds)
                                ->orderByLastName()
                                ->orderByFirstName()
                                ->find();
                            echo "<div class='alert alert-warning mt-3' role='alert'><i class='fa-solid fa-circle-exclamation'></i> <strong>" . gettext('Warning') . "!</strong>" . gettext('There are people assigned to this Volunteer Opportunity. Deletion will unassign') . ':' . "</div>";
                            echo "<div class='ms-3 mb-3'>";
                            foreach ($assignedPeople as $person) {
                                echo "<div><i class='fa-solid fa-person'></i>" . InputUtils::escapeHTML($person->getFirstName()) . " " . InputUtils::escapeHTML($person->getLastName()) . "</div>";
                            }
                            echo "</div>";
                        }
                        ?>
                        <div class="d-flex justify-content-center mt-4">
                            <form method="POST" action="VolunteerOpportunityEditor.php" class="d-inline me-2">
                                <input type="hidden" name="act" value="ConfDelete">
                                <input type="hidden" name="Opp" value="<?= $iOpp ?>">
                                <?= CSRFUtils::getTokenInputField('deleteVolunteerOpportunity') ?>
                                <button type="submit" class="btn btn-danger">
                                    <i class="fa-solid fa-trash"></i>
                                    <?= gettext('Yes, delete') ?>
                                </button>
                            </form>
                            <a href="VolunteerOpportunityEditor.php" class="btn btn-secondary">
                                <i class="fa-solid fa-ban"></i>
                                <?= gettext('No, cancel this deletion') ?>
                            </a>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    <?php
    require_once __DIR__ . '/Include/Footer.php';
    exit;
}

if ($sAction === 'ConfDelete' && $iOpp > 0) {
    // Security: User must have Delete records permission
    // Otherwise, redirect to the main menu
    AuthenticationManager::redirectHomeIfFalse(AuthenticationManager::getCurrentUser()->isDeleteRecordsEnabled(), 'DeleteRecords');

    // Verify CSRF token for POST requests
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        if (!CSRFUtils::verifyRequest($_POST, 'deleteVolunteerOpportunity')) {
            http_response_code(403);
            die(gettext('Invalid CSRF token'));
        }
    }

    // get the order value for the record being deleted
    $oppToDelete = VolunteerOpportunityQuery::create()->findPk((int) $iOpp);
    if ($oppToDelete === null) {
        RedirectUtils::redirect('VolunteerOpportunityEditor.php');
    }
    $orderVal = $oppToDelete->getOrder();

    // delete the opportunity and its person assignments
    $oppToDelete->delete();
    PersonVolunteerOpportunityQuery::create()
        ->filterByVolunteerOpportunityId((int) $iOpp)
        ->delete();

    // pull back all the vol_Order fields that are higher than the one just deleted
    $higherOpps = VolunteerOpportunityQuery::create()
        ->filterByOrder($orderVal, \Propel\Runtime\ActiveQuery\Criteria::GREATER_EQUAL)
        ->find();
    foreach ($higherOpps as $higherOpp) {
        $higherOpp->setOrder($higherOpp->getOrder() - 1);
        $higherOpp->save();
    }
}

if ($iRowNum === 0) {
    // Skip data integrity check if we are only changing the ordering
    // by moving items up or down.
    // System response is too slow to do these checks every time the page
    // is viewed.

    // Data integrity checks performed when adding or deleting records.
    // Also on initial page view

    // Data integrity check #1
    // The default value of `vol_Order` is '0'.  But '0' is not assigned.
    // If we find a '0' add it to the end of the list by changing it to
    // MAX(vol_Order)+1.

    $zeroOrderOpps = VolunteerOpportunityQuery::create()
        ->filterByOrder(0)
        ->orderById()
        ->find();
    if ($zeroOrderOpps->count() > 0) {
        $maxOrder = VolunteerOpportunityQuery::create()
            ->orderByOrder(\Propel\Runtime\ActiveQuery\Criteria::DESC)
            ->findOne();
        $maxOrderVal = $maxOrder ? $maxOrder->getOrder() : 0;
        $rowNum = 1;
        foreach ($zeroOrderOpps as $zeroOpp) {
            $zeroOpp->setOrder($maxOrderVal + $rowNum);
            $zeroOpp->save();
            $rowNum++;
        }
    }

    // Data integrity check #2
    // re-order the vol_Order field just in case there is a missing number(s)
    $allOpps = VolunteerOpportunityQuery::create()->orderByOrder()->find();

    $orderCounter = 1;
    foreach ($allOpps as $volOpp) {
        if ($orderCounter !== (int) $volOpp->getOrder()) {
            $volOpp->setOrder($orderCounter);
            $volOpp->save();
        }
        ++$orderCounter;
    }
}

$sPageTitle = gettext('Volunteer Opportunity Editor');
$sPageSubtitle = gettext('Create or edit volunteer positions');

$aBreadcrumbs = PageHeader::breadcrumbs([
    [gettext('Admin'), '/admin/'],
    [gettext('Volunteer Opportunities')],
]);
require_once __DIR__ . '/Include/Header.php';
?>

<p class="text-body-secondary mb-3"><?= gettext('Manage volunteer opportunities and assign members') ?></p>

<?php

// Does the user want to save changes to text fields?
if (isset($_POST['SaveChanges'])) {
    $allVolOpps = VolunteerOpportunityQuery::create()->orderByOrder()->find();
    $numRows = $allVolOpps->count();

    $oppIndex = 0;
    for ($iFieldID = 1; $iFieldID <= $numRows; $iFieldID++) {
        $nameName = $iFieldID . 'name';
        $descName = $iFieldID . 'desc';
        if (array_key_exists($nameName, $_POST)) {
            $aNameFields[$iFieldID] = InputUtils::legacyFilterInput($_POST[$nameName]);

            if (strlen($aNameFields[$iFieldID]) === 0) {
                $aNameErrors[$iFieldID] = true;
                $bErrorFlag = true;
            } else {
                $aNameErrors[$iFieldID] = false;
            }

            $aDescFields[$iFieldID] = InputUtils::legacyFilterInput($_POST[$descName]);

            if (isset($allVolOpps[$oppIndex])) {
                $aIDFields[$iFieldID] = $allVolOpps[$oppIndex]->getId();
            }
            $oppIndex++;
        }
    }

    // If no errors, then update.
    if (!$bErrorFlag) {
        for ($iFieldID = 1; $iFieldID <= $numRows; $iFieldID++) {
            if (array_key_exists($iFieldID, $aNameFields)) {
                $volunteerOpp = VolunteerOpportunityQuery::create()->findOneById($aIDFields[$iFieldID]);
                $volunteerOpp
                    ->setName($aNameFields[$iFieldID])
                    ->setDescription($aDescFields[$iFieldID]);
                $volunteerOpp->save();
            }
        }
    }
} else {
    if (isset($_POST['AddField'])) { // Check if we're adding a VolOp
        $newFieldName = InputUtils::legacyFilterInput($_POST['newFieldName']);
        $newFieldDesc = InputUtils::legacyFilterInput($_POST['newFieldDesc']);
        if (strlen($newFieldName) === 0) {
            $bNewNameError = true;
        } else { // Insert into table
            $numRows = VolunteerOpportunityQuery::create()->count();
            $newOrder = $numRows + 1;

            $volunteerOpp = new VolunteerOpportunity();
            $volunteerOpp
                ->setOrder($newOrder)
                ->setName($newFieldName)
                ->setDescription($newFieldDesc);
            $volunteerOpp->save();

            $bNewNameError = false;
        }
    }
    // Get data for the form as it now exists
    $formOpps = VolunteerOpportunityQuery::create()->orderByOrder()->find();
    $numRows = $formOpps->count();

    // Create arrays of Volunteer Opportunities
    foreach ($formOpps as $volOpp) {
        $rowIndex = $volOpp->getOrder();
        $aIDFields[$rowIndex] = $volOpp->getId();
        $aNameFields[$rowIndex] = $volOpp->getName();
        $aDescFields[$rowIndex] = $volOpp->getDescription();
    }
}

// Construct the form
    ?>
    <form method="post" action="VolunteerOpportunityEditor.php" name="OppsEditor">

                <div class="card mb-4">
                    <div class="card-status-top bg-success"></div>
                    <div class="card-header">
                        <h5 class="mb-0">
                            <i class="fa-solid fa-plus"></i>
                            <?= gettext('Add New Volunteer Opportunity') ?>
                        </h5>
                    </div>
                    <div class="card-body">
                        <div class="row">
                            <div class="col-md-6">
                                <div class="mb-3">
                                    <label class="form-label" for="newFieldName"><?= gettext('Name') ?></label>
                                    <input type="text" id="newFieldName" name="newFieldName" maxlength="30" class="form-control form-control-sm">
                                    <?php if ($bNewNameError) {
                                        echo '<small class="text-danger d-block mt-1"><i class="fa-solid fa-circle-exclamation"></i> ' . gettext('You must enter a name') . '</small>';
                                    } ?>
                                </div>
                            </div>
                            <div class="col-md-6">
                                <div class="mb-3">
                                    <label class="form-label" for="newFieldDesc"><?= gettext('Description') ?></label>
                                    <input type="text" id="newFieldDesc" name="newFieldDesc" maxlength="100" class="form-control form-control-sm">
                                </div>
                            </div>
                        </div>
                        <div class="text-center">
                            <button type="submit" class="btn btn-success" name="AddField">
                                <i class="fa-solid fa-plus"></i>
                                <?= gettext('Add New Opportunity') ?>
                            </button>
                        </div>
                    </div>
                </div>

                <?php
                if ($numRows === 0) {
                ?>
                    <div class="alert alert-info" role="alert">
                        <i class="fa-solid fa-circle-info"></i>
                        <?= gettext('No volunteer opportunities have been added yet') ?>
                    </div>
                <?php
                } else {
                    // if an 'action' (up/down arrow clicked, or order was input)
                    if ($iRowNum && $sAction !== '') {
                        // cast as int and couple with switch for sql injection prevention for $row_num
                        $swapRow = $iRowNum;
                        if ($sAction === 'up') {
                            $newRow = --$iRowNum;
                        } elseif ($sAction === 'down') {
                            $newRow = ++$iRowNum;
                        } else {
                            $newRow = $iRowNum;
                        }

                        if (array_key_exists($swapRow, $aIDFields)) {
                            $volunteerOpp = VolunteerOpportunityQuery::create()->findOneById($aIDFields[$swapRow]);
                            $volunteerOpp->setOrder($newRow);
                            $volunteerOpp->save();
                        }

                        if (array_key_exists($newRow, $aIDFields)) {
                            $volunteerOpp = VolunteerOpportunityQuery::create()->findOneById($aIDFields[$newRow]);
                            $volunteerOpp->setOrder($swapRow);
                            $volunteerOpp->save();
                        }

                        // now update internal data to match
                        if (array_key_exists($swapRow, $aIDFields)) {
                            $saveID = $aIDFields[$swapRow];
                            $saveName = $aNameFields[$swapRow];
                            $saveDesc = $aDescFields[$swapRow];
                            $aIDFields[$newRow] = $saveID;
                            $aNameFields[$newRow] = $saveName;
                            $aDescFields[$newRow] = $saveDesc;
                        }

                        if (array_key_exists($newRow, $aIDFields)) {
                            $aIDFields[$swapRow] = $aIDFields[$newRow];
                            $aNameFields[$swapRow] = $aNameFields[$newRow];
                            $aDescFields[$swapRow] = $aDescFields[$newRow];
                        }
                    }
                ?>

                <div class="alert alert-info" role="alert">
                    <i class="fa-solid fa-circle-info me-1"></i>
                    <?= gettext('Name changes require saving. Reorder and delete actions in the action menu take effect immediately.') ?>
                </div>

                <?php
                if ($bErrorFlag) {
                    echo '<div class="alert alert-danger" role="alert"><i class="fa-solid fa-circle-exclamation"></i> <strong>' . gettext('Error') . ':</strong> ' . gettext('Invalid fields or selections. Changes not saved! Please correct and try again!') . '</div>';
                }
                if (strlen($sDeleteError) > 0) {
                    echo '<div class="alert alert-danger" role="alert"><i class="fa-solid fa-circle-exclamation"></i> <strong>' . gettext('Error') . ':</strong> ' . $sDeleteError . '</div>';
                }
                ?>

                <div class="card">
                    <div class="card-header d-flex align-items-center">
                        <h5 class="mb-0">
                            <i class="fa-solid fa-list me-2"></i>
                            <?= gettext('Existing Volunteer Opportunities') ?>
                        </h5>
                        <span class="badge bg-info text-white ms-auto"><?= $numRows ?> <?= gettext('opportunities') ?></span>
                    </div>
                    <div class="card-body" style="overflow: visible;">
                        <table class="table table-hover table-sm">
                            <thead>
                                <tr>
                                    <th><?= gettext('Order') ?></th>
                                    <th><?= gettext('Name') ?></th>
                                    <th><?= gettext('Description') ?></th>
                                    <th class="text-center no-export w-1"><?= gettext('Actions') ?></th>
                                </tr>
                            </thead>
                            <tbody>

                        <?php
                        for ($row = 1; $row <= $numRows; $row++) {
                            if (array_key_exists($row, $aNameFields)) {
                                echo '<tr>';
                                echo '<td><span class="badge bg-light text-dark">' . $row . '</span></td>';
                                echo '<td>';
                                echo '<input type="text" name="' . $row . 'name" value="' . InputUtils::escapeAttribute($aNameFields[$row]) . '" class="form-control form-control-sm" maxlength="30">';
                                if (array_key_exists($row, $aNameErrors) && $aNameErrors[$row]) {
                                    echo '<small class="text-danger d-block mt-1"><i class="fa-solid fa-circle-exclamation"></i> ' . gettext('You must enter a name') . '</small>';
                                }
                                echo '</td>';
                                echo '<td>';
                                echo '<input type="text" name="' . $row . 'desc" value="' . InputUtils::escapeAttribute($aDescFields[$row]) . '" class="form-control form-control-sm" maxlength="100">';
                                echo '</td>';
                                echo '<td class="w-1">';
                                echo '<div class="dropdown">';
                                echo '<button class="btn btn-sm btn-ghost-secondary" type="button" data-bs-toggle="dropdown" data-bs-display="static" aria-expanded="false">';
                                echo '<i class="ti ti-dots-vertical"></i>';
                                echo '</button>';
                                echo '<div class="dropdown-menu dropdown-menu-end">';
                                if ($row !== 1) {
                                    echo '<a href="VolunteerOpportunityEditor.php?act=up&amp;row_num=' . $row . '" class="dropdown-item"><i class="ti ti-arrow-up me-2"></i>' . gettext('Move up') . '</a>';
                                }
                                if ($row !== $numRows) {
                                    echo '<a href="VolunteerOpportunityEditor.php?act=down&amp;row_num=' . $row . '" class="dropdown-item"><i class="ti ti-arrow-down me-2"></i>' . gettext('Move down') . '</a>';
                                }
                                if ($row !== 1 || $row !== $numRows) {
                                    echo '<div class="dropdown-divider"></div>';
                                }
                                // False positive: $aIDFields[$row] is an ORM integer ID (not user input) and this constructs HTML, not SQL.
                                // The tainted-sql-string rule mis-classifies this HTML href as a SQL sink.
                                // nosemgrep: php.lang.security.injection.tainted-sql-string.tainted-sql-string
                                echo '<a href="VolunteerOpportunityEditor.php?act=delete&amp;Opp=' . $aIDFields[$row] . '" class="dropdown-item text-danger"><i class="ti ti-trash me-2"></i>' . gettext('Delete') . '</a>';
                                echo '</div>';
                                echo '</div>';
                                echo '</td>';
                                echo '</tr>';
                            }
                        }
                        ?>

                            </tbody>
                        </table>
                    </div>
                </div>

                <div class="d-flex mt-3 justify-content-center">
                    <button type="submit" class="btn btn-primary me-2" name="SaveChanges">
                        <i class="fa-solid fa-floppy-disk"></i>
                        <?= gettext('Save Changes') ?>
                    </button>
                    <button type="button" class="btn btn-secondary" name="Exit" onclick="document.location='v2/dashboard'">
                        <i class="fa-solid fa-arrow-right-from-bracket"></i>
                        <?= gettext('Exit') ?>
                    </button>
                </div>
        <?php } ?>
    </form>
    <?php
    require_once __DIR__ . '/Include/Footer.php';
