<?php

namespace App\Services;

use App\Models\AuditLog as AuditLogModel;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Request;

class AuditLog
{
    /**
     * @param  array<string, mixed>  $context
     */
    public static function record(
        string $action,
        ?Model $subject = null,
        array $context = [],
        ?int $actorId = null,
        ?string $description = null,
    ): AuditLogModel {
        // The tenant backfill migration enforces tenant_id NOT NULL on MySQL only
        // (SQLite test tables stay nullable). Skip the insert on MySQL when there
        // is no tenant context — e.g. a login attempt on the central/admin domain.
        if (DB::getDriverName() !== 'sqlite' && ! app(CurrentContext::class)->tenantId()) {
            return new AuditLogModel;
        }

        // Audit actors are always tenant users (FK → users). Resolve from the
        // web guard specifically: in landlord/central context the default guard
        // is `central`, whose ids must never be written here.
        $resolvedActor = $actorId ?? Auth::guard('web')->id();

        $actorName = null;
        if ($resolvedActor) {
            $actorName = User::query()->find($resolvedActor)?->name;
        }

        $subjectType = $subject ? $subject::class : null;
        $subjectId = $subject?->getKey();

        $computedDescription = $description ?? self::describeForAction($action, $actorName ?? 'System', $subjectType, $subjectId, $context);

        return AuditLogModel::create([
            'actor_id' => $resolvedActor,
            'action' => $action,
            'description' => $computedDescription,
            'subject_type' => $subjectType,
            'subject_id' => $subjectId,
            'context' => $context,
            'ip' => Request::ip(),
            'created_at' => now(),
        ]);
    }

    public static function describe(AuditLogModel $log): string
    {
        if (! empty($log->description)) {
            return rtrim(trim((string) $log->description), '.').'.';
        }

        $ctx = $log->context ?? [];
        $actor = $log->actor?->name ?? 'System';

        return self::describeForAction($log->action, $actor, $log->subject_type, $log->subject_id, $ctx);
    }

