#  Copyright 2026 European Union
#  Author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu)
#  SPDX-License-Identifier: EUPL-1.2
"""Unit tests covering the DatabaseEditor widget."""

from __future__ import annotations

from typing import List

import pytest

pytest.importorskip('PySide6', reason='PySide6 is required for GUI tests')
from PySide6.QtWidgets import QApplication, QFileDialog

from mafw.steering_gui.views.database_editor import DatabaseEditor

pytestmark = pytest.mark.gui


@pytest.fixture(scope='session')
def qapp() -> QApplication:
    """Ensure a single QApplication instance exists for all GUI tests."""

    app = QApplication.instance()
    if app is None:
        app = QApplication([])
    return app


def test_set_data_does_not_emit_configuration_signal(qapp: QApplication) -> None:
    """set_data should populate the editor without triggering configuration_changed."""

    editor = DatabaseEditor()
    events: List[dict] = []
    editor.configuration_changed.connect(lambda config: events.append(config))

    editor.set_data(
        {
            'backend': 'mysql',
            'url': 'mysql://localhost',
            'user': 'tester',
            'read_default_file': '/tmp/.my.cnf',
            'pragmas': {'cache_size': -123},
        }
    )

    assert events == []


def test_configuration_changed_emitted_for_user_input(qapp: QApplication) -> None:
    """Changing a field should emit configuration_changed with the latest values."""

    editor = DatabaseEditor()
    events: List[dict] = []
    editor.configuration_changed.connect(lambda config: events.append(config))

    editor.user_edit.setText('science')
    assert events[-1]['user'] == 'science'

    editor.password_file_edit.setText('/tmp/my.cnf')
    assert events[-1]['read_default_file'] == '/tmp/my.cnf'


def test_backend_detects_scheme_from_url(qapp: QApplication) -> None:
    """Typing a URL should adjust the backend combo to match the detected scheme."""

    editor = DatabaseEditor()
    editor.url_edit.setText('postgresql://db.example.com:5432/analysis')
    assert editor.backend_combo.currentText() == 'postgresql'


def test_sqlite_browse_button_updates_url(qapp: QApplication, monkeypatch: pytest.MonkeyPatch) -> None:
    """The browse action should load an absolute path into the sqlite URL field."""

    editor = DatabaseEditor()

    monkeypatch.setattr(QFileDialog, 'getOpenFileName', lambda *args, **kwargs: ('/tmp/test.db', ''))
    editor.url_browse.click()

    assert editor.url_edit.text().startswith('sqlite:///')
    assert 'test.db' in editor.url_edit.text()


def test_mysql_password_file_browse_is_reflected(qapp: QApplication, monkeypatch: pytest.MonkeyPatch) -> None:
    """Selecting a mysql password file should populate the corresponding field."""

    editor = DatabaseEditor()
    editor.backend_combo.setCurrentText('mysql')

    monkeypatch.setattr(QFileDialog, 'getOpenFileName', lambda *args, **kwargs: ('/etc/.my.cnf', ''))
    editor.password_file_browse.click()

    assert editor.password_file_edit.text() == '/etc/.my.cnf'


def test_pragmas_round_trip_edit(qapp: QApplication) -> None:
    """Modifying a pragma cell should be observable in get_data."""

    editor = DatabaseEditor()
    assert 'journal_mode' in editor.get_data()['pragmas']

    model = editor.pragmas_table.model()
    key_item = model.item(0, 0)
    value_item = model.item(0, 1)
    key_item.setText('journal_mode')
    value_item.setText('minimal')

    assert editor.get_data()['pragmas']['journal_mode'] == 'minimal'


def test_test_connection_button_emits_request(qapp: QApplication) -> None:
    """Clicking the test connection button should emit the signal with current config."""

    editor = DatabaseEditor()
    received: List[dict] = []
    editor.test_connection_requested.connect(lambda data: received.append(data))

    editor.test_connection_button.click()

    assert received


def test_memory_button_sets_in_memory_url(qapp: QApplication) -> None:
    """The memory button should switch the SQLite URL to the in-memory scheme."""

    editor = DatabaseEditor()
    editor.url_edit.setText('sqlite:///tmp/db')
    editor.url_memory.click()
    assert editor.url_edit.text() == 'sqlite:///:memory:'

    editor.backend_combo.setCurrentText('mysql')
    assert not editor.url_memory.isEnabled()
