<?php

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

use ChurchCRM\Authentication\AuthenticationManager;
use ChurchCRM\Bootstrapper;
use ChurchCRM\dto\SystemConfig;
use ChurchCRM\dto\SystemURLs;
use ChurchCRM\model\ChurchCRM\Family;
use ChurchCRM\model\ChurchCRM\FamilyQuery;
use ChurchCRM\model\ChurchCRM\ListOptionQuery;
use ChurchCRM\Service\FamilyService;
use ChurchCRM\model\ChurchCRM\Map\FamilyTableMap;
use ChurchCRM\model\ChurchCRM\Person;
use ChurchCRM\model\ChurchCRM\PersonCustom;
use ChurchCRM\model\ChurchCRM\PersonQuery;
use ChurchCRM\Utils\CustomFieldUtils;
use ChurchCRM\Utils\DateTimeUtils;
use ChurchCRM\Utils\InputUtils;
use ChurchCRM\Utils\MiscUtils;
use ChurchCRM\Utils\RedirectUtils;
use ChurchCRM\view\PageHeader;

$sPageTitle = gettext('Family Editor');
$sPageSubtitle = gettext('Create and edit family information and relationships');

$iFamilyID = -1;
$family = null;

// Get the FamilyID from the querystring
if (array_key_exists('FamilyID', $_GET)) {
    $iFamilyID = InputUtils::legacyFilterInput($_GET['FamilyID'], 'int');
}

// Security: User must have Add or Edit Records permission to use this form in those manners
// Clean error handling: (such as somebody typing an incorrect URL ?PersonID= manually)
if ($iFamilyID > 0) {
    if (!( AuthenticationManager::getCurrentUser()->isEditRecordsEnabled() || AuthenticationManager::getCurrentUser()->isEditSelfEnabled() && $iFamilyID == AuthenticationManager::getCurrentUser()->getPerson()->getFamId())) {
        RedirectUtils::securityRedirect('EditRecords');
    }

    $family = FamilyQuery::create()->findOneById($iFamilyID);
    if ($family === null) {
        RedirectUtils::redirect('v2/dashboard');
    }
} elseif (!AuthenticationManager::getCurrentUser()->isAddRecordsEnabled()) {
    RedirectUtils::securityRedirect('AddRecords');
}

// Get the list of custom person fields
$sSQL = 'SELECT family_custom_master.* FROM family_custom_master ORDER BY fam_custom_Order';
$rsCustomFields = RunQuery($sSQL);
$numCustomFields = mysqli_num_rows($rsCustomFields);

// Get Field Security List Matrix
$sSQL = 'SELECT * FROM list_lst WHERE lst_ID = 5 ORDER BY lst_OptionSequence';
$rsSecurityGrp = RunQuery($sSQL);

while ($aRow = mysqli_fetch_array($rsSecurityGrp)) {
    extract($aRow);
    $aSecurityType[$lst_OptionID] = $lst_OptionName;
}

$bErrorFlag = false;
$sNameError = '';
$sEmailError = '';
$sWeddingDateError = '';

$sName = '';

$UpdateBirthYear = 0;

$aFirstNameError = [];
$aBirthDateError = [];
$aperFlags = [];

