<?php

declare(strict_types=1);

namespace App\Framework\Database\Examples;

use App\Framework\Core\ValueObjects\Duration;
use App\Framework\Database\AsyncDatabaseDecorator;

/**
 * Real-world examples for AsyncDatabaseDecorator
 */
final readonly class AsyncDatabaseExample
{
    public function __construct(
        private AsyncDatabaseDecorator $db
    ) {
    }

    /**
     * Example: Dashboard data aggregation
     */
    public function loadDashboardData(int $userId): array
    {
        return $this->db->aggregate([
            'user_profile' => [
                'sql' => 'SELECT id, name, email, avatar FROM users WHERE id = ?',
                'params' => [$userId],
                'method' => 'queryOne',
            ],
            'user_stats' => [
                'sql' => 'SELECT COUNT(*) as post_count FROM posts WHERE user_id = ?',
                'params' => [$userId],
                'method' => 'queryScalar',
            ],
            'recent_orders' => [
                'sql' => 'SELECT id, total, created_at FROM orders WHERE user_id = ? ORDER BY created_at DESC LIMIT 5',
                'params' => [$userId],
            ],
            'unread_notifications' => [
                'sql' => 'SELECT COUNT(*) FROM notifications WHERE user_id = ? AND read_at IS NULL',
                'params' => [$userId],
                'method' => 'queryScalar',
            ],
            'account_balance' => [
                'sql' => 'SELECT balance FROM accounts WHERE user_id = ?',
                'params' => [$userId],
                'method' => 'queryScalar',
            ],
        ]);
    }

    /**
     * Example: E-commerce product page data
     */
    public function loadProductPageData(int $productId): array
    {
        return $this->db->aggregate([
            'product' => [
                'sql' => 'SELECT * FROM products WHERE id = ?',
                'params' => [$productId],
                'method' => 'queryOne',
            ],
            'inventory' => [
                'sql' => 'SELECT quantity, reserved FROM inventory WHERE product_id = ?',
                'params' => [$productId],
                'method' => 'queryOne',
            ],
            'reviews_summary' => [
                'sql' => 'SELECT AVG(rating) as avg_rating, COUNT(*) as review_count FROM reviews WHERE product_id = ?',
                'params' => [$productId],
                'method' => 'queryOne',
            ],
            'recent_reviews' => [
                'sql' => 'SELECT rating, comment, user_name, created_at FROM reviews WHERE product_id = ? ORDER BY created_at DESC LIMIT 5',
                'params' => [$productId],
            ],
            'related_products' => [
                'sql' => 'SELECT id, name, price, image FROM products WHERE category_id = (SELECT category_id FROM products WHERE id = ?) AND id != ? LIMIT 4',
                'params' => [$productId, $productId],
            ],
            'price_history' => [
                'sql' => 'SELECT price, created_at FROM price_history WHERE product_id = ? ORDER BY created_at DESC LIMIT 10',
                'params' => [$productId],
            ],
        ]);
    }

    /**
     * Example: Bulk user import
     */
    public function importUsers(array $userData): array
    {
        $columns = ['name', 'email', 'password_hash', 'created_at'];

        // Prepare data
        $rows = [];
        foreach ($userData as $user) {
            $rows[] = [
                $user['name'],
                $user['email'],
                password_hash($user['password'], PASSWORD_DEFAULT),
                date('Y-m-d H:i:s'),
            ];
        }

        // Insert in batches of 100
        return $this->db->batchInsert('users', $columns, $rows, 100);
    }

    /**
     * Example: Bulk order status updates
     */
    public function updateOrderStatuses(array $orderUpdates): array
    {
        // Each update: ['id' => 123, 'status' => 'shipped', 'shipped_at' => '2024-01-01']
        return $this->db->batchUpdate('orders', $orderUpdates, 'id', 25);
    }

    /**
     * Example: Analytics data collection
     */
    public function collectAnalyticsData(\DateTime $date): array
    {
        $dateStr = $date->format('Y-m-d');

        return $this->db->aggregate([
            'daily_users' => [
                'sql' => 'SELECT COUNT(DISTINCT user_id) FROM user_sessions WHERE DATE(created_at) = ?',
                'params' => [$dateStr],
                'method' => 'queryScalar',
            ],
            'daily_orders' => [
                'sql' => 'SELECT COUNT(*), SUM(total) as revenue FROM orders WHERE DATE(created_at) = ?',
                'params' => [$dateStr],
                'method' => 'queryOne',
            ],
            'popular_products' => [
                'sql' => 'SELECT p.name, COUNT(*) as sales FROM order_items oi JOIN products p ON oi.product_id = p.id JOIN orders o ON oi.order_id = o.id WHERE DATE(o.created_at) = ? GROUP BY p.id ORDER BY sales DESC LIMIT 10',
                'params' => [$dateStr],
            ],
            'top_customers' => [
                'sql' => 'SELECT u.name, u.email, SUM(o.total) as spent FROM users u JOIN orders o ON u.id = o.user_id WHERE DATE(o.created_at) = ? GROUP BY u.id ORDER BY spent DESC LIMIT 10',
                'params' => [$dateStr],
            ],
            'page_views' => [
                'sql' => 'SELECT page, COUNT(*) as views FROM page_views WHERE DATE(created_at) = ? GROUP BY page ORDER BY views DESC LIMIT 20',
                'params' => [$dateStr],
            ],
        ]);
    }

    /**
     * Example: Database health monitoring
     */
    public function monitorDatabaseHealth(): array
    {
        $tables = ['users', 'orders', 'products', 'order_items', 'reviews'];

        $tableStats = $this->db->getTableStats($tables);

        $systemStats = $this->db->aggregate([
            'active_connections' => [
                'sql' => 'SHOW STATUS LIKE "Threads_connected"',
                'method' => 'queryOne',
            ],
            'slow_queries' => [
                'sql' => 'SHOW STATUS LIKE "Slow_queries"',
                'method' => 'queryOne',
            ],
            'uptime' => [
                'sql' => 'SHOW STATUS LIKE "Uptime"',
                'method' => 'queryOne',
            ],
            'innodb_buffer_pool_usage' => [
                'sql' => 'SELECT (1 - (FREE_BUFFERS / TOTAL_BUFFERS)) * 100 as usage_percent FROM (SELECT VARIABLE_VALUE as FREE_BUFFERS FROM information_schema.GLOBAL_STATUS WHERE VARIABLE_NAME = "Innodb_buffer_pool_pages_free") f CROSS JOIN (SELECT VARIABLE_VALUE as TOTAL_BUFFERS FROM information_schema.GLOBAL_STATUS WHERE VARIABLE_NAME = "Innodb_buffer_pool_pages_total") t',
                'method' => 'queryScalar',
            ],
        ]);

        return [
            'table_stats' => $tableStats,
            'system_stats' => $systemStats,
            'timestamp' => time(),
        ];
    }

    /**
     * Example: User activity timeline
     */
    public function getUserActivityTimeline(int $userId, int $days = 30): array
    {
        $since = date('Y-m-d', strtotime("-$days days"));

        return $this->db->aggregate([
            'login_history' => [
                'sql' => 'SELECT DATE(created_at) as date, COUNT(*) as logins FROM user_sessions WHERE user_id = ? AND created_at >= ? GROUP BY DATE(created_at) ORDER BY date DESC',
                'params' => [$userId, $since],
            ],
            'order_history' => [
                'sql' => 'SELECT DATE(created_at) as date, COUNT(*) as orders, SUM(total) as spent FROM orders WHERE user_id = ? AND created_at >= ? GROUP BY DATE(created_at) ORDER BY date DESC',
                'params' => [$userId, $since],
            ],
            'page_views' => [
                'sql' => 'SELECT DATE(created_at) as date, COUNT(*) as views FROM page_views WHERE user_id = ? AND created_at >= ? GROUP BY DATE(created_at) ORDER BY date DESC',
                'params' => [$userId, $since],
            ],
            'support_tickets' => [
                'sql' => 'SELECT DATE(created_at) as date, COUNT(*) as tickets FROM support_tickets WHERE user_id = ? AND created_at >= ? GROUP BY DATE(created_at) ORDER BY date DESC',
                'params' => [$userId, $since],
            ],
        ]);
    }

    /**
     * Example: Inventory management with optimistic locking
     */
    public function reserveInventory(int $productId, int $quantity): bool
    {
        return $this->db->optimisticUpdate(
            'inventory',
            ['reserved' => $quantity],
            ['product_id' => $productId],
            'version',
            maxRetries: 5
        );
    }

    /**
     * Example: Complex reporting with timeout protection
     */
    public function generateSalesReport(\DateTime $startDate, \DateTime $endDate): array
    {
        return $this->db->transactionWithTimeout(function ($db) use ($startDate, $endDate) {
            $start = $startDate->format('Y-m-d');
            $end = $endDate->format('Y-m-d');

            return $db->aggregate([
                'summary' => [
                    'sql' => 'SELECT COUNT(*) as total_orders, SUM(total) as total_revenue, AVG(total) as avg_order_value FROM orders WHERE created_at BETWEEN ? AND ?',
                    'params' => [$start, $end],
                    'method' => 'queryOne',
                ],
                'by_day' => [
                    'sql' => 'SELECT DATE(created_at) as date, COUNT(*) as orders, SUM(total) as revenue FROM orders WHERE created_at BETWEEN ? AND ? GROUP BY DATE(created_at) ORDER BY date',
                    'params' => [$start, $end],
                ],
                'by_product' => [
                    'sql' => 'SELECT p.name, SUM(oi.quantity) as units_sold, SUM(oi.price * oi.quantity) as revenue FROM order_items oi JOIN products p ON oi.product_id = p.id JOIN orders o ON oi.order_id = o.id WHERE o.created_at BETWEEN ? AND ? GROUP BY p.id ORDER BY revenue DESC LIMIT 20',
                    'params' => [$start, $end],
                ],
                'by_customer' => [
                    'sql' => 'SELECT u.name, u.email, COUNT(o.id) as orders, SUM(o.total) as total_spent FROM users u JOIN orders o ON u.id = o.user_id WHERE o.created_at BETWEEN ? AND ? GROUP BY u.id ORDER BY total_spent DESC LIMIT 20',
                    'params' => [$start, $end],
                ],
            ]);
        }, Duration::fromMinutes(5));
    }

    /**
     * Example: Background data cleanup
     */
    public function cleanupOldData(): void
    {
        // Non-blocking cleanup operations
        $this->db->executeAsync('DELETE FROM user_sessions WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY)');
        $this->db->executeAsync('DELETE FROM page_views WHERE created_at < DATE_SUB(NOW(), INTERVAL 90 DAY)');
        $this->db->executeAsync('DELETE FROM audit_logs WHERE created_at < DATE_SUB(NOW(), INTERVAL 1 YEAR)');
        $this->db->executeAsync('DELETE FROM temporary_uploads WHERE created_at < DATE_SUB(NOW(), INTERVAL 1 DAY)');
    }

    /**
     * Example: Read-ahead caching for related data
     */
    public function preloadRelatedData(array $productIds): array
    {
        $queries = [];

        foreach ($productIds as $productId) {
            $queries["reviews_$productId"] = [
                'sql' => 'SELECT COUNT(*) as count, AVG(rating) as avg_rating FROM reviews WHERE product_id = ?',
                'params' => [$productId],
                'method' => 'queryOne',
            ];

            $queries["inventory_$productId"] = [
                'sql' => 'SELECT quantity FROM inventory WHERE product_id = ?',
                'params' => [$productId],
                'method' => 'queryScalar',
            ];
        }

        return $this->db->readAhead($queries, Duration::fromSeconds(5));
    }
}
