<?php
/**
 * Field-level audit helpers for members and households (uses activity_logs via audit.php).
 */
declare(strict_types=1);

require_once __DIR__ . '/audit.php';

/**
 * @return list<string>
 */
function nazarethMemberAuditColumns(): array
{
    return [
        'membership_number', 'title', 'first_name', 'middle_name', 'last_name', 'gender', 'date_of_birth',
        'phone', 'email', 'marital_status', 'occupation', 'status', 'baptism_date', 'confirmation_date',
        'address', 'ghana_post_address', 'map_link', 'emergency_contact', 'emergency_phone', 'notes',
        'is_aged', 'is_invalid', 'household_id', 'photo',
    ];
}

function nazarethAuditNormalizeScalar($v): string
{
    if ($v === null || $v === false) {
        return '';
    }
    if (is_bool($v)) {
        return $v ? '1' : '0';
    }

    return trim((string) $v);
}

/**
 * Comma-separated service group names for a member.
 */
function nazarethMemberServiceGroupLabels(PDO $pdo, int $memberId): string
{
    if ($memberId <= 0) {
        return '';
    }
    try {
        $stmt = $pdo->prepare(
            'SELECT GROUP_CONCAT(mn.name ORDER BY mn.name SEPARATOR ", ")
             FROM member_ministries mm
             INNER JOIN ministries mn ON mn.id = mm.ministry_id
             WHERE mm.member_id = ?'
        );
        $stmt->execute([$memberId]);
        $s = $stmt->fetchColumn();

        return $s ? (string) $s : '';
    } catch (Throwable $e) {
        return '';
    }
}

function nazarethMemberDisplayName(array $row): string
{
    $parts = array_filter([
        trim((string) ($row['title'] ?? '')),
        trim((string) ($row['first_name'] ?? '')),
        trim((string) ($row['middle_name'] ?? '')),
        trim((string) ($row['last_name'] ?? '')),
    ]);

    $name = trim(implode(' ', $parts));

    return $name !== '' ? $name : ('Member #' . (int) ($row['id'] ?? 0));
}

/**
 * @return array<string, array{old: mixed, new: mixed}>
 */
function nazarethMemberRowDiff(?array $before, array $after): array
{
    $changes = [];
    foreach (nazarethMemberAuditColumns() as $c) {
        $ov = $before ? ($before[$c] ?? null) : null;
        $nv = $after[$c] ?? null;
        if (nazarethAuditNormalizeScalar($ov) !== nazarethAuditNormalizeScalar($nv)) {
            $changes[$c] = ['old' => $ov, 'new' => $nv];
        }
    }

    return $changes;
}

/**
 * Snapshot of auditable columns for create / reference.
 *
 * @return array<string, mixed>
 */
function nazarethMemberSnapshotForAudit(array $row): array
{
    $out = [];
    foreach (nazarethMemberAuditColumns() as $c) {
        $out[$c] = $row[$c] ?? null;
    }

    return $out;
}

function nazarethTryLogMemberCreated(PDO $pdo, ?int $userId, int $memberId, string $source): void
{
    try {
        $stmt = $pdo->prepare('SELECT * FROM members WHERE id = ?');
        $stmt->execute([$memberId]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$row) {
            return;
        }
        $name = nazarethMemberDisplayName($row);
        $sg = nazarethMemberServiceGroupLabels($pdo, $memberId);
        $details = [
            'member_id' => $memberId,
            'display_name' => $name,
            'source' => $source,
            'snapshot' => nazarethMemberSnapshotForAudit($row),
            'service_groups' => $sg !== '' ? $sg : null,
        ];
        logActivity(
            'member_created',
            "Member created: {$name} (ID {$memberId})",
            $details,
            $userId
        );
    } catch (Throwable $e) {
        error_log('nazarethTryLogMemberCreated: ' . $e->getMessage());
    }
}

/**
 * @param array<string,mixed>|null $beforeRow Full row before save (edit only)
 */
function nazarethTryLogMemberUpdated(
    PDO $pdo,
    ?int $userId,
    int $memberId,
    ?array $beforeRow,
    string $oldServiceGroups,
    string $source
): void {
    try {
        $stmt = $pdo->prepare('SELECT * FROM members WHERE id = ?');
        $stmt->execute([$memberId]);
        $afterRow = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$afterRow) {
            return;
        }
        $newSg = nazarethMemberServiceGroupLabels($pdo, $memberId);
        $diff = nazarethMemberRowDiff($beforeRow, $afterRow);
        $o = $oldServiceGroups !== '' ? $oldServiceGroups : '(none)';
        $n = $newSg !== '' ? $newSg : '(none)';
        if ($o !== $n) {
            $diff['service_groups'] = ['old' => $o, 'new' => $n];
        }
        $name = nazarethMemberDisplayName($afterRow);
        $details = [
            'member_id' => $memberId,
            'display_name' => $name,
            'source' => $source,
            'changes' => $diff,
        ];
        logActivity(
            'member_updated',
            'Member updated: ' . $name . ' (ID ' . $memberId . ', ' . count($diff) . ' change set(s))',
            $details,
            $userId
        );
    } catch (Throwable $e) {
        error_log('nazarethTryLogMemberUpdated: ' . $e->getMessage());
    }
}

function nazarethTryLogHouseholdSaved(PDO $pdo, ?int $userId, int $householdId, bool $isEdit, ?array $beforeRow): void
{
    try {
        $stmt = $pdo->prepare('SELECT * FROM households WHERE id = ?');
        $stmt->execute([$householdId]);
        $after = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$after) {
            return;
        }
        $label = trim((string) ($after['name'] ?? '')) ?: ('Household #' . $householdId);
        if (!$isEdit) {
            logActivity(
                'household_created',
                "Household created: {$label} (ID {$householdId})",
                [
                    'household_id' => $householdId,
                    'snapshot' => [
                        'name' => $after['name'] ?? null,
                        'address' => $after['address'] ?? null,
                        'head_member_id' => isset($after['head_member_id']) ? (int) $after['head_member_id'] : null,
                        'notes' => $after['notes'] ?? null,
                    ],
                ],
                $userId
            );

            return;
        }
        $changes = [];
        foreach (['name', 'address', 'head_member_id', 'notes'] as $c) {
            $ov = $beforeRow[$c] ?? null;
            $nv = $after[$c] ?? null;
            if (nazarethAuditNormalizeScalar($ov) !== nazarethAuditNormalizeScalar($nv)) {
                $changes[$c] = ['old' => $ov, 'new' => $nv];
            }
        }
        logActivity(
            'household_updated',
            "Household updated: {$label} (ID {$householdId})",
            [
                'household_id' => $householdId,
                'changes' => $changes,
            ],
            $userId
        );
    } catch (Throwable $e) {
        error_log('nazarethTryLogHouseholdSaved: ' . $e->getMessage());
    }
}