//Is this the second pass?
if (isset($_POST['FamilySubmit']) || isset($_POST['FamilySubmitAndAdd'])) {
    //Assign everything locally
    $sName = InputUtils::legacyFilterInput($_POST['Name']);
    // Strip commas out of address fields because they are problematic when
    // exporting addresses to CSV file
    $sAddress1 = str_replace(',', '', InputUtils::legacyFilterInput($_POST['Address1']));
    $sAddress2 = str_replace(',', '', InputUtils::legacyFilterInput($_POST['Address2']));
    $sCity = InputUtils::legacyFilterInput($_POST['City']);
    $sZip = InputUtils::legacyFilterInput($_POST['Zip']);

    if (SystemConfig::getBooleanValue('bForceUppercaseZip')) {
        $sZip = strtoupper($sZip);
    }

    $sCountry = InputUtils::legacyFilterInput($_POST['Country']);
    $iFamilyMemberRows = InputUtils::legacyFilterInput($_POST['FamCount']);

    $sState = InputUtils::legacyFilterInput($_POST[$_POST['stateType'] === 'dropDown' ? 'State' : 'StateTextbox']);

    $sHomePhone = InputUtils::legacyFilterInput($_POST['HomePhone']);
    $sEmail = InputUtils::legacyFilterInput($_POST['Email']);
    $bSendNewsLetter = isset($_POST['SendNewsLetter']);

    $nLatitude = 0.0;
    $nLongitude = 0.0;
    if (array_key_exists('Latitude', $_POST)) {
        $nLatitude = InputUtils::legacyFilterInput($_POST['Latitude'], 'float');
    }
    if (array_key_exists('Longitude', $_POST)) {
        $nLongitude = InputUtils::legacyFilterInput($_POST['Longitude'], 'float');
    }

    if (!is_numeric($nLatitude)) {
        $nLatitude = null;
    }

    if (!is_numeric($nLongitude)) {
        $nLongitude = null;
    }

    $nEnvelope = 0;
    if (array_key_exists('Envelope', $_POST)) {
        $nEnvelope = InputUtils::legacyFilterInput($_POST['Envelope'], 'int');
    }

    // Only integers are allowed as Envelope Numbers
    $nEnvelope = is_numeric($nEnvelope) && intval($nEnvelope) == floatval($nEnvelope)
        ? "'" . intval($nEnvelope) . "'"
        : "'0'";

    $iPropertyID = 0;
    if (array_key_exists('PropertyID', $_POST)) {
        $iPropertyID = InputUtils::legacyFilterInput($_POST['PropertyID'], 'int');
    }
    $dWeddingDate = InputUtils::legacyFilterInput($_POST['WeddingDate'] ?? '');

    $bNoFormat_HomePhone = isset($_POST['NoFormat_HomePhone']);

    //Loop through the Family Member 'quick entry' form fields
    for ($iCount = 1; $iCount <= $iFamilyMemberRows; $iCount++) {
        // Assign everything to arrays
        $aFirstNames[$iCount] = InputUtils::legacyFilterInput($_POST["FirstName$iCount"]);
        $aMiddleNames[$iCount] = InputUtils::legacyFilterInput($_POST["MiddleName$iCount"]);
        $aLastNames[$iCount] = InputUtils::legacyFilterInput($_POST["LastName$iCount"]);
        $aSuffix[$iCount] = InputUtils::legacyFilterInput($_POST["Suffix$iCount"]);
        $aRoles[$iCount] = InputUtils::legacyFilterInput($_POST["Role$iCount"], 'int');
        $aGenders[$iCount] = InputUtils::legacyFilterInput($_POST["Gender$iCount"], 'int');
        $aBirthDays[$iCount] = InputUtils::legacyFilterInput($_POST["BirthDay$iCount"], 'int');
        $aBirthMonths[$iCount] = InputUtils::legacyFilterInput($_POST["BirthMonth$iCount"], 'int');
        $aBirthYears[$iCount] = InputUtils::legacyFilterInput($_POST["BirthYear$iCount"], 'int');
        $aClassification[$iCount] = InputUtils::legacyFilterInput($_POST["Classification$iCount"], 'int');
        $aPersonIDs[$iCount] = InputUtils::legacyFilterInput($_POST["PersonID$iCount"], 'int');
        $aUpdateBirthYear[$iCount] = InputUtils::legacyFilterInput($_POST['UpdateBirthYear'], 'int');

        // Make sure first names were entered if editing existing family
        if ($iFamilyID > 0) {
            if (strlen($aFirstNames[$iCount]) === 0) {
                $aFirstNameError[$iCount] = gettext('First name must be entered');
                $bErrorFlag = true;
            }
        }

        // Validate any family member birthdays
        if ($aBirthMonths[$iCount] > 0 xor $aBirthDays[$iCount] > 0) {
            $aBirthDateError[$iCount] = gettext('Invalid Birth Date: Missing birth month or day.');
            $bErrorFlag = true;
        } elseif (strlen($aBirthYears[$iCount]) > 0 && $aBirthMonths[$iCount] === 0 && $aBirthDays[$iCount] === 0) {
            $aBirthDateError[$iCount] = gettext('Invalid Birth Date: Missing birth month and day.');
            $bErrorFlag = true;
        } elseif (strlen($aFirstNames[$iCount]) > 0 && strlen($aBirthYears[$iCount]) > 0) {
            if ($aBirthYears[$iCount] < 0) {
                $aBirthDateError[$iCount] = gettext('Invalid Year');
                $bErrorFlag = true;
            } elseif ($aBirthMonths[$iCount] > 0 && $aBirthDays[$iCount] > 0) {
                if (!checkdate($aBirthMonths[$iCount], $aBirthDays[$iCount], $aBirthYears[$iCount])) {
                    $aBirthDateError[$iCount] = gettext('Invalid Birth Date.');
                    $bErrorFlag = true;
                }
            }
        }
    }

    //Did they enter a name?
    if (strlen($sName) < 1) {
        $sNameError = gettext('You must enter a name');
        $bErrorFlag = true;
    }

    // Validate Wedding Date if one was entered
    $dateString = DateTimeUtils::parseAndValidate($dWeddingDate, Bootstrapper::getCurrentLocale()->getCountryCode(), $pasfut = 'past');
    if (strlen($dWeddingDate) > 0 && $dateString === false) {
        $sWeddingDateError = '<span class="text-danger">'
            . gettext('Not a valid Wedding Date') . '</span>';
        $bErrorFlag = true;
    } else {
        $dWeddingDate = $dateString;
    }

    // Validate Email
    if (strlen($sEmail) > 0) {
        if (MiscUtils::checkEmail($sEmail) === false) {
            $sEmailError = '<span class="text-danger">'
                . gettext('Email is Not Valid') . '</span>';
            $bErrorFlag = true;
            $sEmail = null;
        }
    }

    // Validate all the custom fields
    $aCustomData = [];
    while ($rowCustomField = mysqli_fetch_array($rsCustomFields, MYSQLI_BOTH)) {
        extract($rowCustomField);

        $currentFieldData = InputUtils::legacyFilterInput($_POST[$fam_custom_Field]);

        $bErrorFlag |= !CustomFieldUtils::validate($type_ID, $currentFieldData, $fam_custom_Field, $aCustomErrors);

        // assign processed value locally to $aPersonProps so we can use it to generate the form later
        $aCustomData[$fam_custom_Field] = $currentFieldData;
    }

    //If no errors, then let's update...
    if (!$bErrorFlag) {
        //Write the base SQL depending on the Action
        $bSendNewsLetterString = $bSendNewsLetter ? 'TRUE' : 'FALSE';

        $family = new Family();
        if ($iFamilyID >= 1) {
            $family = FamilyQuery::create()->findPk($iFamilyID);
            $family
                ->setDateLastEdited(date('YmdHis'))
                ->setEditedBy(AuthenticationManager::getCurrentUser()->getId());
        } else {
            $family
                ->setDateEntered(date('YmdHis'))
                ->setEnteredBy(AuthenticationManager::getCurrentUser()->getId());
        }
        $family
            ->setName($sName)
            ->setAddress1($sAddress1)
            ->setAddress2($sAddress2)
            ->setCity($sCity)
            ->setState($sState)
            ->setZip($sZip)
            ->setCountry($sCountry)
            ->setHomePhone($sHomePhone)
            ->setSendNewsletter($bSendNewsLetterString)
            ->setEnvelope($nEnvelope)
            ->setWeddingdate($dWeddingDate)
            ->setEmail($sEmail)
            ->setLatitude($nLatitude)
            ->setLongitude($nLongitude);

        // Capture address-changed flag BEFORE save() clears isColumnModified() flags
        $addressChanged = $family->isColumnModified(FamilyTableMap::COL_FAM_ADDRESS1)
            || $family->isColumnModified(FamilyTableMap::COL_FAM_ADDRESS2)
            || $family->isColumnModified(FamilyTableMap::COL_FAM_CITY)
            || $family->isColumnModified(FamilyTableMap::COL_FAM_STATE)
            || $family->isColumnModified(FamilyTableMap::COL_FAM_ZIP)
            || $family->isColumnModified(FamilyTableMap::COL_FAM_COUNTRY);

        // Update Lat/Long if address changes
        if (
            $addressChanged
            && !$family->isColumnModified(FamilyTableMap::COL_FAM_LATITUDE)
            && !$family->isColumnModified(FamilyTableMap::COL_FAM_LONGITUDE)
        ) {
            $family->setLatitude(null);
            $family->setLongitude(null);
        }

        $family->save();
        $family->reload();

        // Auto-geocode family if address was modified (use pre-save flag — isColumnModified is cleared after save)
        if ($addressChanged && empty($family->getLatitude())) {
            $familyService = new FamilyService();
            $familyService->autoGeocodeFamily($family);
        }

        //If the user added a new record, we need to key back to the route to the FamilyView page
        if ($iFamilyID < 1) {
            $iFamilyID = $family->getId();
            RunPreparedQuery('INSERT INTO `family_custom` (`fam_ID`) VALUES (?)', 'i', [$iFamilyID]);

            // Add property if assigned
            if ($iPropertyID) {
                RunPreparedQuery('INSERT INTO record2property_r2p (r2p_pro_ID, r2p_record_ID) VALUES (?, ?)', 'ii', [$iPropertyID, $iFamilyID]);
            }

            //Run through the family member arrays...
            for ($iCount = 1; $iCount <= $iFamilyMemberRows; $iCount++) {
                if (strlen($aFirstNames[$iCount]) > 0) {
                    if (strlen($aBirthYears[$iCount]) < 4) {
                        $aBirthYears[$iCount] = 'NULL';
                    }

                    //If no last name is entered for a member, use the family name.
                    $sLastNameToEnter = strlen($aLastNames[$iCount]) && $aLastNames[$iCount] != $sName
                        ? $aLastNames[$iCount]
                        : $sName;

                    $person = new Person();
                    $person
                        ->setFirstName($aFirstNames[$iCount])
                        ->setMiddleName($aMiddleNames[$iCount])
                        ->setLastName($sLastNameToEnter)
                        ->setSuffix($aSuffix[$iCount])
                        ->setFamId($iFamilyID)
                        ->setFmrId($aRoles[$iCount])
                        ->setDateEntered(date('YmdHis'))
                        ->setEnteredBy(AuthenticationManager::getCurrentUser()->getId())
                        ->setGender($aGenders[$iCount])
                        ->setBirthDay($aBirthDays[$iCount])
                        ->setBirthMonth($aBirthMonths[$iCount])
                        ->setBirthYear($aBirthYears[$iCount])
                        ->setClsId($aClassification[$iCount]);
                    $person->save();
                    $person->reload();
                    $personCustom = new PersonCustom();
                    $personCustom->setPerId($person->getId());
                    $personCustom->save();
                }
            }
            $family = FamilyQuery::create()->findPk($iFamilyID);
            $family->updateLanLng();
        } else {
            for ($iCount = 1; $iCount <= $iFamilyMemberRows; $iCount++) {
                if (strlen($aFirstNames[$iCount]) > 0) {
                    if (strlen($aBirthYears[$iCount]) < 4) {
                        $aBirthYears[$iCount] = 'NULL';
                    }

                    //If no last name is entered for a member, use the family name.
                    $sLastNameToEnter = strlen($aLastNames[$iCount]) && $aLastNames[$iCount] != $sName
                        ? $aLastNames[$iCount]
                        : $sName;
                    $person = PersonQuery::create()->findOneById($aPersonIDs[$iCount]);
                    $person
                        ->setFirstName($aFirstNames[$iCount])
                        ->setMiddleName($aMiddleNames[$iCount])
                        ->setLastName($aLastNames[$iCount])
                        ->setSuffix($aSuffix[$iCount])
                        ->setGender($aGenders[$iCount])
                        ->setFmrId($aRoles[$iCount])
                        ->setBirthMonth($aBirthMonths[$iCount])
                        ->setBirthDay($aBirthDays[$iCount])
                        ->setClsId($aClassification[$iCount])
                        ->setDateLastEdited(date('YmdHis'))
                        ->setEditedBy(AuthenticationManager::getCurrentUser()->getId());
                    if ($aUpdateBirthYear[$iCount] & 1) {
                        $person->setBirthYear($aBirthYears[$iCount]);
                    }
                    $person->save();
                }
            }
            $family = FamilyQuery::create()->findPk($iFamilyID);
            $family->updateLanLng();
        }

        // Update the custom person fields.
        if ($numCustomFields > 0) {
            $sSQL = 'REPLACE INTO family_custom SET ';
            mysqli_data_seek($rsCustomFields, 0);

            while ($rowCustomField = mysqli_fetch_array($rsCustomFields, MYSQLI_BOTH)) {
                extract($rowCustomField);
                if (AuthenticationManager::getCurrentUser()->isEnabledSecurity($aSecurityType[$fam_custom_FieldSec])) {
                    $currentFieldData = trim($aCustomData[$fam_custom_Field]);

                    CustomFieldUtils::buildSql($sSQL, $type_ID, $currentFieldData, $fam_custom_Field, $sCountry);
                }
            }

            // chop off the last 2 characters (comma and space) added in the last while loop iteration.
            $sSQL = mb_substr($sSQL, 0, -2);

            $sSQL .= ", fam_ID = $iFamilyID";

            //Execute the SQL
            RunQuery($sSQL);
        }

        //Which submit button did they press?
        if (isset($_POST['FamilySubmit'])) {
            //Send to the view of this person
            RedirectUtils::redirect("people/family/$iFamilyID");
        } else {
            //Reload to editor to add another record
            RedirectUtils::redirect('FamilyEditor.php');
        }
    }
} else {
    //FirstPass
    //Are we editing or adding?
    if ($family) {
        //Editing....
        //Get the information on this family
        $rsFamily = RunPreparedQuery('SELECT * FROM family_fam WHERE fam_ID = ?', 'i', [$iFamilyID]);
        extract(mysqli_fetch_array($rsFamily));

        $iFamilyID = $family->getId();
        $sName = $family->getName();
        $sAddress1 = $family->getAddress1();
        $sAddress2 = $family->getAddress2();
        $sCity = $family->getCity();
        $sState = $family->getState();
        $sZip = $family->getZip();
        $sCountry = $family->getCountry();
        $sHomePhone = $family->getHomePhone();
        $sEmail = $family->getEmail();
        $bSendNewsLetter = $family->getSendNewsletter() === 'TRUE';
        $dWeddingDate = $family->getWeddingdate(SystemConfig::getValue("sDatePickerFormat"));
        $nLatitude = $family->getLatitude();
        $nLongitude = $family->getLongitude();

        // No display formatting — keep stored value as-is

        // Set"No format" checkbox based on whether field has data
        // If field has data: checkbox checked, no mask
        // If field is empty: checkbox unchecked, mask applied
        $bNoFormat_HomePhone = !empty($sHomePhone);

        $rsCustomData = RunPreparedQuery('SELECT * FROM family_custom WHERE fam_ID = ?', 'i', [$iFamilyID]);
        $aCustomData = mysqli_fetch_array($rsCustomData, MYSQLI_BOTH);

        $aCustomErrors = [];

        if ($numCustomFields > 0) {
            mysqli_data_seek($rsCustomFields, 0);
            while ($rowCustomField = mysqli_fetch_array($rsCustomFields, MYSQLI_BOTH)) {
                $aCustomErrors[$rowCustomField['fam_custom_Field']] = false;
            }
        }

        $rsMembers = RunPreparedQuery('SELECT * FROM person_per LEFT JOIN family_fam ON per_fam_ID = fam_ID WHERE per_fam_ID = ? ORDER BY per_fmr_ID', 'i', [$iFamilyID]);
        $iCount = 0;
        $iFamilyMemberRows = 0;
        while ($aRow = mysqli_fetch_array($rsMembers)) {
            extract($aRow);
            $iCount++;
            $iFamilyMemberRows++;
            $aFirstNames[$iCount] = $per_FirstName;
            $aMiddleNames[$iCount] = $per_MiddleName;
            $aLastNames[$iCount] = $per_LastName;
            $aSuffix[$iCount] = $per_Suffix;
            $aGenders[$iCount] = (int)$per_Gender;
            $aRoles[$iCount] = (int)$per_fmr_ID;
            $aBirthMonths[$iCount] = (int)$per_BirthMonth;
            $aBirthDays[$iCount] = (int)$per_BirthDay;
            $aBirthYears[$iCount] = $per_BirthYear > 0 ? (int)$per_BirthYear : '';
            $aClassification[$iCount] = (int)$per_cls_ID;
            $aPersonIDs[$iCount] = (int)$per_ID;
            $aPerFlag[$iCount] = $per_Flags;
        }
    } else {
        //Adding....
        //Set defaults
        $sCity = SystemConfig::getValue('sDefaultCity');
        $sCountry = SystemConfig::getValue('sDefaultCountry');
        $sState = SystemConfig::getValue('sDefaultState');
        $sZip = SystemConfig::getValue('sDefaultZip');
        $iClassification = '0';
        $iFamilyMemberRows = 4;

        $iFamilyID = -1;
        $sName = '';
        $sAddress1 = '';
        $sAddress2 = '';
        $sHomePhone = '';
        $bNoFormat_HomePhone = isset($_POST['NoFormat_HomePhone']);
        $sWorkPhone = '';
        $bNoFormat_WorkPhone = isset($_POST['NoFormat_WorkPhone']);
        $sCellPhone = '';
        $bNoFormat_CellPhone = isset($_POST['NoFormat_CellPhone']);
        $sEmail = '';
        $bSendNewsLetter = 'TRUE';
        $dWeddingDate = '';
        $nLatitude = 0.0;
        $nLongitude = 0.0;

        //Loop through the Family Member 'quick entry' form fields
        $iDefaultHeadRole = (int) SystemConfig::getValue('sDirRoleHead');
        for ($iCount = 1; $iCount <= $iFamilyMemberRows; $iCount++) {
            // Assign everything to arrays
            $aFirstNames[$iCount] = '';
            $aMiddleNames[$iCount] = '';
            $aLastNames[$iCount] = '';
            $aSuffix[$iCount] = '';
            // First member defaults to Head of Household
            $aRoles[$iCount] = ($iCount === 1) ? $iDefaultHeadRole : 0;
            $aGenders[$iCount] = '';
            $aBirthDays[$iCount] = 0;
            $aBirthMonths[$iCount] = 0;
            $aBirthYears[$iCount] = '';
            $aClassification[$iCount] = 0;
            $aPersonIDs[$iCount] = 0;
            $aUpdateBirthYear[$iCount] = 0;
        }

        $aCustomData = [];
        $aCustomErrors = [];
        if ($numCustomFields > 0) {
            mysqli_data_seek($rsCustomFields, 0);
            while ($rowCustomField = mysqli_fetch_array($rsCustomFields, MYSQLI_BOTH)) {
                extract($rowCustomField);
                $aCustomData[$fam_custom_Field] = '';
                $aCustomErrors[$fam_custom_Field] = false;
            }
        }
    }
}