    /**
     * Centralized description generation used both when recording and when rendering.
     *
     * @param  mixed  $subjectId
     * @param  array<string,mixed>  $ctx
     */
    private static function describeForAction(string $action, string $actor, ?string $subjectType, $subjectId, array $ctx): string
    {
        $subject = $subjectType ? class_basename($subjectType).'#'.($subjectId ?? '?') : null;

        // Build a human-readable "changed X from A to B" summary when before/after pairs are present.
        $changes = '';
        if (! empty($ctx['changed'])) {
            $changes = ' Changed: '.implode(', ', (array) $ctx['changed']).'.';
        }

        $description = match ($action) {
            // ── Auth ──────────────────────────────────────────────────────────
            'user.login' => "{$actor} signed in successfully.",
            'user.pin_login' => "{$actor} signed in using a quick PIN on a trusted device.",
            'user.logout' => "{$actor} signed out.",
            'user.login_failed' => 'Failed login attempt for email "'.($ctx['email'] ?? 'unknown').'". '
                .(! empty($ctx['reason']) ? 'Reason: '.$ctx['reason'].'. ' : '')
                .'Attempt '.($ctx['attempts'] ?? '?').' of '.($ctx['max_attempts'] ?? '?').'.',
            'user.locked' => 'Account for "'.($ctx['email'] ?? $subject ?? 'unknown').'" has been locked after '
                .($ctx['attempts'] ?? '?').' consecutive failed login attempts.',
            'user.unlocked' => "{$actor} manually unlocked the account for ".($ctx['target'] ?? $subject ?? 'unknown').'.',
            'user.two_factor_challenged' => 'A second factor was requested at login for '.($subject ?? 'unknown')
                .(! empty($ctx['method']) ? ' via '.str_replace('_', ' ', (string) $ctx['method']) : '').'.',
            'user.login_otp_sent' => 'A login verification code was emailed to '.($subject ?? 'unknown').'.',
            'user.login_otp_failed' => 'A login verification code failed for '.($subject ?? 'unknown')
                .(! empty($ctx['via']) ? ' (via '.str_replace('_', ' ', (string) $ctx['via']).')' : '').'.',
            'user.two_factor_failed' => 'A two-factor challenge failed for '.($subject ?? 'unknown').'.',
            'user.two_factor_enabled' => "{$actor} started enabling two-factor authentication.",
            'user.two_factor_confirmed' => "{$actor} confirmed two-factor authentication with an authenticator app.",
            'user.two_factor_disabled' => "{$actor} disabled authenticator-app two-factor authentication.",
            'user.two_factor_email_enabled' => "{$actor} enabled email verification codes at login.",
            'user.two_factor_email_disabled' => "{$actor} disabled email verification codes at login.",
            'user.recovery_code_used' => 'A recovery code was used to complete a login for '.($subject ?? 'unknown').'.',
            'user.recovery_codes_regenerated' => "{$actor} generated a new set of recovery codes.",
            'user.password_reset_requested' => 'A password reset code was requested for '.($subject ?? 'unknown').'.',
            'user.password_reset_completed' => 'The password for '.($subject ?? 'unknown').' was reset via emailed code.',
            'user.password_reset_by_admin' => "{$actor} set a new password for ".($subject ?? 'unknown')
                .' — the user must change it at next login.',
            'user.pin_set' => "{$actor} set a quick PIN for ".($subject ?? 'unknown').'.',
            'user.pin_cleared' => "{$actor} cleared the quick PIN for ".($subject ?? 'unknown').'.',

            // ── Users ─────────────────────────────────────────────────────────
            'user.created' => "{$actor} created a new user account: ".($ctx['name'] ?? $subject ?? 'unknown')
                .(! empty($ctx['email']) ? ' ('.$ctx['email'].')' : '')
                .(! empty($ctx['role']) ? ', assigned role "'.$ctx['role'].'"' : '').'.',
            'user.updated' => "{$actor} updated user ".($ctx['name'] ?? $subject ?? 'unknown')
                .(! empty($ctx['email']) ? ' ('.$ctx['email'].')' : '').'.'.$changes,
            'user.deleted' => "{$actor} permanently deleted user account for ".($ctx['name'] ?? $subject ?? 'unknown')
                .(! empty($ctx['email']) ? ' ('.$ctx['email'].')' : '').'.',
            'user.password_reset' => "{$actor} reset the password for ".($ctx['target'] ?? $subject ?? 'unknown').'.',
            'user.suspended' => "{$actor} suspended ".($ctx['target'] ?? $subject ?? 'unknown')
                .(! empty($ctx['reason']) ? '. Reason: '.$ctx['reason'] : '').'. The user can no longer sign in.',
            'user.reactivated' => "{$actor} reactivated ".($ctx['target'] ?? $subject ?? 'unknown').'. The account is now active.',
            'user.deactivated' => "{$actor} deactivated ".($ctx['target'] ?? $subject ?? 'unknown').'. The account has been marked inactive.',

            // ── Roles ─────────────────────────────────────────────────────────
            'role.created' => "{$actor} created a new role: \""
                .($ctx['name'] ?? $subject ?? 'unknown').'\"'
                .(! empty($ctx['permissions_count']) ? ' with '.$ctx['permissions_count'].' permission(s)' : '').'. ',
            'role.updated' => (function () use ($actor, $ctx, $subject): string {
                $name = $ctx['name'] ?? $subject ?? 'unknown';
                $parts = [];
                if (! empty($ctx['added'])) {
                    $parts[] = 'added: '.implode(', ', (array) $ctx['added']);
                }
                if (! empty($ctx['removed'])) {
                    $parts[] = 'removed: '.implode(', ', (array) $ctx['removed']);
                }
                $detail = $parts ? ' Permissions changed — '.implode('; ', $parts).'.' : '';

                return "{$actor} updated role \"{$name}\".{$detail}";
            })(),
            'role.deleted' => "{$actor} deleted role \""
                .($ctx['name'] ?? $subject ?? 'unknown').'\"'
                .(! empty($ctx['users_affected']) ? ' which had '.$ctx['users_affected'].' assigned user(s)' : '').'.',
            'role.resynced' => "{$actor} re-synced role \""
                .($ctx['name'] ?? $subject ?? 'unknown').'\"'
                .' — permissions propagated to '.($ctx['user_count'] ?? '?').' user(s).',
            'role.duplicated' => "{$actor} duplicated role \""
                .($ctx['source'] ?? $subject ?? 'unknown').'\" into new role "'
                .($ctx['name'] ?? 'unknown').'".',
            'role.toggle_active', 'role.toggled_active' => "{$actor} ".($ctx['is_active'] ? 'activated' : 'deactivated').' role "'
                .($ctx['name'] ?? $subject ?? 'unknown').'".',
            'role.assigned' => "{$actor} assigned role \""
                .($ctx['role'] ?? 'unknown').'\" to '.($ctx['target'] ?? $subject ?? 'unknown').'.',
            'role.revoked' => "{$actor} revoked role \""
                .($ctx['role'] ?? 'unknown').'\" from '.($ctx['target'] ?? $subject ?? 'unknown').'.',

            // ── Security ──────────────────────────────────────────────────────
            'escalation.blocked' => (function () use ($actor, $ctx): string {
                $perms = ! empty($ctx['permissions'])
                    ? implode(', ', (array) $ctx['permissions'])
                    : ($ctx['attempted_permission'] ?? null);

                return "{$actor} attempted to grant permissions they do not hold."
                    .($perms ? " Blocked permission(s): {$perms}." : ' The operation was blocked.');
            })(),
            'permission.direct_grant' => "{$actor} directly granted permissions to "
                .($ctx['target'] ?? $subject ?? 'unknown')
                .(! empty($ctx['permissions']) ? ': '.implode(', ', (array) $ctx['permissions']) : '').'.',
            'permission.direct_revoke' => "{$actor} revoked direct permissions from "
                .($ctx['target'] ?? $subject ?? 'unknown')
                .(! empty($ctx['permissions']) ? ': '.implode(', ', (array) $ctx['permissions']) : '').'.',

            // ── Products ──────────────────────────────────────────────────────
            'product.created' => "{$actor} created product \""
                .($ctx['name'] ?? $subject ?? 'unknown').'\"'
                .(! empty($ctx['code']) ? ' (SKU: '.$ctx['code'].')' : '').'.',
            'product.updated' => ! empty($ctx['description'])
                ? (string) $ctx['description']
                : "{$actor} updated product \"".($ctx['name'] ?? $subject ?? 'unknown').'".'.$changes,
            'product.deleted' => "{$actor} deleted product \""
                .($ctx['name'] ?? $subject ?? 'unknown').'\"'
                .(! empty($ctx['code']) ? ' (SKU: '.$ctx['code'].')' : '').'.',

            // ── Invoices ──────────────────────────────────────────────────────
            'invoice.created' => "{$actor} created invoice ".($ctx['reference'] ?? $subject ?? '?')
                .(! empty($ctx['customer']) ? ' for "'.$ctx['customer'].'"' : '')
                .(! empty($ctx['total']) ? ' — total: '.$ctx['total'] : '').'.',
            'invoice.payment_added' => "{$actor} recorded a payment of ".($ctx['amount'] ?? '?')
                .(! empty($ctx['method']) ? ' via '.$ctx['method'] : '')
                .' on invoice '.($ctx['reference'] ?? $subject ?? '?').'.',
            'invoice.note_updated' => "{$actor} updated the note on invoice ".($ctx['reference'] ?? $subject ?? '?').'.',

            // ── Sales ─────────────────────────────────────────────────────────
            'sale.created' => "{$actor} created sale #".($ctx['reference'] ?? '?')
                .(! empty($ctx['customer']) ? ' for customer "'.$ctx['customer'].'"' : '')
                .(! empty($ctx['total']) ? ' - total: '.$ctx['total'] : '').'.',
            'sale.updated' => "{$actor} updated sale #".($ctx['reference'] ?? '?').'.'.$changes,
            'sale.deleted' => "{$actor} deleted sale #".($ctx['reference'] ?? '?')
                .(! empty($ctx['customer']) ? ' (customer: '.$ctx['customer'].')' : '').'.',
            'sale_return.created' => "{$actor} created sale return #".($ctx['reference'] ?? '?')
                .(! empty($ctx['sale_reference']) ? ' against sale #'.$ctx['sale_reference'] : '')
                .(! empty($ctx['total']) ? ' - total: '.$ctx['total'] : '').'.',

            // ── Purchases ─────────────────────────────────────────────────────
            'purchase.created' => "{$actor} created purchase #".($ctx['reference'] ?? '?')
                .(! empty($ctx['supplier']) ? ' from supplier "'.$ctx['supplier'].'"' : '')
                .(! empty($ctx['total']) ? ' - total: '.$ctx['total'] : '').'.',
            'purchase.updated' => "{$actor} updated purchase #".($ctx['reference'] ?? '?').'.'.$changes,
            'purchase.deleted' => "{$actor} deleted purchase #".($ctx['reference'] ?? '?')
                .(! empty($ctx['supplier']) ? ' (supplier: '.$ctx['supplier'].')' : '').'.',
            'purchase_return.created' => "{$actor} created purchase return #".($ctx['reference'] ?? '?')
                .(! empty($ctx['purchase_reference']) ? ' against purchase #'.$ctx['purchase_reference'] : '').'.',

            // ── People ────────────────────────────────────────────────────────
            'customer.created' => "{$actor} created customer \""
                .($ctx['name'] ?? $subject ?? 'unknown').'\"'
                .(! empty($ctx['email']) ? ' ('.$ctx['email'].')' : '').'.',
            'customer.updated' => "{$actor} updated customer \""
                .($ctx['name'] ?? $subject ?? 'unknown').'".'.$changes,
            'customer.deleted' => "{$actor} deleted customer \""
                .($ctx['name'] ?? $subject ?? 'unknown').'".',
            'supplier.created' => "{$actor} created supplier \""
                .($ctx['name'] ?? $subject ?? 'unknown').'".',
            'supplier.updated' => "{$actor} updated supplier \""
                .($ctx['name'] ?? $subject ?? 'unknown').'".'.$changes,
            'supplier.deleted' => "{$actor} deleted supplier \""
                .($ctx['name'] ?? $subject ?? 'unknown').'".',

            // ── Inventory – GRN ───────────────────────────────────────────────
            'grn.created' => "{$actor} created GRN "
                .($ctx['grn_number'] ?? $subject ?? '?')
                .(! empty($ctx['branch']) ? ' at branch "'.$ctx['branch'].'"' : '')
                .' as a draft with '.($ctx['items_count'] ?? '?').' item(s).'
                .(! empty($ctx['reference']) ? ' Reference: '.$ctx['reference'].'.' : ''),
            'grn.confirmed' => (function () use ($actor, $ctx, $subject): string {
                $base = "{$actor} confirmed GRN ".($ctx['grn_number'] ?? $subject ?? '?')
                    .(! empty($ctx['branch']) ? ' at branch "'.$ctx['branch'].'"' : '')
                    .'. Stock updated for '.($ctx['items_count'] ?? '?').' item(s).';

                $priceChanges = array_filter($ctx['items'] ?? [], fn ($i) => isset($i['old_price'], $i['new_price']));
                if (! empty($priceChanges)) {
                    $summaries = array_map(
                        fn ($i) => '"'.$i['product'].'" price '.$i['old_price'].' → '.$i['new_price'],
                        array_slice(array_values($priceChanges), 0, 3)
                    );
                    $extra = count($priceChanges) > 3 ? ' and '.(count($priceChanges) - 3).' more.' : '.';
                    $base .= ' Selling prices updated: '.implode(', ', $summaries).$extra;
                }

                return $base;
            })(),
            'grn.deleted' => "{$actor} permanently deleted GRN "
                .($ctx['grn_number'] ?? $subject ?? '?')
                .(! empty($ctx['branch']) ? ' (branch: "'.$ctx['branch'].'")' : '')
                .'. Previous status: '.($ctx['previous_status'] ?? '?').', '
                .($ctx['items_count'] ?? '?').' item(s).'
                .($ctx['stock_reversed'] ?? false
                    ? ' All stock quantities from this GRN have been reversed.'
                    : ' No stock changes were made (GRN was draft).'),

            // ── Inventory – Adjustments / Damage / Transfer ───────────────────
            'adjustment.created' => "{$actor} created stock adjustment #".($ctx['reference'] ?? '?')
                .(! empty($ctx['warehouse']) ? ' in warehouse "'.$ctx['warehouse'].'"' : '')
                .(! empty($ctx['items']) ? ' affecting '.$ctx['items'].' item(s)' : '').'.',
            'damage.created', 'damage.recorded' => "{$actor} recorded stock damage #".($ctx['reference'] ?? '?')
                .(! empty($ctx['items']) ? ' with '.$ctx['items'].' item(s)' : '')
                .(! empty($ctx['cost']) ? ' — estimated cost: '.$ctx['cost'] : '').'.',
            'damage.from_return' => "{$actor} recorded a damage write-off from a customer return"
                .(! empty($ctx['cost']) ? ' — estimated cost: '.$ctx['cost'] : '').'.',
            'transfer.created' => "{$actor} created stock transfer #".($ctx['reference'] ?? '?')
                .(! empty($ctx['from']) ? ' from "'.$ctx['from'].'" to "'.$ctx['to'].'"' : '')
                .(! empty($ctx['items']) ? ' - '.$ctx['items'].' item(s)' : '').'.',

            // ── Inventory – Stock Movements ───────────────────────────────────
            'stock.movement' => (function () use ($actor, $ctx): string {
                $product = $ctx['product'] ?? 'unknown product';
                $branch = $ctx['branch'] ?? 'unknown branch';
                $type = $ctx['movement_type'] ?? $ctx['movement_code'] ?? 'unknown';
                $before = $ctx['quantity_before'] ?? '?';
                $change = $ctx['quantity_change'] ?? '?';
                $after = $ctx['quantity_after'] ?? '?';
                $ref = $ctx['reference_number'] ?? null;

                $direction = is_numeric($change) && (float) $change >= 0 ? 'in' : 'out';
                $absChange = is_numeric($change) ? abs((float) $change) : $change;

                return "{$actor} recorded stock {$direction} for \"{$product}\" at \"{$branch}\" "
                    ."via {$type}: qty {$before} → {$after} ({$absChange} unit(s) {$direction})."
                    .($ref ? " Reference: {$ref}." : '');
            })(),

            // ── Finance ───────────────────────────────────────────────────────
            'expense.created' => "{$actor} recorded an expense under category \""
                .($ctx['category'] ?? 'unknown').'\" - amount: '.($ctx['amount'] ?? '?').'.',
            'expense.updated' => "{$actor} updated expense \""
                .($ctx['name'] ?? $subject ?? '?').'".'.$changes,
            'expense.deleted' => "{$actor} deleted expense \""
                .($ctx['name'] ?? $subject ?? '?').'".',
            'account.created' => "{$actor} created account \""
                .($ctx['name'] ?? $subject ?? 'unknown').'".',
            'account.updated' => "{$actor} updated account \""
                .($ctx['name'] ?? $subject ?? 'unknown').'".'.$changes,
            'account.deleted' => "{$actor} deleted account \""
                .($ctx['name'] ?? $subject ?? 'unknown').'".',
            'deposit.created' => "{$actor} recorded a deposit under category \""
                .($ctx['category'] ?? 'unknown').'\" - amount: '.($ctx['amount'] ?? '?').'.',

            // ── Credit Notes ──────────────────────────────────────────────────
            'credit_note.issued_overpayment' => "{$actor} issued a credit note of "
                .($ctx['amount'] ?? '?').' due to overpayment'
                .(! empty($ctx['transaction_id']) ? ' (transaction #'.$ctx['transaction_id'].')' : '').'.',
            'credit_note.issued' => ! empty($ctx['return'])
                ? "{$actor} issued credit note ".($subject ?? '?').' of '.($ctx['amount'] ?? '?')
                    .' against return #'.($ctx['return'] ?? '?').'.'
                : "{$actor} issued credit note ".($subject ?? '?').'.',
            'credit_note.remainder_issued' => "{$actor} issued a remainder credit note of "
                .($ctx['amount'] ?? '?').' on '.($subject ?? '?').'.',
            'credit_note.draft_created' => "{$actor} created a draft credit note of "
                .($ctx['amount'] ?? '?').'.',
            'credit_note.claimed' => "{$actor} applied credit note ".($subject ?? '?')
                .(! empty($ctx['invoice']) ? ' to invoice #'.$ctx['invoice'] : '').'.',
            'credit_note.voided' => "{$actor} voided credit note ".($subject ?? '?')
                .(! empty($ctx['reason']) ? ' — reason: '.$ctx['reason'] : '').'.',

            // ── Transactions / Payments ───────────────────────────────────────
            'transaction.created' => "{$actor} recorded a payment transaction of "
                .($ctx['amount'] ?? '?')
                .(! empty($ctx['method']) ? ' via '.strtoupper((string) $ctx['method']) : '')
                .(! empty($ctx['status']) ? ' (status: '.$ctx['status'].')' : '').'.',
            'transaction.allocated' => "{$actor} allocated "
                .($ctx['allocated'] ?? '?').' from a transaction of '.($ctx['amount'] ?? '?')
                .(! empty($ctx['leftover_credit']) && (float) $ctx['leftover_credit'] > 0
                    ? '. Remaining credit: '.$ctx['leftover_credit']
                    : '').'.',
            'transaction.approved' => "{$actor} approved transaction ".($subject ?? '?').'.',
            'transaction.rejected' => "{$actor} rejected transaction ".($subject ?? '?')
                .(! empty($ctx['reason']) ? ' — reason: '.$ctx['reason'] : '').'.',

            // ── Returns ───────────────────────────────────────────────────────
            'return.created' => "{$actor} created customer return #".($ctx['reference'] ?? '?')
                .(! empty($ctx['cn']) ? ' — credit note '.$ctx['cn'].' issued' : '')
                .(! empty($ctx['total']) ? ' for '.$ctx['total'] : '').'.',
            'return_item.silent_writeoff' => "{$actor} wrote off a returned item as damaged "
                .(! empty($ctx['quantity']) ? '(qty: '.$ctx['quantity'].')' : '').'.',

            // ── POS Sessions ──────────────────────────────────────────────────
            'pos_session.opened' => "{$actor} opened a POS session"
                .(! empty($ctx['opening_balance']) ? ' with opening balance '.$ctx['opening_balance'] : '').'.',
            'pos_session.closed' => "{$actor} closed a POS session"
                .(! empty($ctx['closing_balance']) ? ' with closing balance '.$ctx['closing_balance'] : '')
                .(! empty($ctx['variance']) && (float) $ctx['variance'] !== 0.0 ? ' (variance: '.$ctx['variance'].')' : '').'.',

            // ── Held sales ────────────────────────────────────────────────────
            'held_sale.created' => "{$actor} held sale #".($ctx['reference'] ?? '?')
                .(! empty($ctx['items']) ? ' ('.$ctx['items'].' item(s))' : '').'.',
            'held_sale.resumed' => "{$actor} resumed held sale #".($ctx['reference'] ?? '?').'.',
            'held_sale.discarded' => "{$actor} discarded held sale #".($ctx['reference'] ?? '?').'.',

            // ── Till cash movements ───────────────────────────────────────────
            'cash_movement.withdrawn' => "{$actor} withdrew ".($ctx['amount'] ?? '?').' from the till'
                .(! empty($ctx['reason']) ? ' — reason: '.$ctx['reason'] : '').'.',
            'cash_movement.cash_in' => "{$actor} added ".($ctx['amount'] ?? '?').' cash to the till.',

            // ── Till access ───────────────────────────────────────────────────
            'till_access.updated' => "{$actor} updated till access for ".($subject ?? 'a user').'.',

            // ── Impersonation ─────────────────────────────────────────────────
            'user.impersonated' => "{$actor} was impersonated by central admin "
                .($ctx['central_admin'] ?? '?').'.',
            'tenant.impersonation_started' => 'Central admin '.($ctx['central_admin'] ?? '?')
                .' generated an impersonation session for tenant user '.($subject ?? '?')
                .' (single-use link, valid 2 minutes).',

            // ── Branches / Tills (landlord-managed) ───────────────────────────
            'branch.created' => "{$actor} created branch \"".($ctx['name'] ?? $subject ?? 'unknown').'"'
                .(! empty($ctx['city']) ? ' in '.$ctx['city'] : '').'.',
            'branch.updated' => "{$actor} updated branch \"".($ctx['name'] ?? $subject ?? 'unknown').'".'.$changes,
            'branch.deleted' => "{$actor} deleted branch \"".($ctx['name'] ?? $subject ?? 'unknown').'"'
                .(! empty($ctx['city']) ? ' in '.$ctx['city'] : '').'.',
            'till.created' => "{$actor} created till \"".($ctx['name'] ?? $subject ?? 'unknown').'"'
                .(! empty($ctx['identifier']) ? ' ('.$ctx['identifier'].')' : '')
                .(! empty($ctx['branch']) ? ' at branch "'.$ctx['branch'].'"' : '').'.',
            'till.updated' => "{$actor} updated till \"".($ctx['name'] ?? $subject ?? 'unknown').'".'.$changes,
            'till.deleted' => "{$actor} deleted till \"".($ctx['name'] ?? $subject ?? 'unknown').'"'
                .(! empty($ctx['identifier']) ? ' ('.$ctx['identifier'].')' : '').'.',

            // ── Inventory – Adjustments / Transfers / Damage ──────────────────
            'stock_adjustment.created' => "{$actor} created stock adjustment"
                .(! empty($ctx['product']) ? ' for "'.$ctx['product'].'"' : '')
                .(! empty($ctx['branch']) ? ' at "'.$ctx['branch'].'"' : '')
                .(! empty($ctx['reason']) ? ' (reason: '.$ctx['reason'].')' : '')
                .(isset($ctx['before_stock'], $ctx['new_stock'])
                    ? ': stock '.$ctx['before_stock'].' → '.$ctx['new_stock'].'.'
                    : '.'),
            'stock_adjustment.deleted' => "{$actor} deleted stock adjustment"
                .(! empty($ctx['product']) ? ' for "'.$ctx['product'].'"' : '')
                .(! empty($ctx['branch']) ? ' at "'.$ctx['branch'].'"' : '').'.',
            'stock_transfer.created' => "{$actor} created stock transfer of ".($ctx['quantity'] ?? '?')
                .' unit(s) of "'.($ctx['product'] ?? '?').'" from "'.($ctx['from'] ?? '?')
                .'" to "'.($ctx['to'] ?? '?').'".',
            'stock_transfer.deleted' => "{$actor} deleted stock transfer of ".($ctx['quantity'] ?? '?')
                .' unit(s) of "'.($ctx['product'] ?? '?').'" from "'.($ctx['from'] ?? '?')
                .'" to "'.($ctx['to'] ?? '?').'".',
            'damage.deleted' => "{$actor} deleted damage record #".($ctx['reference'] ?? '?').'.',

            // ── Invoices / Sales Orders ───────────────────────────────────────
            'invoice.deleted' => "{$actor} deleted invoice ".($ctx['reference'] ?? $subject ?? '?')
                .(! empty($ctx['total']) ? ' (total: '.$ctx['total'].')' : '').'.',
            'invoice.legacy_created' => "{$actor} created a legacy invoice record #".($ctx['reference'] ?? '?')
                .(! empty($ctx['total']) ? ' — total: '.$ctx['total'] : '').'.',
            'invoice.credit_applied' => "{$actor} applied a credit-note payment of ".($ctx['amount'] ?? '?')
                .' to invoice '.($ctx['reference'] ?? $subject ?? '?')
                .(! empty($ctx['balance']) ? ' — remaining balance: '.$ctx['balance'] : '').'.',
            'sales_order.created' => "{$actor} created sales order ".($ctx['reference'] ?? '?')
                .(! empty($ctx['customer']) ? ' for "'.$ctx['customer'].'"' : '')
                .(! empty($ctx['branch']) ? ' at "'.$ctx['branch'].'"' : '')
                .(! empty($ctx['items']) ? ' with '.$ctx['items'].' line(s)' : '')
                .(! empty($ctx['custom_items']) ? ' ('.$ctx['custom_items'].' custom)' : '')
                .(! empty($ctx['deadline']) ? ' due '.$ctx['deadline'] : '')
                .(! empty($ctx['credit_applied']) && (float) $ctx['credit_applied'] > 0
                    ? ' (credit applied: '.$ctx['credit_applied'].')' : '')
                .(! empty($ctx['total']) ? ' — total: '.$ctx['total'] : '').'.',
            'sales_order.updated' => "{$actor} updated sales order ".($ctx['reference'] ?? $subject ?? '?')
                .(! empty($ctx['items']) ? ' — now '.$ctx['items'].' line(s)' : '')
                .(! empty($ctx['total']) ? ', total: '.$ctx['total'] : '').'.',
            'sales_order.status_changed' => "{$actor} moved sales order ".($ctx['reference'] ?? $subject ?? '?')
                .' to "'.($ctx['to'] ?? '?').'"'
                .(! empty($ctx['from']) ? ' from "'.$ctx['from'].'"' : '').'.',
            'sales_order.cancelled' => "{$actor} cancelled sales order ".($ctx['reference'] ?? $subject ?? '?')
                .(! empty($ctx['reason']) ? ' — reason: '.$ctx['reason'] : '').'.',
            'sales_order.invoiced' => "{$actor} invoiced sales order ".($ctx['reference'] ?? $subject ?? '?')
                .' as '.($ctx['invoice'] ?? '?')
                .(! empty($ctx['total']) ? ' — total: '.$ctx['total'] : '')
                .(! empty($ctx['repriced_from']) ? ' (repriced from '.$ctx['repriced_from'].')' : '').'.',

            // ── Purchase Orders ───────────────────────────────────────────────
            'purchase_order.created' => "{$actor} created purchase order ".($ctx['po_number'] ?? $subject ?? '?')
                .(! empty($ctx['supplier']) ? ' from "'.$ctx['supplier'].'"' : '')
                .(! empty($ctx['total']) ? ' — total: '.$ctx['total'] : '').'.',
            'purchase_order.sent' => "{$actor} sent purchase order ".($ctx['po_number'] ?? $subject ?? '?').'.',
            'purchase_order.cancelled' => "{$actor} cancelled purchase order ".($ctx['po_number'] ?? $subject ?? '?')
                .(! empty($ctx['reason']) ? ' — reason: '.$ctx['reason'] : '').'.',
            'purchase_order.receipt_applied' => "{$actor} applied a receipt to purchase order ".($ctx['po_number'] ?? '?')
                .(! empty($ctx['status']) ? ' — status: '.str_replace('_', ' ', (string) $ctx['status']) : '').'.',

            // ── Returns / Suppliers ───────────────────────────────────────────
            'return.deleted' => "{$actor} deleted customer return #".($ctx['reference'] ?? '?')
                .(! empty($ctx['reason']) ? ' — reason: '.$ctx['reason'] : '').'.',
            'supplier.blacklisted' => "{$actor} blacklisted supplier \"".($ctx['name'] ?? $subject ?? 'unknown').'"'
                .(! empty($ctx['reason']) ? ' — reason: '.$ctx['reason'] : '').'.',
            'supplier.unblacklisted' => "{$actor} removed supplier \"".($ctx['name'] ?? $subject ?? 'unknown').'" from the blacklist.',

            // ── Transactions ──────────────────────────────────────────────────
            'transaction.reverted_to_pending' => "{$actor} reverted transaction ".($subject ?? '?').' to pending status.',

            // ── Vouchers / Loyalty ────────────────────────────────────────────
            'voucher.generated' => "{$actor} generated voucher ".($ctx['code'] ?? '?')
                .(! empty($ctx['value']) ? ' (value: '.$ctx['value'].')' : '').'.',
            'voucher.redeemed' => "{$actor} redeemed voucher ".($ctx['code'] ?? '?')
                .(! empty($ctx['value']) ? ' (value: '.$ctx['value'].')' : '').'.',
            'voucher.redemption_reversed' => "{$actor} reversed the redemption of voucher ".($ctx['code'] ?? '?')
                .(! empty($ctx['reason']) ? ' — reason: '.$ctx['reason'] : '').'.',
            'voucher.voided' => "{$actor} voided voucher ".($ctx['code'] ?? '?')
                .(! empty($ctx['reason']) ? ' — reason: '.$ctx['reason'] : '').'.',
            'loyalty.earned' => "{$actor} earned ".($ctx['points'] ?? '?').' loyalty point(s) '
                .(! empty($ctx['invoice']) ? ' on invoice '.$ctx['invoice'] : '').'.',
            'loyalty.redeemed' => "{$actor} redeemed ".($ctx['points'] ?? '?').' loyalty point(s) '
                .(! empty($ctx['value']) ? ' for '.$ctx['value'] : '').'.',
            'loyalty.tier_changed' => "{$actor} moved to loyalty tier \"".($ctx['tier'] ?? '?').'".',
            'loyalty.adjusted' => "{$actor} adjusted loyalty points by ".($ctx['points'] ?? '?')
                .(! empty($ctx['reason']) ? ' — reason: '.$ctx['reason'] : '').'.',

            // ── Loyalty programs / Categories / Bundles ──────────────────────
            'loyalty_program.created' => "{$actor} created loyalty program \"".($ctx['name'] ?? $subject ?? 'unknown').'".',
            'loyalty_program.updated' => "{$actor} updated loyalty program \"".($ctx['name'] ?? $subject ?? 'unknown').'".',
            'main_category.created' => "{$actor} created main category \"".($ctx['name'] ?? $subject ?? 'unknown').'".',
            'main_category.updated' => "{$actor} updated main category \"".($ctx['name'] ?? $subject ?? 'unknown').'".',
            'main_category.deleted' => "{$actor} deleted main category \"".($ctx['name'] ?? $subject ?? 'unknown').'".',
            'sub_category.created' => "{$actor} created sub-category \"".($ctx['name'] ?? $subject ?? 'unknown').'".',
            'sub_category.updated' => "{$actor} updated sub-category \"".($ctx['name'] ?? $subject ?? 'unknown').'".',
            'sub_category.deleted' => "{$actor} deleted sub-category \"".($ctx['name'] ?? $subject ?? 'unknown').'".',
            'product_bundle.created' => "{$actor} created product bundle \"".($ctx['name'] ?? $subject ?? 'unknown').'".',
            'product_bundle.updated' => "{$actor} updated product bundle \"".($ctx['name'] ?? $subject ?? 'unknown').'".',
            'product_bundle.deleted' => "{$actor} deleted product bundle \"".($ctx['name'] ?? $subject ?? 'unknown').'".',

            // ── Serials / Batches ─────────────────────────────────────────────
            'serial.lost' => "{$actor} marked serial ".($ctx['serial_number'] ?? '?').' as lost'
                .(! empty($ctx['notes']) ? ' — notes: '.$ctx['notes'] : '').'.',
            'serial.damaged' => "{$actor} marked serial ".($ctx['serial_number'] ?? '?').' as damaged'
                .(! empty($ctx['notes']) ? ' — notes: '.$ctx['notes'] : '').'.',
            'serial.written_off' => "{$actor} wrote off serial ".($ctx['serial_number'] ?? '?')
                .(! empty($ctx['reason']) ? ' — reason: '.$ctx['reason'] : '').'.',
            'serial.repair_started' => "{$actor} started a repair on serial ".($ctx['serial_number'] ?? '?')
                .(! empty($ctx['description']) ? ' — '.$ctx['description'] : '').'.',
            'serial.repair_completed' => "{$actor} completed a repair on serial ".($ctx['serial_number'] ?? '?')
                .(! empty($ctx['outcome']) ? ' — outcome: '.$ctx['outcome'] : '').'.',
            'batch.recalled' => "{$actor} recalled batch ".($ctx['internal_batch_number'] ?? $ctx['batch_number'] ?? $subject ?? '?')
                .(! empty($ctx['reason']) ? ' — reason: '.$ctx['reason'] : '').'.',
            'batch.deactivated' => "{$actor} deactivated batch ".($ctx['internal_batch_number'] ?? $subject ?? '?')
                .(! empty($ctx['reason']) ? ' — reason: '.$ctx['reason'] : '')
                .' — it no longer appears anywhere lots are offered.',
            'batch.reactivated' => "{$actor} reactivated batch ".($ctx['internal_batch_number'] ?? $subject ?? '?')
                .(! empty($ctx['status']) ? " as {$ctx['status']}" : '').'.',
            'batches.flagged_expired' => 'System flagged '.($ctx['count'] ?? '?')
                .' batch(es) as expired during a scheduled sweep.',

            // ── Tenant (master control) ───────────────────────────────────────
            'tenant.suspended' => 'Tenant '.($subject ?? '"?"').' was suspended'
                .(! empty($ctx['reason']) ? ' — reason: '.$ctx['reason'] : '')
                .(! empty($ctx['central_admin']) ? ' by central admin '.$ctx['central_admin'] : '').'.',
            'tenant.resumed' => 'Tenant '.($subject ?? '"?"').' was resumed'
                .(! empty($ctx['central_admin']) ? ' by central admin '.$ctx['central_admin'] : '').'.',
            'tenant.entitlements_updated' => 'Entitlements updated for tenant '.($subject ?? '"?"').'.'
                .(! empty($ctx['count']) ? ' '.$ctx['count'].' permission(s) granted.' : ' No permissions granted.'),
            'tenant.admin_password_reset' => 'Password reset for tenant admin '.($ctx['admin_email'] ?? '?')
                .(! empty($ctx['central_admin']) ? ' by central admin '.$ctx['central_admin'] : '').'.',
            'tenant.catalog_reset' => 'Product catalog reset for tenant '.($subject ?? '"?"')
                .(! empty($ctx['central_admin']) ? ' by central admin '.$ctx['central_admin'] : '')
                .'. Removed '.($ctx['products'] ?? '?').' product(s), '.($ctx['categories'] ?? '?').' categor(y/ies), '
                .($ctx['bundles'] ?? '?').' bundle(s), '.($ctx['stock_batches'] ?? '?').' stock batch(es), '
                .($ctx['product_serials'] ?? '?').' serial(s). "Packaging & Add-ons" was kept, emptied.',
            'test_instance.synced' => 'Test instance '.($subject ?? '"?"').' was refreshed from its live tenant'
                .(! empty($ctx['central_admin']) ? ' by central admin '.$ctx['central_admin'] : '')
                .'. Copied '.($ctx['products'] ?? '?').' product(s), '.($ctx['customers'] ?? '?').' customer(s), '
                .($ctx['invoices'] ?? '?').' invoice(s), '.($ctx['branches'] ?? '?').' branch(es), '
                .($ctx['users'] ?? '?').' user(s) — '.($ctx['total_rows'] ?? '?').' rows in '
                .($ctx['seconds'] ?? '?').'s.',

            // ── Default ───────────────────────────────────────────────────────
            default => ! empty($ctx['description'])
                ? (string) $ctx['description']
                : ucwords(str_replace(['.', '_'], [' - ', ' '], $action)).($subject ? ' on '.$subject : '').'.',
        };

        return rtrim(trim($description), '.').'.';
    }
}
