<?php

declare(strict_types=1);

/**
 * ActivityLog
 * 
 * Logs and retrieves workspace activity for audit trail
 */
class ActivityLog
{
    /**
     * Action types
     */
    public const ACTIONS = [
        // Client actions
        'client_created' => 'Created client',
        'client_updated' => 'Updated client',
        'client_deleted' => 'Deleted client',
        
        // Proposal actions
        'proposal_created' => 'Created proposal',
        'proposal_updated' => 'Updated proposal',
        'proposal_deleted' => 'Deleted proposal',
        'proposal_sent' => 'Sent proposal',
        'proposal_viewed' => 'Proposal viewed',
        'proposal_accepted' => 'Proposal accepted',
        'proposal_rejected' => 'Proposal rejected',
        
        // Contract actions
        'contract_created' => 'Created contract',
        'contract_updated' => 'Updated contract',
        'contract_deleted' => 'Deleted contract',
        'contract_sent' => 'Sent contract',
        'contract_signed' => 'Contract signed',
        'contract_status_changed' => 'Changed contract status',
        'contract_signing_link_generated' => 'Generated contract signing link',

        // Contract module actions
        'contract_module_created' => 'Created contract module',
        'contract_module_updated' => 'Updated contract module',
        'contract_module_deleted' => 'Deleted contract module',

        // Contract template actions
        'contract_template_module_attached' => 'Attached module to contract template',
        'contract_template_module_detached' => 'Detached module from contract template',
        'contract_template_modules_reordered' => 'Reordered contract template modules',
        
        // Invoice actions
        'invoice_created' => 'Created invoice',
        'invoice_updated' => 'Updated invoice',
        'invoice_deleted' => 'Deleted invoice',
        'invoice_sent' => 'Sent invoice',
        'invoice_paid' => 'Invoice paid',
        'payment_received' => 'Payment received',

        // Invoice item actions
        'invoice_item_created' => 'Created invoice item',
        'invoice_item_updated' => 'Updated invoice item',
        'invoice_item_deleted' => 'Deleted invoice item',

        // Invoice settings actions
        'invoice_settings_updated' => 'Updated invoice settings',
        'invoice_logo_uploaded' => 'Uploaded invoice logo',
        'invoice_signature_uploaded' => 'Uploaded invoice signature',
        'invoice_signature_removed' => 'Removed invoice signature',
        'tax_bracket_created' => 'Created tax bracket',
        
        // Template actions
        'template_created' => 'Created template',
        'template_updated' => 'Updated template',
        'template_deleted' => 'Deleted template',

        // Template module actions
        'template_modules_attached' => 'Attached modules to template',
        'template_module_detached' => 'Detached module from template',
        'template_modules_reordered' => 'Reordered template modules',

        // Template preview actions
        'template_previewed' => 'Previewed template',
        'contract_template_previewed' => 'Previewed contract template',
        
        // Member actions
        'member_invited' => 'Invited member',
        'member_joined' => 'Member joined',
        'member_removed' => 'Removed member',
        'member_role_changed' => 'Changed member role',
        
        // Role actions
        'role_created' => 'Created role',
        'role_updated' => 'Updated role',
        'role_deleted' => 'Deleted role',
        
        // Settings actions
        'settings_updated' => 'Updated settings',
        'workspace_updated' => 'Updated workspace',
        
        // Auth actions
        'user_login' => 'User logged in',
        'user_logout' => 'User logged out',

        // Subscription / billing actions
        'subscription_renewed' => 'Renewed subscription',
        'subscription_updated' => 'Updated subscription',
        'subscription_canceled' => 'Canceled subscription',

        // Label actions
        'label_created' => 'Created label',
        'label_deleted' => 'Deleted label',
        'label_renamed' => 'Renamed label',
    ];

