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

:Author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu)
:Description: Verify that ProcessorFilterEditor lists models, marks recommended
              entries, and emits the correct action signals.
"""

from __future__ import annotations

from unittest.mock import patch

import pytest

pytest.importorskip('PySide6', reason='PySide6 is required for GUI tests')
from peewee import AutoField
from PySide6.QtCore import Qt
from PySide6.QtWidgets import QApplication

from mafw.db.db_model import MAFwBaseModel, mafw_model_register
from mafw.steering.models import ModelFilterConfig, ProcessorConfig
from mafw.steering_gui.views.filter_editors import ProcessorFilterEditor

pytestmark = pytest.mark.gui


class ProcModelA(MAFwBaseModel):
    """Dummy model A for processor editor tests."""

    id = AutoField(primary_key=True)


class ProcModelB(MAFwBaseModel):
    """Dummy model B for processor editor tests."""

    id = AutoField(primary_key=True)


class ProcModelC(MAFwBaseModel):
    """Dummy model C for processor editor tests."""

    id = AutoField(primary_key=True)


@pytest.fixture(scope='session')
def qapp() -> QApplication:
    app = QApplication.instance()
    if app is None:
        app = QApplication([])
    return app


def test_processor_filter_editor_table(qapp: QApplication) -> None:
    mafw_model_register.register_model('model_a', ProcModelA)
    mafw_model_register.register_model('model_b', ProcModelB)
    mafw_model_register.register_model('model_c', ProcModelC)

    config = ProcessorConfig(name='Proc')
    config.schema_filter_models = [ProcModelB.__name__]
    config.filters[ProcModelC.__name__] = [ModelFilterConfig(name=ProcModelC.__name__, model=ProcModelC.__name__)]

    editor = ProcessorFilterEditor()
    editor.set_config(config)

    table_model = editor._models_table.model()
    all_models = mafw_model_register.get_model_names()
    advertised = [ProcModelB.__name__]
    others = sorted([name for name in all_models if name not in advertised])
    expected = advertised + others

    assert table_model.rowCount() == len(expected)

    # Advertised first, remaining sorted
    assert table_model.data(table_model.index(0, 0)) == expected[0]

    row_b = expected.index(ProcModelB.__name__)
    row_a = expected.index(ProcModelA.__name__)
    row_c = expected.index(ProcModelC.__name__)

    assert table_model.data(table_model.index(row_b, 1), role=Qt.ItemDataRole.CheckStateRole) == Qt.CheckState.Checked
    assert table_model.data(table_model.index(row_a, 1), role=Qt.ItemDataRole.CheckStateRole) == Qt.CheckState.Unchecked

    font = table_model.data(table_model.index(row_c, 0), role=Qt.ItemDataRole.FontRole)
    assert font is not None and font.bold() is True


def test_processor_filter_editor_double_click_signals(qapp: QApplication) -> None:
    mafw_model_register.register_model('model_a', ProcModelA)
    mafw_model_register.register_model('model_b', ProcModelB)
    mafw_model_register.register_model('model_c', ProcModelC)

    config = ProcessorConfig(name='Proc')
    config.schema_filter_models = [ProcModelB.__name__]
    config.filters[ProcModelC.__name__] = [ModelFilterConfig(name=ProcModelC.__name__, model=ProcModelC.__name__)]

    editor = ProcessorFilterEditor()
    editor.set_config(config)

    received = {'add': None, 'edit': None}
    editor.add_model_filter_requested.connect(lambda name: received.update({'add': name}))
    editor.edit_model_filter_requested.connect(lambda name: received.update({'edit': name}))

    table_model = editor._models_table.model()
    all_models = mafw_model_register.get_model_names()
    advertised = [ProcModelB.__name__]
    others = sorted([name for name in all_models if name not in advertised])
    expected = advertised + others

    row_a = expected.index(ProcModelA.__name__)
    row_c = expected.index(ProcModelC.__name__)

    editor._on_table_double_clicked(table_model.index(row_a, 0))
    assert received['add'] == ProcModelA.__name__

    editor._on_table_double_clicked(table_model.index(row_c, 0))
    assert received['edit'] == ProcModelC.__name__


def test_processor_filter_editor_add_dialog(qapp: QApplication) -> None:
    mafw_model_register.register_model('model_a', ProcModelA)
    mafw_model_register.register_model('model_b', ProcModelB)

    config = ProcessorConfig(name='Proc')
    config.schema_filter_models = [ProcModelB.__name__]

    editor = ProcessorFilterEditor()
    editor.set_config(config)

    received = []
    editor.add_model_filter_requested.connect(received.append)

    from PySide6.QtWidgets import QDialog

    with patch('mafw.steering_gui.views.filter_editors.AddModelDialog') as dialog_cls:
        dialog = dialog_cls.return_value
        dialog.exec.return_value = QDialog.DialogCode.Accepted
        dialog.selected_model.return_value = ProcModelA.__name__

        editor._add_model_btn.click()

    assert received == [ProcModelA.__name__]
