"""
Create Task Dialog
"""

from __future__ import annotations

from typing import Any, Dict, List, Optional

from ..models import EngineType
from ..qt_compat import (
    QCheckBox,
    QComboBox,
    QDialog,
    QFormLayout,
    QHBoxLayout,
    QLabel,
    QLineEdit,
    QMessageBox,
    QPushButton,
    QStackedWidget,
    QTextEdit,
    QVBoxLayout,
    QWidget,
)
from ..qt_compat import Qt, exec_dialog
from .engine_selection import get_simple_engine_choices, engine_description_for_value
from ..translator import tr, add_listener, remove_listener


class CreateTaskDialog(QDialog):
    """Select whether a new task is a simple engine run or a workflow task."""

    SIMPLE_TASK = "simple"
    WORKFLOW_TASK = "workflow"

    def __init__(
        self,
        *,
        workflow_definitions: List[Dict[str, Any]],
        parent=None,
    ) -> None:
        super().__init__(parent)
        self.workflow_definitions = list(workflow_definitions or [])
        self._updating_ui = False
        self.setWindowTitle(tr("create_task.window_title"))
        self.resize(680, 520)
        self._init_ui()
        self._refresh_mode()
        self.retranslateUi()
        add_listener(self.retranslateUi)

    def _init_ui(self) -> None:
        layout = QVBoxLayout()
        self.setLayout(layout)

        self.instructions_label = QLabel(tr("create_task.instructions"))
        self.instructions_label.setWordWrap(True)
        layout.addWidget(self.instructions_label)

        form = QFormLayout()
        layout.addLayout(form)
        self._top_form = form

        self.task_type_combo = QComboBox()
        self.task_type_combo.addItem(tr("create_task.task_type_simple"), self.SIMPLE_TASK)
        self.task_type_combo.addItem(tr("create_task.task_type_workflow"), self.WORKFLOW_TASK)
        self.task_type_combo.currentIndexChanged.connect(self._refresh_mode)
        self.row_task_type_label = QLabel(tr("create_task.row_task_type"))
        form.addRow(self.row_task_type_label, self.task_type_combo)

        self.mode_stack = QStackedWidget(self)
        self.row_configuration_label = QLabel(tr("create_task.row_configuration"))
        form.addRow(self.row_configuration_label, self.mode_stack)

        self._build_simple_task_page()
        self._build_workflow_task_page()

        button_row = QHBoxLayout()
        button_row.addStretch()
        self.cancel_button = QPushButton(tr("create_task.btn_cancel"))
        self.cancel_button.clicked.connect(self.reject)
        button_row.addWidget(self.cancel_button)
        self.ok_button = QPushButton(tr("create_task.btn_ok"))
        self.ok_button.clicked.connect(self.accept)
        button_row.addWidget(self.ok_button)
        layout.addLayout(button_row)

    def _build_simple_task_page(self) -> None:
        page = QWidget(self)
        form = QFormLayout()
        page.setLayout(form)
        self._simple_form = form

        self.simple_engine_combo = QComboBox()
        for label, engine_type, description in get_simple_engine_choices():
            self.simple_engine_combo.addItem(label, engine_type.value)
            self.simple_engine_combo.setItemData(
                self.simple_engine_combo.count() - 1,
                description,
                Qt.ItemDataRole.ToolTipRole,
            )
        self.simple_engine_combo.currentIndexChanged.connect(self._refresh_simple_engine_description)
        self.simple_row_engine_label = QLabel(tr("create_task.row_engine"))
        form.addRow(self.simple_row_engine_label, self.simple_engine_combo)

        self.simple_description_label = QLabel(tr("create_task.simple_description"))
        self.simple_description_label.setWordWrap(True)
        form.addRow("", self.simple_description_label)

        self.simple_engine_description = QLabel("")
        self.simple_engine_description.setWordWrap(True)
        self.simple_row_engine_details_label = QLabel(tr("create_task.row_engine_details"))
        form.addRow(self.simple_row_engine_details_label, self.simple_engine_description)
        self._refresh_simple_engine_description()

        self.mode_stack.addWidget(page)

    def _build_workflow_task_page(self) -> None:
        page = QWidget(self)
        form = QFormLayout()
        page.setLayout(form)
        self._workflow_form = form

        self.workflow_task_name_input = QLineEdit()
        self.workflow_row_task_name_label = QLabel(tr("create_task.row_task_name"))
        form.addRow(self.workflow_row_task_name_label, self.workflow_task_name_input)

        self.workflow_definition_combo = QComboBox()
        self.workflow_definition_combo.addItem(tr("create_task.pipeline_default_choice"), "")
        for definition in self.workflow_definitions:
            self.workflow_definition_combo.addItem(
                str(definition.get("name") or tr("create_task.pipeline_unnamed")),
                str(definition.get("id") or ""),
            )
        self.workflow_definition_combo.currentIndexChanged.connect(self._on_workflow_definition_changed)
        self.workflow_row_pipeline_label = QLabel(tr("create_task.row_pipeline"))
        form.addRow(self.workflow_row_pipeline_label, self.workflow_definition_combo)

        self.inherited_label = QLabel(tr("create_task.inherited_inputs_body"))
        self.inherited_label.setWordWrap(True)
        self.workflow_row_inherited_label = QLabel(tr("create_task.row_inherited_inputs"))
        form.addRow(self.workflow_row_inherited_label, self.inherited_label)

        self.binding_help_label = QLabel(tr("create_task.binding_help"))
        self.binding_help_label.setWordWrap(True)
        form.addRow("", self.binding_help_label)

        self.workflow_bindings_input = QTextEdit()
        self.workflow_bindings_input.setMinimumHeight(140)
        self.workflow_row_additional_label = QLabel(tr("create_task.row_additional_inputs"))
        form.addRow(self.workflow_row_additional_label, self.workflow_bindings_input)

        self.workflow_run_immediately_checkbox = QCheckBox(tr("create_task.run_immediately"))
        form.addRow("", self.workflow_run_immediately_checkbox)

        self.workflow_definition_summary = QLabel("")
        self.workflow_definition_summary.setWordWrap(True)
        self.workflow_row_summary_label = QLabel(tr("create_task.row_pipeline_summary"))
        form.addRow(self.workflow_row_summary_label, self.workflow_definition_summary)

        self.mode_stack.addWidget(page)

    def retranslateUi(self) -> None:
        self.setWindowTitle(tr("create_task.window_title"))
        if hasattr(self, "instructions_label"):
            self.instructions_label.setText(tr("create_task.instructions"))
        if hasattr(self, "row_task_type_label"):
            self.row_task_type_label.setText(tr("create_task.row_task_type"))
        if hasattr(self, "row_configuration_label"):
            self.row_configuration_label.setText(tr("create_task.row_configuration"))
        if hasattr(self, "task_type_combo"):
            current = self.task_type_combo.currentData()
            self.task_type_combo.blockSignals(True)
            self.task_type_combo.clear()
            self.task_type_combo.addItem(tr("create_task.task_type_simple"), self.SIMPLE_TASK)
            self.task_type_combo.addItem(tr("create_task.task_type_workflow"), self.WORKFLOW_TASK)
            idx = self.task_type_combo.findData(current)
            if idx >= 0:
                self.task_type_combo.setCurrentIndex(idx)
            self.task_type_combo.blockSignals(False)
        if hasattr(self, "cancel_button"):
            self.cancel_button.setText(tr("create_task.btn_cancel"))
        if hasattr(self, "ok_button"):
            self.ok_button.setText(tr("create_task.btn_ok"))
        # Simple page
        if hasattr(self, "simple_row_engine_label"):
            self.simple_row_engine_label.setText(tr("create_task.row_engine"))
        if hasattr(self, "simple_description_label"):
            self.simple_description_label.setText(tr("create_task.simple_description"))
        if hasattr(self, "simple_row_engine_details_label"):
            self.simple_row_engine_details_label.setText(tr("create_task.row_engine_details"))
        if hasattr(self, "simple_engine_combo"):
            current_engine = str(self.simple_engine_combo.currentData() or "")
            self.simple_engine_combo.blockSignals(True)
            self.simple_engine_combo.clear()
            for label, engine_type, description in get_simple_engine_choices():
                self.simple_engine_combo.addItem(label, engine_type.value)
                self.simple_engine_combo.setItemData(
                    self.simple_engine_combo.count() - 1,
                    description,
                    Qt.ItemDataRole.ToolTipRole,
                )
                if engine_type.value == current_engine:
                    self.simple_engine_combo.setCurrentIndex(self.simple_engine_combo.count() - 1)
            self.simple_engine_combo.blockSignals(False)
            self._refresh_simple_engine_description()
        # Workflow page
        if hasattr(self, "workflow_row_task_name_label"):
            self.workflow_row_task_name_label.setText(tr("create_task.row_task_name"))
        if hasattr(self, "workflow_row_pipeline_label"):
            self.workflow_row_pipeline_label.setText(tr("create_task.row_pipeline"))
        if hasattr(self, "inherited_label"):
            self.inherited_label.setText(tr("create_task.inherited_inputs_body"))
        if hasattr(self, "workflow_row_inherited_label"):
            self.workflow_row_inherited_label.setText(tr("create_task.row_inherited_inputs"))
        if hasattr(self, "binding_help_label"):
            self.binding_help_label.setText(tr("create_task.binding_help"))
        if hasattr(self, "workflow_row_additional_label"):
            self.workflow_row_additional_label.setText(tr("create_task.row_additional_inputs"))
        if hasattr(self, "workflow_run_immediately_checkbox"):
            self.workflow_run_immediately_checkbox.setText(tr("create_task.run_immediately"))
        if hasattr(self, "workflow_row_summary_label"):
            self.workflow_row_summary_label.setText(tr("create_task.row_pipeline_summary"))
        # Workflow combo: only update the first sentinel item; user-driven entries
        # are workflow names and should NOT be translated.
        if hasattr(self, "workflow_definition_combo") and self.workflow_definition_combo.count() > 0:
            self.workflow_definition_combo.setItemText(0, tr("create_task.pipeline_default_choice"))

    def closeEvent(self, event):
        remove_listener(self.retranslateUi)
        super().closeEvent(event)

    def _refresh_mode(self, *_args) -> None:
        task_type = self.current_task_type()
        page_index = 0 if task_type == self.SIMPLE_TASK else 1
        self.mode_stack.setCurrentIndex(page_index)

    def _refresh_simple_engine_description(self, *_args) -> None:
        engine_value = str(self.simple_engine_combo.currentData() or "").strip()
        self.simple_engine_description.setText(engine_description_for_value(engine_value))

    def current_task_type(self) -> str:
        return str(self.task_type_combo.currentData() or self.SIMPLE_TASK)

    def _on_workflow_definition_changed(self, *_args) -> None:
        workflow_id = str(self.workflow_definition_combo.currentData() or "").strip()
        definition = next(
            (item for item in self.workflow_definitions if str(item.get("id") or "").strip() == workflow_id),
            None,
        )
        if definition is None:
            self.workflow_definition_summary.setText("")
            return

        summary_lines = [
            definition.get("description", "").strip() or tr("create_task.summary_no_description"),
        ]
        if definition.get("step_count") is not None:
            summary_lines.append(tr("create_task.summary_steps", count=definition.get("step_count")))
        self.workflow_definition_summary.setText("\n".join(summary_lines))

        if not self.workflow_task_name_input.text().strip():
            self.workflow_task_name_input.setText(str(definition.get("name") or "").strip())

    def _parse_bindings(self) -> Optional[Dict[str, str]]:
        bindings: Dict[str, str] = {}
        raw_text = self.workflow_bindings_input.toPlainText().strip()
        if not raw_text:
            return bindings

        for line_number, raw_line in enumerate(raw_text.splitlines(), start=1):
            line = raw_line.strip()
            if not line:
                continue
            if "=" not in line:
                QMessageBox.warning(
                    self,
                    tr("create_task.warn_pipeline_title"),
                    tr("create_task.warn_binding_format", line=line_number),
                )
                return None
            name, value = line.split("=", 1)
            name = name.strip()
            value = value.strip()
            if not name:
                QMessageBox.warning(
                    self,
                    tr("create_task.warn_pipeline_title"),
                    tr("create_task.warn_binding_missing_name", line=line_number),
                )
                return None
            bindings[name] = value
        return bindings

    def get_task_request(self) -> Optional[Dict[str, Any]]:
        if exec_dialog(self) != QDialog.DialogCode.Accepted:
            return None

        task_type = self.current_task_type()
        if task_type == self.SIMPLE_TASK:
            engine_value = str(self.simple_engine_combo.currentData() or "").strip()
            engine_lookup = {
                EngineType.NETWEAVER.value: EngineType.NETWEAVER,
                EngineType.CDP.value: EngineType.CDP,
                EngineType.TEMPLATE_2.value: EngineType.TEMPLATE_2,
            }
            engine_type = engine_lookup.get(engine_value)
            if engine_type is None:
                QMessageBox.warning(self, tr("create_task.window_title"), tr("create_task.warn_no_engine"))
                return self.get_task_request()
            return {
                "task_type": self.SIMPLE_TASK,
                "engine_type": engine_type,
            }

        workflow_definition_id = str(self.workflow_definition_combo.currentData() or "").strip()
        if not workflow_definition_id:
            QMessageBox.warning(self, tr("create_task.warn_pipeline_title"), tr("create_task.warn_no_pipeline"))
            return self.get_task_request()

        task_name = self.workflow_task_name_input.text().strip()
        if not task_name:
            QMessageBox.warning(self, tr("create_task.warn_pipeline_title"), tr("create_task.warn_no_task_name"))
            return self.get_task_request()

        bindings = self._parse_bindings()
        if bindings is None:
            return self.get_task_request()

        definition = next(
            (
                item for item in self.workflow_definitions
                if str(item.get("id") or "").strip() == workflow_definition_id
            ),
            None,
        )

        return {
            "task_type": self.WORKFLOW_TASK,
            "engine_type": EngineType.WORKFLOW,
            "task_name": task_name,
            "workflow_definition_id": workflow_definition_id,
            "workflow_definition_name": str((definition or {}).get("name") or task_name),
            "workflow_bindings": bindings,
            "run_immediately": bool(self.workflow_run_immediately_checkbox.isChecked()),
        }
