"""Unified database manager with MySQL primary target and SQLite fallback for testing."""

from __future__ import annotations

import contextlib
import sqlite3
from dataclasses import dataclass
from pathlib import Path
from typing import Any, Dict, Optional

try:
    import mysql.connector  # type: ignore
    from mysql.connector import pooling  # type: ignore
except ImportError:  # pragma: no cover - optional dependency
    mysql = None  # type: ignore
    pooling = None  # type: ignore


@dataclass
class _MySQLBackend:
    config: Dict[str, Any]

    def __post_init__(self) -> None:
        self.pool = pooling.MySQLConnectionPool(
            pool_name=self.config.get("pool_name", "web_sentinel_pool"),
            pool_size=self.config.get("pool_size", 10),
            host=self.config.get("host", "localhost"),
            user=self.config.get("user"),
            password=self.config.get("password"),
            database=self.config.get("database", "web_sentinel"),
            charset="utf8mb4",
            use_unicode=True,
            autocommit=True,
        )
        self.paramstyle = "format"

    def get_connection(self):
        return self.pool.get_connection()

    def close(self) -> None:
        with contextlib.suppress(Exception):
            self.pool.close()


@dataclass
class _SQLiteBackend:
    config: Dict[str, Any]

    def __post_init__(self) -> None:
        path = self.config.get("database", ":memory:")
        self.path = Path(path) if path != ":memory:" else path
        if isinstance(self.path, Path):
            self.path.parent.mkdir(parents=True, exist_ok=True)
        self.paramstyle = "qmark"

    def get_connection(self):
        conn = sqlite3.connect(self.path)
        conn.row_factory = sqlite3.Row
        return conn

    def close(self) -> None:
        return


class MySQLManager:
    """Factory that provides MySQL connections or SQLite fallback."""

    def __init__(self, config: Optional[Dict[str, Any]] = None):
        config = config or {}
        driver = config.get("driver")
        if driver == "sqlite" or pooling is None:
            self.backend = _SQLiteBackend(config)
        else:
            self.backend = _MySQLBackend(config)
        self.paramstyle = getattr(self.backend, "paramstyle", "format")

    def get_connection(self):
        return self.backend.get_connection()

    def close(self) -> None:
        self.backend.close()
