<?php
/**
 * ITSWEBER CMS – Activity Logger Service
 *
 * Logs admin actions for auditing. Can be called statically from any controller.
 * Silently fails if the table doesn't exist or the feature is disabled.
 *
 * @author    Benny Weber (ITSWEBER)
 * @copyright © ITSWEBER – www.itsweber.de
 * @contact   kontakt@itsweber.de
 */

namespace App\Services;

use App\Core\App;

class ActivityLogger
{
    private static ?bool $tableExistsCache = null;

    /**
     * Log an admin action.
     */
    public static function log(
        string  $action,
        string  $resourceType,
        ?int    $resourceId = null,
        ?string $resourceName = null,
        ?int    $userId = null,
        ?string $details = null
    ): void {
        // Check if feature is enabled
        if (setting('activity_log_enabled', '1') !== '1') {
            return;
        }

        if (!static::tableExists()) {
            return;
        }

        // Auto-detect user and IP if not provided
        if ($userId === null) {
            $app = App::getInstance();
            if ($app && $app->hasService('auth')) {
                $userId = $app->service('auth')->userId() ?? 0;
            } else {
                $userId = 0;
            }
        }

        $ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';

        try {
            $db = App::getInstance()->service('database');
            $db->insert('iw_activity_logs', [
                'user_id'       => $userId,
                'action'        => $action,
                'resource_type' => $resourceType,
                'resource_id'   => $resourceId,
                'resource_name' => $resourceName ? mb_substr($resourceName, 0, 255) : null,
                'details'       => $details,
                'ip_address'    => $ip,
            ]);
        } catch (\Throwable $e) {
            // Silently fail – logging should never break the app
        }
    }

    /**
     * Get paginated activity logs with user names.
     */
    public static function paginated(int $page = 1, int $perPage = 30, ?string $filterAction = null, ?string $filterType = null): array
    {
        if (!static::tableExists()) {
            return ['items' => [], 'total' => 0, 'page' => 1, 'perPage' => $perPage, 'pages' => 1];
        }

        $db = App::getInstance()->service('database');

        $page    = max(1, $page);
        $perPage = max(1, min(100, $perPage));
        $offset  = ($page - 1) * $perPage;

        $where  = [];
        $params = [];

        if ($filterAction) {
            $where[]            = 'a.action = :action';
            $params['action']   = $filterAction;
        }
        if ($filterType) {
            $where[]            = 'a.resource_type = :rtype';
            $params['rtype']    = $filterType;
        }

        $whereClause = $where ? 'WHERE ' . implode(' AND ', $where) : '';

        $total = (int) $db->fetchColumn(
            "SELECT COUNT(*) FROM iw_activity_logs a $whereClause",
            $params
        );

        $items = $db->fetchAll(
            "SELECT a.*, u.username AS user_name
             FROM iw_activity_logs a
             LEFT JOIN iw_users u ON a.user_id = u.id
             $whereClause
             ORDER BY a.created_at DESC
             LIMIT " . (int) $perPage . " OFFSET " . (int) $offset,
            $params
        );

        return [
            'items'   => $items,
            'total'   => $total,
            'page'    => $page,
            'perPage' => $perPage,
            'pages'   => (int) ceil($total / $perPage),
        ];
    }

    /**
     * Get distinct action types for filter dropdown.
     */
    public static function distinctActions(): array
    {
        if (!static::tableExists()) {
            return [];
        }
        $db = App::getInstance()->service('database');
        return array_column(
            $db->fetchAll("SELECT DISTINCT action FROM iw_activity_logs ORDER BY action"),
            'action'
        );
    }

    /**
     * Get distinct resource types for filter dropdown.
     */
    public static function distinctResourceTypes(): array
    {
        if (!static::tableExists()) {
            return [];
        }
        $db = App::getInstance()->service('database');
        return array_column(
            $db->fetchAll("SELECT DISTINCT resource_type FROM iw_activity_logs ORDER BY resource_type"),
            'resource_type'
        );
    }

    private static function tableExists(): bool
    {
        if (static::$tableExistsCache !== null) {
            return static::$tableExistsCache;
        }

        try {
            $db = App::getInstance()->service('database');
            $db->query("SELECT 1 FROM iw_activity_logs LIMIT 1");
            static::$tableExistsCache = true;
        } catch (\Throwable $e) {
            static::$tableExistsCache = false;
        }

        return static::$tableExistsCache;
    }
}