$aBreadcrumbs = PageHeader::breadcrumbs([
    [gettext('People'), '/people/dashboard'],
    [gettext('Families'), '/people/family'],
    [($iFamilyID > 0) ? gettext('Edit Family') : gettext('New Family')],
]);
require_once __DIR__ . '/Include/Header.php';
?>
<form method="post" action="FamilyEditor.php?FamilyID=<?php echo $iFamilyID ?>" id="familyEditor">
    <input type="hidden" name="iFamilyID" value="<?= $iFamilyID ?>">
    <input type="hidden" name="FamCount" value="<?= $iFamilyMemberRows ?>">
    <input type="hidden" id="stateType" name="stateType" value="">

    <?php if ($bErrorFlag) { ?>
    <div class="alert alert-danger alert-dismissable" role="alert">
        <i class="fa-solid fa-ban me-2"></i>
        <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
        <?= gettext('Invalid fields or selections. Changes not saved! Please correct and try again!') ?>
    </div>
    <?php } ?>

    <!-- Card 1: Family Info -->
    <div class="card clearfix">
        <div class="card-header d-flex align-items-center">
            <h3 class="card-title"><?= gettext('Family Info') ?></h3>
        </div>
        <div class="card-body">
            <div class="row">
                <div class="mb-3 col-12 col-md-6">
                    <label for="FamilyName"><?= gettext('Family Name') ?>:</label>
                    <div class="input-group">
                        <span class="input-group-text"><i class="fa-solid fa-people-roof"></i></span>
                        <input type="text" name="Name" id="FamilyName" value="<?= InputUtils::escapeAttribute($sName) ?>" maxlength="48" class="form-control">
                    </div>
                    <?php if ($sNameError) { ?>
                        <span class="text-danger small"><?= $sNameError ?></span>
                    <?php } ?>
                </div>
                <?php if (!SystemConfig::getBooleanValue('bHideWeddingDate')) { /* Wedding Date can be hidden - General Settings */
                    if (empty($dWeddingDate)) {
                        $dWeddingDate = '';
                    } ?>
                <div class="mb-3 col-12 col-sm-6 col-md-4">
                    <label for="WeddingDate"><?= gettext('Wedding Date') ?>:</label>
                    <div class="input-group">
                        <span class="input-group-text"><i class="fa-solid fa-heart"></i></span>
                        <input type="text" class="form-control date-picker" name="WeddingDate" id="WeddingDate" value="<?= DateTimeUtils::formatForDatePicker($dWeddingDate) ?>" maxlength="12" placeholder="<?= SystemConfig::getValueForAttr("sDatePickerPlaceHolder") ?>">
                    </div>
                    <?php if ($sWeddingDateError) { ?>
                    <span class="text-danger small"><?= $sWeddingDateError ?></span>
                    <?php } ?>
                </div>
                <?php } /* Wedding date can be hidden - General Settings */ ?>
            </div>
        </div>
    </div>

    <!-- Card 2: Location & Contact Information -->
    <div class="card clearfix">
        <div class="card-header d-flex align-items-center">
            <h3 class="card-title"><?= gettext('Location & Contact Information') ?></h3>
        </div>
        <div class="card-body">
            <!-- Location Section -->
            <div class="row">
                <div class="col-12">
                    <h5 class="text-body-secondary mb-3"><?= gettext('Address') ?></h5>
                </div>
            </div>
            <div class="row">
                <div class="mb-3 col-12 col-md-6">
                    <label for="Address1"><?= gettext('Address') ?> 1:</label>
                    <div class="input-group">
                        <span class="input-group-text"><i class="fa-solid fa-location-dot"></i></span>
                        <input type="text" id="Address1" name="Address1" value="<?= InputUtils::escapeAttribute($sAddress1) ?>" maxlength="250" class="form-control">
                    </div>
                </div>
                <div class="mb-3 col-12 col-md-6">
                    <label for="Address2"><?= gettext('Address') ?> 2:</label>
                    <div class="input-group">
                        <span class="input-group-text"><i class="fa-solid fa-location-dot"></i></span>
                        <input type="text" id="Address2" name="Address2" value="<?= InputUtils::escapeAttribute($sAddress2) ?>" maxlength="250" class="form-control">
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="mb-3 col-12 col-sm-6 col-md-4">
                    <label for="City"><?= gettext('City') ?>:</label>
                    <div class="input-group">
                        <span class="input-group-text"><i class="fa-solid fa-city"></i></span>
                        <input type="text" id="City" name="City" value="<?= InputUtils::escapeAttribute($sCity) ?>" maxlength="50" class="form-control">
                    </div>
                </div>
                <div id="stateOptionDiv" class="mb-3 col-12 col-sm-6 col-md-3">
                    <label for="State"><?= gettext('State') ?>:</label>
                    <select id="State" name="State" class="form-select" data-user-selected="<?= InputUtils::escapeAttribute($sState) ?>" data-system-default="<?= SystemConfig::getValueForAttr('sDefaultState') ?>">
                    </select>
                </div>
                <div id="stateInputDiv" class="mb-3 col-12 col-sm-6 col-md-3 d-none">
                    <label for="StateTextbox"><?= gettext('State') ?>:</label>
                    <input id="StateTextbox" type="text" class="form-control" name="StateTextbox" value="<?= InputUtils::escapeAttribute($sState) ?>" maxlength="30">
                </div>
                <div class="mb-3 col-12 col-sm-6 col-md-2">
                    <label for="Zip"><?= gettext('Zip') ?>:</label>
                    <input type="text" id="Zip" name="Zip" class="form-control" <?php
                    if (SystemConfig::getBooleanValue('bForceUppercaseZip')) {
                        echo 'style="text-transform:uppercase" ';
                    }
                    echo 'value="' . InputUtils::escapeAttribute($sZip) . '" '; ?> maxlength="10">
                </div>
                <div class="mb-3 col-12 col-sm-6 col-md-3">
                    <label for="Country"><?= gettext('Country') ?>:</label>
                    <select id="Country" name="Country" class="form-select" data-user-selected="<?= InputUtils::escapeAttribute($sCountry) ?>" data-system-default="<?= SystemConfig::getValueForAttr('sDefaultCountry') ?>">
                    </select>
                </div>
            </div>
            <?php if (!SystemConfig::getBooleanValue('bHideLatLon')) { /* Lat/Lon can be hidden - General Settings */
                if (!$bHaveXML) { // No point entering if values will just be overwritten
                    ?>
                    <div class="row">
                        <div class="mb-3 col-12 col-sm-6 col-md-3">
                            <label for="Latitude"><?= gettext('Latitude') ?>:</label>
                            <div class="input-group">
                                <span class="input-group-text"><i class="fa-solid fa-globe"></i></span>
                                <input type="text" class="form-control" id="Latitude" name="Latitude" value="<?= $nLatitude && $nLatitude !== 0 ? $nLatitude : '' ?>" maxlength="50">
                            </div>
                        </div>
                        <div class="mb-3 col-12 col-sm-6 col-md-3">
                            <label for="Longitude"><?= gettext('Longitude') ?>:</label>
                            <div class="input-group">
                                <span class="input-group-text"><i class="fa-solid fa-globe"></i></span>
                                <input type="text" class="form-control" id="Longitude" name="Longitude" value="<?= $nLongitude && $nLongitude !== 0 ? $nLongitude : '' ?>" maxlength="50">
                            </div>
                        </div>
                    </div>
                    <?php
                }
            } /* Lat/Lon can be hidden - General Settings */ ?>

            <!-- Contact Information Section -->
            <div class="row mt-4">
                <div class="col-12">
                    <h5 class="text-body-secondary mb-3"><?= gettext('Contact') ?></h5>
                </div>
            </div>
            <div class="row">
                <div class="mb-3 col-12 col-md-6">
                    <label for="HomePhone"><?= gettext('Home Phone') ?>:</label>
                    <div class="input-group">
                        <span class="input-group-text"><i class="fa-solid fa-house"></i></span>
                        <input type="text" id="HomePhone" name="HomePhone" value="<?= InputUtils::escapeAttribute($sHomePhone) ?>" maxlength="30" class="form-control" data-phone-mask='{"mask":"<?= SystemConfig::getValueForAttr('sPhoneFormat') ?>"}'>
                        <span class="input-group-text gap-2">
                            <input class="form-check-input mt-0" type="checkbox" id="NoFormat_HomePhone" name="NoFormat_HomePhone" value="1" <?= $bNoFormat_HomePhone ? 'checked' : '' ?>>
                            <label class="form-check-label" for="NoFormat_HomePhone"><?= gettext('No format') ?></label>
                        </span>
                    </div>
                </div>
                <div class="mb-3 col-12 col-md-6">
                    <label for="Email"><?= gettext('Email') ?>:</label>
                    <div class="input-group">
                        <span class="input-group-text"><i class="fa-solid fa-at"></i></span>
                        <input type="email" id="Email" name="Email" class="form-control" value="<?= InputUtils::escapeAttribute($sEmail) ?>" maxlength="100">
                    </div>
                    <?php if ($sEmailError) { ?>
                    <span class="text-danger small"><?= $sEmailError ?></span>
                    <?php } ?>
                </div>
            </div>
            <?php if (!SystemConfig::getBooleanValue('bHideFamilyNewsletter')) { /* Newsletter can be hidden - General Settings */ ?>
            <div class="row">
                <div class="mb-3 col-12 col-md-6">
                    <div class="form-check">
                        <input type="checkbox" class="form-check-input" id="SendNewsLetter" name="SendNewsLetter" value="1" <?= $bSendNewsLetter ? 'checked' : '' ?>>
                        <label class="form-check-label" for="SendNewsLetter"><?= gettext('Send Newsletter') ?></label>
                    </div>
                </div>
            </div>
            <?php } ?>
        </div>
    </div>
    <?php if (SystemConfig::getBooleanValue('bUseDonationEnvelopes')) { /* Donation envelopes can be hidden - General Settings */ ?>
        <div class="card clearfix">
            <div class="card-header d-flex align-items-center">
                <h3 class="card-title"><?= gettext('Envelope Info') ?></h3>
            <div class="card-body">
                <div class="row">
                    <div class="mb-3 col-12 col-sm-6 col-md-4">
                        <label for="Envelope"><?= gettext('Envelope Number') ?>:</label>
                        <div class="input-group">
                            <span class="input-group-text"><i class="fa-solid fa-envelope-open-text"></i></span>
                            <input type="text" id="Envelope" name="Envelope" class="form-control" value="<?= $fam_Envelope ?? '' ?>" maxlength="50">
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <?php
    }
    if ($numCustomFields > 0) {
        ?>
        <div class="card clearfix">
            <div class="card-header d-flex align-items-center">
                <h3 class="card-title"><?= gettext('Custom Fields') ?></h3>
            </div>
            <div class="card-body">
                <?php 
                $customPhoneFields = [];
                mysqli_data_seek($rsCustomFields, 0);
                while ($rowCustomField = mysqli_fetch_array($rsCustomFields, MYSQLI_BOTH)) {
                    extract($rowCustomField);
                    if (AuthenticationManager::getCurrentUser()->isEnabledSecurity($aSecurityType[$fam_custom_FieldSec])) {
                        ?>
                        <div class="row">
                            <div class="mb-3 col-12 col-md-6">
                                <label for="<?= $fam_custom_Field ?>"><?= $fam_custom_Name ?></label>
                        <?php $currentFieldData = trim($aCustomData[$fam_custom_Field]);

                        CustomFieldUtils::renderForm($type_ID, $fam_custom_Field, $currentFieldData, $fam_custom_Special, !isset($_POST['FamilySubmit']));
                        if (!empty($aCustomErrors[$fam_custom_Field])) {
                            echo '<span class="text-danger small">' . $aCustomErrors[$fam_custom_Field] . '</span>';
                        }
                        echo '</div></div>';
                    }
                } ?>
            </div>
        </div>
    <?php
    } ?>
    <div class="card clearfix">
        <div class="card-header d-flex align-items-center">
            <h3 class="card-title"><?= gettext('Family Members') ?></h3>
        </div>
        <div class="card-body">

            <?php if ($iFamilyMemberRows > 0) {
                ?>

                                <?php if ($iFamilyID < 0) { ?>
                                <div class="alert alert-info mb-3">
                                    <i class="fa-solid fa-circle-info"></i> <?= gettext('You may create family members now or add them later. All entries will become new person records.') ?>
                                </div>
                                <?php } ?>
                                <div class="table-responsive">
                                    <table class="table table-hover">
                                        <thead>
                                            <tr class="text-center">
                                                <th><?= gettext('First') ?></th>
                                                <th><?= gettext('Middle') ?></th>
                                                <th><?= gettext('Last') ?></th>
                                                <th><?= gettext('Suffix') ?></th>
                                                <th><?= gettext('Gender') ?></th>
                                                <th><?= gettext('Role') ?></th>
                                                <th><?= gettext('Birth Month') ?></th>
                                                <th><?= gettext('Birth Day') ?></th>
                                                <th><?= gettext('Birth Year') ?></th>
                                                <th><?= gettext('Classification') ?></th>
                                            </tr>
                                        </thead>
                                        <tbody id="familyMembersTbody">
                                        <?php

                                        //Get family roles using Propel ORM
                                        $familyRoles = ListOptionQuery::create()
                                            ->filterById(2)
                                            ->orderByOptionSequence()
                                            ->find();
                                        $numFamilyRoles = $familyRoles->count();
                                        $c = 1;
                                        foreach ($familyRoles as $role) {
                                            $aFamilyRoleNames[$c] = $role->getOptionName();
                                            $aFamilyRoleIDs[$c] = $role->getOptionId();
                                            $c++;
                                        }

                                        for ($iCount = 1; $iCount <= $iFamilyMemberRows; $iCount++) {
                                            ?>
                                            <tr>
                                                <td>
                                                    <input type="hidden" name="PersonID<?= $iCount ?>" value="<?= $aPersonIDs[$iCount] ?>">
                                                    <input name="FirstName<?= $iCount ?>" type="text" value="<?= InputUtils::escapeAttribute($aFirstNames[$iCount]) ?>" class="form-control form-control-sm">
                                                    <?php if (array_key_exists($iCount, $aFirstNameError)) { ?>
                                                    <span class="text-danger small"><?= $aFirstNameError[$iCount] ?></span>
                                                    <?php } ?>
                                                </td>
                                                <td>
                                                    <input name="MiddleName<?= $iCount ?>" type="text" value="<?= InputUtils::escapeAttribute($aMiddleNames[$iCount]) ?>" class="form-control form-control-sm">
                                                </td>
                                                <td>
                                                    <input name="LastName<?= $iCount ?>" type="text" value="<?= InputUtils::escapeAttribute($aLastNames[$iCount]) ?>" class="form-control form-control-sm">
                                                </td>
                                                <td>
                                                    <input name="Suffix<?= $iCount ?>" type="text" value="<?= InputUtils::escapeAttribute($aSuffix[$iCount]) ?>" class="form-control form-control-sm" maxlength="50">
                                                </td>
                                                <td>
                                                    <select name="Gender<?= $iCount ?>" class="form-select form-select-sm">
                                                        <option value="0" <?= $aGenders[$iCount] === 0 ? 'selected' : '' ?>><?= gettext('Select Gender') ?></option>
                                                        <option value="1" <?= $aGenders[$iCount] === 1 ? 'selected' : '' ?>><?= gettext('Male') ?></option>
                                                        <option value="2" <?= $aGenders[$iCount] === 2 ? 'selected' : '' ?>><?= gettext('Female') ?></option>
                                                    </select>
                                                </td>
                                                <td>
                                                    <select name="Role<?= $iCount ?>" class="form-select form-select-sm">
                                                        <option value="0" <?= $aRoles[$iCount] === 0 ? 'selected' : '' ?>><?= gettext('Select Role') ?></option>
                                                        <?php
                                                        //Build the role select box
                                                        for ($c = 1; $c <= $numFamilyRoles; $c++) {
                                                            echo '<option value="' . $aFamilyRoleIDs[$c] . '"';
                                                            if ($aRoles[$iCount] === $aFamilyRoleIDs[$c]) {
                                                                echo ' selected';
                                                            }
                                                            echo '>' . $aFamilyRoleNames[$c] . '</option>';
                                                        } ?>
                                                    </select>
                                                </td>
                                                <td>
                                                    <select name="BirthMonth<?= $iCount ?>" class="form-select form-select-sm">
                                                        <option value="0" <?= $aBirthMonths[$iCount] === 0 ? 'selected' : '' ?>><?= gettext('Unknown') ?></option>
                                                        <option value="01" <?= $aBirthMonths[$iCount] === 1 ? 'selected' : '' ?>><?= gettext('January') ?></option>
                                                        <option value="02" <?= $aBirthMonths[$iCount] === 2 ? 'selected' : '' ?>><?= gettext('February') ?></option>
                                                        <option value="03" <?= $aBirthMonths[$iCount] === 3 ? 'selected' : '' ?>><?= gettext('March') ?></option>
                                                        <option value="04" <?= $aBirthMonths[$iCount] === 4 ? 'selected' : '' ?>><?= gettext('April') ?></option>
                                                        <option value="05" <?= $aBirthMonths[$iCount] === 5 ? 'selected' : '' ?>><?= gettext('May') ?></option>
                                                        <option value="06" <?= $aBirthMonths[$iCount] === 6 ? 'selected' : '' ?>><?= gettext('June') ?></option>
                                                        <option value="07" <?= $aBirthMonths[$iCount] === 7 ? 'selected' : '' ?>><?= gettext('July') ?></option>
                                                        <option value="08" <?= $aBirthMonths[$iCount] === 8 ? 'selected' : '' ?>><?= gettext('August') ?></option>
                                                        <option value="09" <?= $aBirthMonths[$iCount] === 9 ? 'selected' : '' ?>><?= gettext('September') ?></option>
                                                        <option value="10" <?= $aBirthMonths[$iCount] === 10 ? 'selected' : '' ?>><?= gettext('October') ?></option>
                                                        <option value="11" <?= $aBirthMonths[$iCount] === 11 ? 'selected' : '' ?>><?= gettext('November') ?></option>
                                                        <option value="12" <?= $aBirthMonths[$iCount] === 12 ? 'selected' : '' ?>><?= gettext('December') ?></option>
                                                    </select>
                                                </td>
                                                <td>
                                                    <select name="BirthDay<?= $iCount ?>" class="form-select form-select-sm">
                                                        <option value="0"><?= gettext('Unk') ?></option>
                                                        <?php for ($x = 1; $x < 32; $x++) {
                                                            $sDay = $x < 10 ? "0$x" : $x;
                                                            ?>
                                                            <option value="<?= $sDay ?>" <?= $aBirthDays[$iCount] === $x ? 'selected' : '' ?>><?= $x ?></option>
                                                        <?php } ?>
                                                    </select>
                                                </td>
                                                <td>
                                                    <?php if (!array_key_exists($iCount, $aperFlags) || !$aperFlags[$iCount]) {
                                                        $UpdateBirthYear = 1; ?>
                                                        <input name="BirthYear<?= $iCount ?>" type="text" value="<?= $aBirthYears[$iCount] ?>" class="form-control form-control-sm" maxlength="4">
                                                        <?php if (array_key_exists($iCount, $aBirthDateError)) { ?>
                                                        <span class="text-danger small"><?= $aBirthDateError[$iCount] ?></span>
                                                        <?php }
                                                    } else {
                                                        $UpdateBirthYear = 0;
                                                    } ?>
                                                </td>
                                                <td>
                                                    <select name="Classification<?= $iCount ?>" class="form-select form-select-sm">
                                                        <option value="0" <?= $aClassification[$iCount] === 0 ? 'selected' : '' ?>><?= gettext('Unassigned') ?></option>
                                                        <option value="" disabled>-----------------------</option>
                                                        <?php
                                                        //Get Classifications for the drop-down
                                                        $sSQL = 'SELECT * FROM list_lst WHERE lst_ID = 1 ORDER BY lst_OptionSequence';
                                                        $rsClassifications = RunQuery($sSQL);

                                                        //Display Classifications
                                                        while ($aRow = mysqli_fetch_array($rsClassifications)) {
                                                            extract($aRow);
                                                            echo "<option value=\"$lst_OptionID\"";
                                                            if ($aClassification[$iCount] == $lst_OptionID) {
                                                                echo ' selected';
                                                            }
                                                            echo '>' . InputUtils::escapeHTML($lst_OptionName) . '</option>';
                                                        }
                                                        ?>
                                                    </select>
                                                </td>
                                            </tr>
                                        <?php } ?>
                                        </tbody>
                                    </table>
                                </div>
                                <?php if ($iFamilyID < 0) { ?>
                                <div class="mt-3">
                                    <button type="button" class="btn btn-outline-primary btn-sm" id="addFamilyMemberRow">
                                        <i class="fa-solid fa-plus"></i><?= gettext('Add Another Family Member') ?>
                                    </button>
                                </div>
                                <?php } ?>
                            <?php } ?>
                        </div>
                    </div>

                    <input type="hidden" Name="UpdateBirthYear" value="<?= $UpdateBirthYear ?>">

                    <!-- Form submit buttons -->
                    <div class="d-flex gap-2 mt-4">
                        <!-- Primary action: Save (green) -->
                        <button type="submit" name="FamilySubmit" class="btn btn-success flex-grow-1">
                            <i class="fa-solid fa-check me-2"></i><?= gettext('Save') ?>
                        </button>
                        <!-- Secondary action: Save and Add (blue) -->
                        <?php if (AuthenticationManager::getCurrentUser()->isAddRecordsEnabled()) { ?>
                        <button type="submit" name="FamilySubmitAndAdd" class="btn btn-info flex-grow-1">
                            <i class="fa-solid fa-people-roof me-2"></i><?= gettext('Save and Add New Family') ?>
                        </button>
                        <?php } ?>
                        <!-- Tertiary action: Cancel (gray) -->
                        <?php if ($iFamilyID > 0) { ?>
                        <a href="<?= SystemURLs::getRootPath() ?>/people/family/<?= $iFamilyID ?>" class="btn btn-secondary">
                            <i class="fa-solid fa-xmark me-2"></i><?= gettext('Cancel') ?>
                        </a>
                        <?php } else { ?>
                        <a href="<?= SystemURLs::getRootPath() ?>/people/family" class="btn btn-secondary">
                            <i class="fa-solid fa-xmark me-2"></i><?= gettext('Cancel') ?>
                        </a>
                        <?php } ?>
                    </div>
                </form>

