<?php

declare(strict_types=1);

namespace App\Framework\Exception;

final class DatabaseException extends FrameworkException
{
    public static function connectionFailed(string $dsn, \Throwable $previous): self
    {
        $context = ExceptionContext::forOperation('database.connect', 'PDO')
            ->withData([
                'dsn' => self::sanitizeDsn($dsn),
                'driver' => explode(':', $dsn)[0] ?? 'unknown'
            ]);

        return new self('Database connection failed', 0, $previous, $context);
    }

    public static function queryFailed(string $query, array $params, \Throwable $previous): self
    {
        $context = ExceptionContext::forOperation('database.query', 'PDO')
            ->withData([
                'query' => $query,
                'parameters' => $params,
                'query_type' => self::detectQueryType($query)
            ]);

        return new self('Database query failed', 0, $previous, $context);
    }

    public static function transactionFailed(string $operation, \Throwable $previous): self
    {
        $context = ExceptionContext::forOperation('database.transaction', 'PDO')
            ->withData([
                'transaction_operation' => $operation
            ]);

        return new self("Database transaction failed: {$operation}", 0, $previous, $context);
    }

    private static function sanitizeDsn(string $dsn): string
    {
        return preg_replace('/password=[^;]+/', 'password=[REDACTED]', $dsn);
    }

    private static function detectQueryType(string $query): string
    {
        $query = trim(strtoupper($query));
        return match (true) {
            str_starts_with($query, 'SELECT') => 'SELECT',
            str_starts_with($query, 'INSERT') => 'INSERT',
            str_starts_with($query, 'UPDATE') => 'UPDATE',
            str_starts_with($query, 'DELETE') => 'DELETE',
            str_starts_with($query, 'CREATE') => 'CREATE',
            str_starts_with($query, 'DROP') => 'DROP',
            str_starts_with($query, 'ALTER') => 'ALTER',
            default => 'UNKNOWN'
        };
    }
}
