<?php

namespace App\Services\System;

use Illuminate\Support\Str;

class ActivityFormatter
{
    /**
     * Get a friendly name for the model.
     */
    public static function getFriendlyModelName(?string $model): string
    {
        if (! $model) {
            return 'System';
        }

        $className = class_basename($model);

        // Custom mapping for specific models
        $mapping = [
            'SystemSetting' => 'System Config',
            'User' => 'User Profile',
            'Role' => 'Access Role',
            'Permission' => 'Access Permission',
            'MobileSetting' => 'Mobile Config',
        ];

        return $mapping[$className] ?? Str::headline($className);
    }

    /**
     * Get badge class for the event.
     */
    public static function getEventBadgeClass(string $event): string
    {
        return match (strtolower($event)) {
            'created' => 'text-bg-success',
            'updated' => 'text-bg-warning',
            'deleted' => 'text-bg-danger',
            'restored' => 'text-bg-info',
            'login', 'login_attempt' => 'text-bg-info',
            'logout' => 'text-bg-secondary',
            'password_changed', 'password reset' => 'text-bg-primary',
            default => 'text-bg-theme-1',
        };
    }

    /**
     * Get icon for the event.
     */
    public static function getEventIcon(string $event): string
    {
        return match (strtolower($event)) {
            'created' => 'bi-plus-circle',
            'updated' => 'bi-pencil-square',
            'deleted' => 'bi-trash',
            'restored' => 'bi-arrow-counterclockwise',
            'login', 'login_attempt' => 'bi-box-arrow-in-right',
            'logout' => 'bi-box-arrow-right',
            'password_changed', 'password reset' => 'bi-key',
            default => 'bi-info-circle',
        };
    }

    /**
     * Formats the changes between old and new properties.
     */
    public static function formatChanges(array $properties): array
    {
        $old = $properties['old'] ?? [];
        $new = $properties['attributes'] ?? [];

        $changes = [];

        // If it's a "created" event, show all attributes
        if (empty($old) && ! empty($new)) {
            foreach ($new as $key => $value) {
                if (self::isSensitive($key)) {
                    continue;
                }
                $changes[] = [
                    'field' => Str::headline($key),
                    'old' => null,
                    'new' => self::formatValue($value),
                ];
            }

            return $changes;
        }

        // For updates, show only changed fields
        foreach ($new as $key => $value) {
            if (self::isSensitive($key)) {
                continue;
            }

            $oldValue = $old[$key] ?? null;

            // Loose comparison to handle type juggling from DB
            if ($oldValue != $value) {
                $changes[] = [
                    'field' => Str::headline($key),
                    'old' => self::formatValue($oldValue),
                    'new' => self::formatValue($value),
                ];
            }
        }

        return $changes;
    }

    private static function isSensitive(string $key): bool
    {
        $sensitive = ['password', 'remember_token', 'secret', 'key', 'token', '2fa_secret'];
        foreach ($sensitive as $s) {
            if (str_contains(strtolower($key), $s)) {
                return true;
            }
        }

        return false;
    }

    private static function formatValue(mixed $value): string
    {
        if (is_null($value)) {
            return 'NULL';
        }
        if (is_bool($value)) {
            return $value ? 'TRUE' : 'FALSE';
        }

        if (is_array($value) || is_object($value)) {
            return json_encode($value, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
        }

        if ($value === '') {
            return '[empty]';
        }

        // Truncate long values but keep it readable
        if (is_string($value) && strlen($value) > 200) {
            return substr($value, 0, 197).'...';
        }

        return (string) $value;
    }
}