<?php if ($iFamilyID < 0) {
    // Get family roles for JavaScript using Propel ORM
    $familyRolesForJS = ListOptionQuery::create()
        ->filterById(2)
        ->orderByOptionSequence()
        ->find();
    $familyRolesJS = [];
    foreach ($familyRolesForJS as $role) {
        $familyRolesJS[] = ['id' => $role->getOptionId(), 'name' => $role->getOptionName()];
    }

    // Get classifications for JavaScript using Propel ORM
    $classificationsForJS = ListOptionQuery::create()
        ->filterById(1)
        ->orderByOptionSequence()
        ->find();
    $classificationsJS = [];
    foreach ($classificationsForJS as $classification) {
        $classificationsJS[] = ['id' => $classification->getOptionId(), 'name' => $classification->getOptionName()];
    }
?>
<script nonce="<?= SystemURLs::getCSPNonce() ?>">
    window.CRM.familyRoles = <?= InputUtils::jsonEncodeForScript($familyRolesJS) ?>;
    window.CRM.classifications = <?= InputUtils::jsonEncodeForScript($classificationsJS) ?>;
    window.CRM.customPhoneFields = <?= InputUtils::jsonEncodeForScript($customPhoneFields ?? []) ?>;
    window.CRM.initialFamilyMemberCount = <?= $iFamilyMemberRows ?>;
    window.CRM.i18n = {
        selectGender: <?= InputUtils::jsonEncodeForScript(gettext('Select Gender')) ?>,
        male: <?= InputUtils::jsonEncodeForScript(gettext('Male')) ?>,
        female: <?= InputUtils::jsonEncodeForScript(gettext('Female')) ?>,
        selectRole: <?= InputUtils::jsonEncodeForScript(gettext('Select Role')) ?>,
        unknown: <?= InputUtils::jsonEncodeForScript(gettext('Unknown')) ?>,
        unassigned: <?= InputUtils::jsonEncodeForScript(gettext('Unassigned')) ?>,
        months: [
            <?= InputUtils::jsonEncodeForScript(gettext('January')) ?>,
            <?= InputUtils::jsonEncodeForScript(gettext('February')) ?>,
            <?= InputUtils::jsonEncodeForScript(gettext('March')) ?>,
            <?= InputUtils::jsonEncodeForScript(gettext('April')) ?>,
            <?= InputUtils::jsonEncodeForScript(gettext('May')) ?>,
            <?= InputUtils::jsonEncodeForScript(gettext('June')) ?>,
            <?= InputUtils::jsonEncodeForScript(gettext('July')) ?>,
            <?= InputUtils::jsonEncodeForScript(gettext('August')) ?>,
            <?= InputUtils::jsonEncodeForScript(gettext('September')) ?>,
            <?= InputUtils::jsonEncodeForScript(gettext('October')) ?>,
            <?= InputUtils::jsonEncodeForScript(gettext('November')) ?>,
            <?= InputUtils::jsonEncodeForScript(gettext('December')) ?>
        ]
    };
</script>
<?php } ?>
<script src="<?= SystemURLs::assetVersioned('/skin/js/DropdownManager.js') ?>"></script>
<script src="<?= SystemURLs::assetVersioned('/skin/js/FamilyEditor.js') ?>"></script>
<?php
require_once __DIR__ . '/Include/Footer.php';
