<?php
// ============================================================
//  Member history & admin notes
// ============================================================
//
//  Lightweight wrapper around the `member_history` table.
//  Use member_history_log() for any event worth recording to the
//  per-member timeline shown on admin/member-edit.php.
//
//  Diffs: pass before/after arrays to member_history_log_diff()
//  and we'll compute a tidy summary + JSON body for you.
// ============================================================

if (!function_exists('member_history_log')) {
    /**
     * Log a single event to the member's history.
     *
     * @param int    $member_id
     * @param string $event_type   short slug, e.g. 'profile_updated', 'note', 'payment_received'
     * @param string $summary      one-line description shown in the timeline
     * @param mixed  $body         optional. string, or array (will be JSON-encoded)
     * @param array  $opts         optional: actor_type, actor_id, actor_name
     */
    function member_history_log(
        int    $member_id,
        string $event_type,
        string $summary,
        $body = null,
        array  $opts = []
    ): void {
        if ($member_id <= 0) return;

        // Auto-detect the actor from session if not provided
        $actor_type = $opts['actor_type'] ?? null;
        $actor_id   = $opts['actor_id']   ?? null;
        $actor_name = $opts['actor_name'] ?? null;

        if (!$actor_type) {
            if (!empty($_SESSION['admin_id'])) {
                $actor_type = 'admin';
                $actor_id   = (int)$_SESSION['admin_id'];
                if (!$actor_name) {
                    $admin = db_row('SELECT first_name, last_name, email FROM admin_users WHERE id=:id', ['id'=>$actor_id]);
                    if ($admin) {
                        $full = trim(($admin['first_name'] ?? '').' '.($admin['last_name'] ?? ''));
                        $actor_name = $full !== '' ? $full : ($admin['email'] ?? null);
                    }
                }
            } elseif (!empty($_SESSION['member_id'])) {
                $actor_type = 'member';
                $actor_id   = (int)$_SESSION['member_id'];
                if (!$actor_name) {
                    $m = db_row('SELECT first_name, last_name FROM members WHERE id=:id', ['id'=>$actor_id]);
                    $actor_name = trim(($m['first_name'] ?? '').' '.($m['last_name'] ?? ''));
                    if ($actor_name === '') $actor_name = null;
                }
            } else {
                $actor_type = 'system';
            }
        }

        $body_str = null;
        if (is_array($body)) {
            $body_str = json_encode($body, JSON_UNESCAPED_UNICODE);
        } elseif (is_string($body) && $body !== '') {
            $body_str = $body;
        }

        try {
            db_insert('member_history', [
                'member_id'   => $member_id,
                'event_type'  => mb_substr($event_type, 0, 60),
                'summary'     => mb_substr($summary, 0, 255),
                'body'        => $body_str,
                'actor_type'  => $actor_type,
                'actor_id'    => $actor_id,
                'actor_name'  => $actor_name ? mb_substr($actor_name, 0, 120) : null,
            ]);
        } catch (Throwable $e) {
            // Logging must never fail the calling page. Just app_log it.
            if (function_exists('app_log')) {
                app_log('member_history_log failed: ' . $e->getMessage());
            }
        }
    }
}

if (!function_exists('member_history_diff')) {
    /**
     * Compute a field-by-field diff between two arrays.
     * Returns: ['changed_fields' => [...], 'diff' => ['field' => ['from'=>x, 'to'=>y], ...]]
     * Only keys that exist in $after are considered.
     */
    function member_history_diff(array $before, array $after, array $watch_keys = []): array {
        $diff = [];
        $keys = $watch_keys ?: array_keys($after);
        foreach ($keys as $k) {
            $b = $before[$k] ?? null;
            $a = $after[$k]  ?? null;
            // Normalize null/empty-string to be equal so empty-to-empty doesn't show
            if (($b === null || $b === '') && ($a === null || $a === '')) continue;
            if ((string)$b !== (string)$a) {
                $diff[$k] = ['from' => $b, 'to' => $a];
            }
        }
        return [
            'changed_fields' => array_keys($diff),
            'diff'           => $diff,
        ];
    }
}

if (!function_exists('member_history_log_changes')) {
    /**
     * Log a profile-update event with auto-computed diff.
     * Returns true if anything changed (and was logged), false if no diff.
     */
    function member_history_log_changes(
        int    $member_id,
        array  $before,
        array  $after,
        array  $watch_keys = [],
        string $event_type = 'profile_updated'
    ): bool {
        $r = member_history_diff($before, $after, $watch_keys);
        if (empty($r['changed_fields'])) return false;

        $human = [];
        foreach ($r['changed_fields'] as $f) {
            $human[] = str_replace('_', ' ', $f);
        }
        $summary = 'Updated: ' . implode(', ', $human);

        member_history_log($member_id, $event_type, $summary, $r['diff']);
        return true;
    }
}

if (!function_exists('member_history_field_label')) {
    /**
     * Human label for a field key (used when rendering diffs).
     */
    function member_history_field_label(string $key): string {
        $map = [
            'first_name'    => 'First name',
            'last_name'     => 'Last name',
            'business_name' => 'Business name',
            'email'         => 'Email',
            'phone'         => 'Phone',
            'industry'      => 'Industry',
            'tier'          => 'Tier',
            'status'        => 'Status',
            'renewal_date'  => 'Renewal date',
            'join_date'     => 'Join date',
            'banking_details' => 'Banking details',
            'address'       => 'Address',
            'website'       => 'Website',
            'description'   => 'Description',
            'tagline'       => 'Tagline',
        ];
        return $map[$key] ?? ucfirst(str_replace('_', ' ', $key));
    }
}