    /**
     * Log an activity
     */
    public static function log(
        int $companyId,
        ?int $userId,
        string $action,
        ?string $entityType = null,
        ?int $entityId = null,
        ?string $entityName = null,
        ?array $oldValues = null,
        ?array $newValues = null
    ): bool {
        $pdo = getPDO();
        
        $stmt = $pdo->prepare('
            INSERT INTO workspace_activity_log 
            (company_id, user_id, action, entity_type, entity_id, entity_name, old_values, new_values, ip_address, user_agent)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        ');

        return $stmt->execute([
            $companyId,
            $userId,
            $action,
            $entityType,
            $entityId,
            $entityName,
            $oldValues ? json_encode($oldValues) : null,
            $newValues ? json_encode($newValues) : null,
            $_SERVER['REMOTE_ADDR'] ?? null,
            $_SERVER['HTTP_USER_AGENT'] ?? null,
        ]);
    }

    /**
     * Get activity log for a workspace
     */
    public static function getForWorkspace(
        int $companyId,
        int $page = 1,
        int $perPage = 50,
        array $filters = []
    ): array {
        $pdo = getPDO();
        $offset = ($page - 1) * $perPage;

        $where = ['wal.company_id = ?'];
        $params = [$companyId];

        if (!empty($filters['user_id'])) {
            $where[] = 'wal.user_id = ?';
            $params[] = $filters['user_id'];
        }

        if (!empty($filters['action'])) {
            $where[] = 'wal.action = ?';
            $params[] = $filters['action'];
        }

        if (!empty($filters['entity_type'])) {
            $where[] = 'wal.entity_type = ?';
            $params[] = $filters['entity_type'];
        }

        if (!empty($filters['date_from'])) {
            $where[] = 'wal.created_at >= ?';
            $params[] = $filters['date_from'];
        }

        if (!empty($filters['date_to'])) {
            $where[] = 'wal.created_at <= ?';
            $params[] = $filters['date_to'] . ' 23:59:59';
        }

        $whereClause = implode(' AND ', $where);

        // Get total count
        $countStmt = $pdo->prepare("SELECT COUNT(*) FROM workspace_activity_log wal WHERE $whereClause");
        $countStmt->execute($params);
        $total = (int)$countStmt->fetchColumn();

        // Get activities
        $sql = "
            SELECT wal.*, u.name as user_name, u.email as user_email
            FROM workspace_activity_log wal
            LEFT JOIN users u ON wal.user_id = u.id
            WHERE $whereClause
            ORDER BY wal.created_at DESC
            LIMIT $perPage OFFSET $offset
        ";

        $stmt = $pdo->prepare($sql);
        $stmt->execute($params);
        $activities = $stmt->fetchAll();

        // Format activities
        $activities = array_map(function($activity) {
            $activity['action_label'] = self::ACTIONS[$activity['action']] ?? $activity['action'];
            $activity['old_values'] = $activity['old_values'] ? json_decode($activity['old_values'], true) : null;
            $activity['new_values'] = $activity['new_values'] ? json_decode($activity['new_values'], true) : null;
            $activity['time_ago'] = self::timeAgo($activity['created_at']);
            return $activity;
        }, $activities);

        return [
            'activities' => $activities,
            'total' => $total,
            'page' => $page,
            'per_page' => $perPage,
            'total_pages' => ceil($total / $perPage),
        ];
    }

    /**
     * Get activity summary for a workspace
     */
    public static function getSummary(int $companyId, int $days = 30): array
    {
        $pdo = getPDO();

        $stmt = $pdo->prepare('
            SELECT action, COUNT(*) as count
            FROM workspace_activity_log
            WHERE company_id = ? AND created_at >= DATE_SUB(NOW(), INTERVAL ? DAY)
            GROUP BY action
            ORDER BY count DESC
        ');
        $stmt->execute([$companyId, $days]);

        $summary = [];
        foreach ($stmt->fetchAll() as $row) {
            $summary[$row['action']] = [
                'count' => (int)$row['count'],
                'label' => self::ACTIONS[$row['action']] ?? $row['action'],
            ];
        }

        return $summary;
    }

    /**
     * Get recent activity for a workspace
     */
    public static function getRecent(int $companyId, int $limit = 10): array
    {
        $pdo = getPDO();

        $stmt = $pdo->prepare('
            SELECT wal.*, u.name as user_name
            FROM workspace_activity_log wal
            LEFT JOIN users u ON wal.user_id = u.id
            WHERE wal.company_id = ?
            ORDER BY wal.created_at DESC
            LIMIT ?
        ');
        $stmt->execute([$companyId, $limit]);

        return array_map(function($activity) {
            $activity['action_label'] = self::ACTIONS[$activity['action']] ?? $activity['action'];
            $activity['time_ago'] = self::timeAgo($activity['created_at']);
            return $activity;
        }, $stmt->fetchAll());
    }

    /**
     * Get activity for a specific entity
     */
    public static function getForEntity(string $entityType, int $entityId, int $limit = 50): array
    {
        $pdo = getPDO();

        $stmt = $pdo->prepare('
            SELECT wal.*, u.name as user_name
            FROM workspace_activity_log wal
            LEFT JOIN users u ON wal.user_id = u.id
            WHERE wal.entity_type = ? AND wal.entity_id = ?
            ORDER BY wal.created_at DESC
            LIMIT ?
        ');
        $stmt->execute([$entityType, $entityId, $limit]);

        return array_map(function($activity) {
            $activity['action_label'] = self::ACTIONS[$activity['action']] ?? $activity['action'];
            $activity['time_ago'] = self::timeAgo($activity['created_at']);
            return $activity;
        }, $stmt->fetchAll());
    }

    /**
     * Get unique action types for filtering
     */
    public static function getActionTypes(int $companyId): array
    {
        $pdo = getPDO();

        $stmt = $pdo->prepare('
            SELECT DISTINCT action FROM workspace_activity_log
            WHERE company_id = ?
            ORDER BY action
        ');
        $stmt->execute([$companyId]);

        $actions = [];
        foreach ($stmt->fetchAll() as $row) {
            $actions[$row['action']] = self::ACTIONS[$row['action']] ?? $row['action'];
        }

        return $actions;
    }

    /**
     * Get unique entity types for filtering
     */
    public static function getEntityTypes(int $companyId): array
    {
        $pdo = getPDO();

        $stmt = $pdo->prepare('
            SELECT DISTINCT entity_type FROM workspace_activity_log
            WHERE company_id = ? AND entity_type IS NOT NULL
            ORDER BY entity_type
        ');
        $stmt->execute([$companyId]);

        return array_column($stmt->fetchAll(), 'entity_type');
    }

    /**
     * Format time ago
     */
    private static function timeAgo(string $datetime): string
    {
        $time = strtotime($datetime);
        $diff = time() - $time;

        if ($diff < 5) {
            return 'Just now';
        } elseif ($diff < 60) {
            $secs = max(1, $diff);
            return $secs . ' second' . ($secs !== 1 ? 's' : '') . ' ago';
        } elseif ($diff < 3600) {
            $mins = floor($diff / 60);
            return $mins . ' minute' . ($mins > 1 ? 's' : '') . ' ago';
        } elseif ($diff < 86400) {
            $hours = floor($diff / 3600);
            return $hours . ' hour' . ($hours > 1 ? 's' : '') . ' ago';
        } elseif ($diff < 604800) {
            $days = floor($diff / 86400);
            return $days . ' day' . ($days > 1 ? 's' : '') . ' ago';
        } else {
            return date('M j, Y', $time);
        }
    }

    /**
     * Clean old activity logs (older than specified days)
     */
    public static function cleanup(int $days = 90): int
    {
        $pdo = getPDO();
        $stmt = $pdo->prepare('DELETE FROM workspace_activity_log WHERE created_at < DATE_SUB(NOW(), INTERVAL ? DAY)');
        $stmt->execute([$days]);
        return $stmt->rowCount();
    }
}
