"""Pytest configuration and shared fixtures."""

from datetime import datetime, timezone

import pytest

from wled_controller.config import Config, StorageConfig, ServerConfig, AuthConfig
from wled_controller.storage.database import Database
from wled_controller.storage.device_store import Device, DeviceStore
from wled_controller.storage.sync_clock import SyncClock
from wled_controller.storage.sync_clock_store import SyncClockStore
from wled_controller.storage.output_target_store import OutputTargetStore
from wled_controller.storage.automation import (
    Automation,
)
from wled_controller.storage.automation_store import AutomationStore
from wled_controller.storage.value_source_store import ValueSourceStore


# ---------------------------------------------------------------------------
# Directory / path fixtures
# ---------------------------------------------------------------------------


@pytest.fixture
def test_data_dir(tmp_path):
    """Provide a temporary directory for test data."""
    d = tmp_path / "data"
    d.mkdir(parents=True, exist_ok=True)
    return d


@pytest.fixture
def test_config_dir(tmp_path):
    """Provide a temporary directory for test configuration."""
    return tmp_path / "config"


@pytest.fixture
def temp_store_dir(tmp_path):
    """Provide a temp directory for store files, cleaned up after tests."""
    d = tmp_path / "stores"
    d.mkdir(parents=True, exist_ok=True)
    return d


# ---------------------------------------------------------------------------
# Database fixture
# ---------------------------------------------------------------------------


@pytest.fixture
def tmp_db(tmp_path):
    """Provide a temporary SQLite Database instance."""
    db = Database(tmp_path / "test.db")
    yield db
    db.close()


# ---------------------------------------------------------------------------
# Config fixtures
# ---------------------------------------------------------------------------


@pytest.fixture
def test_config(tmp_path):
    """A Config instance with temp directories for all store files."""
    data_dir = tmp_path / "data"
    data_dir.mkdir(parents=True, exist_ok=True)

    storage = StorageConfig(
        database_file=str(data_dir / "test.db"),
    )

    return Config(
        server=ServerConfig(host="127.0.0.1", port=9999),
        auth=AuthConfig(api_keys={"test": "test-api-key-12345"}),
        storage=storage,
    )


# ---------------------------------------------------------------------------
# Store fixtures
# ---------------------------------------------------------------------------


@pytest.fixture
def device_store(tmp_db):
    """Provide a DeviceStore backed by a temp database."""
    return DeviceStore(tmp_db)


@pytest.fixture
def sync_clock_store(tmp_db):
    """Provide a SyncClockStore backed by a temp database."""
    return SyncClockStore(tmp_db)


@pytest.fixture
def output_target_store(tmp_db):
    """Provide an OutputTargetStore backed by a temp database."""
    return OutputTargetStore(tmp_db)


@pytest.fixture
def automation_store(tmp_db):
    """Provide an AutomationStore backed by a temp database."""
    return AutomationStore(tmp_db)


@pytest.fixture
def value_source_store(tmp_db):
    """Provide a ValueSourceStore backed by a temp database."""
    return ValueSourceStore(tmp_db)


# ---------------------------------------------------------------------------
# Sample entity factories
# ---------------------------------------------------------------------------


@pytest.fixture
def sample_device():
    """Provide a sample device configuration dict."""
    return {
        "id": "test_device_001",
        "name": "Test WLED Device",
        "url": "http://192.168.1.100",
        "led_count": 150,
        "enabled": True,
        "device_type": "wled",
    }


@pytest.fixture
def make_device():
    """Factory fixture: call make_device(name=..., **overrides) to build a Device."""
    _counter = 0

    def _factory(name=None, **kwargs):
        nonlocal _counter
        _counter += 1
        defaults = dict(
            device_id=f"device_test_{_counter:04d}",
            name=name or f"Device {_counter}",
            url=f"http://192.168.1.{_counter}",
            led_count=150,
        )
        defaults.update(kwargs)
        return Device(**defaults)

    return _factory


@pytest.fixture
def make_sync_clock():
    """Factory fixture: call make_sync_clock(name=..., **overrides)."""
    _counter = 0

    def _factory(name=None, **kwargs):
        nonlocal _counter
        _counter += 1
        now = datetime.now(timezone.utc)
        defaults = dict(
            id=f"sc_test_{_counter:04d}",
            name=name or f"Clock {_counter}",
            speed=1.0,
            created_at=now,
            updated_at=now,
        )
        defaults.update(kwargs)
        return SyncClock(**defaults)

    return _factory


@pytest.fixture
def make_automation():
    """Factory fixture: call make_automation(name=..., **overrides)."""
    _counter = 0

    def _factory(name=None, **kwargs):
        nonlocal _counter
        _counter += 1
        now = datetime.now(timezone.utc)
        defaults = dict(
            id=f"auto_test_{_counter:04d}",
            name=name or f"Automation {_counter}",
            enabled=True,
            condition_logic="or",
            conditions=[],
            scene_preset_id=None,
            deactivation_mode="none",
            deactivation_scene_preset_id=None,
            created_at=now,
            updated_at=now,
        )
        defaults.update(kwargs)
        return Automation(**defaults)

    return _factory


# ---------------------------------------------------------------------------
# Authenticated test client
# ---------------------------------------------------------------------------


@pytest.fixture
def authenticated_client(test_config, monkeypatch):
    """Provide a FastAPI TestClient with auth header pre-set.

    Patches global config so the app uses temp storage paths.
    """
    import wled_controller.config as config_mod
    monkeypatch.setattr(config_mod, "config", test_config)

    from fastapi.testclient import TestClient
    from wled_controller.main import app

    client = TestClient(app, raise_server_exceptions=False)
    client.headers["Authorization"] = "Bearer test-api-key-12345"
    return client


# ---------------------------------------------------------------------------
# Calibration sample (kept from original conftest)
# ---------------------------------------------------------------------------


@pytest.fixture
def sample_calibration():
    """Provide a sample calibration configuration."""
    return {
        "layout": "clockwise",
        "start_position": "bottom_left",
        "segments": [
            {"edge": "bottom", "led_start": 0, "led_count": 40, "reverse": False},
            {"edge": "right", "led_start": 40, "led_count": 30, "reverse": False},
            {"edge": "top", "led_start": 70, "led_count": 40, "reverse": True},
            {"edge": "left", "led_start": 110, "led_count": 40, "reverse": True},
        ],
    }
