import platform
from pathlib import Path
from typing import List, Union

from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import (
    QHBoxLayout,
    QLabel,
    QPushButton,
    QScrollArea,
    QVBoxLayout,
    QWidget,
)

from app.data_structures.processing import (
    DetectionResult,
    UnprocessedVideoResult,
    VideoProcessingResult,
)
from app.utils.subprocessing import subprocess_call, subprocess_call_windows

from .base import DialogWindow


class ResultsWindow(DialogWindow):
    """
    Window for displaying results of video processing.
    """

    def __init__(
        self,
        results: List[Union[VideoProcessingResult, UnprocessedVideoResult]],
        results_path: Path,
        object_detection_enabled: bool,
    ) -> None:
        super().__init__((600, 450), title="Výsledky")
        self.video_results = results
        self.results_path = results_path
        self.object_detection_enabled = object_detection_enabled
        self._add_results_list_area()
        self._add_results()
        self._add_results_path()
        self._add_bottom_buttons()

    def _add_results_list_area(self) -> None:
        scrollable_area = QScrollArea()
        scrollable_area.setWidgetResizable(True)
        results_list_widget = QWidget()
        self.results_list_layout = QVBoxLayout(results_list_widget)
        self.results_list_layout.setSpacing(10)
        scrollable_area.setWidget(results_list_widget)
        self.general_layout.addWidget(scrollable_area)

    def _add_results(self) -> None:
        for video_result in self.video_results:
            if video_result.ok is False:
                self._add_error_result(video_result)
                continue
            self._add_successful_result(video_result)

    def _add_successful_result(self, video_result: VideoProcessingResult) -> None:
        detection_results = video_result.detection_results
        movements_number = len(detection_results)
        movements_number_repr = (
            f"{movements_number} {generate_movements_word(movements_number)}"
        )
        detected_objects_repr = "<br>".join(
            self._format_result(detection_result)
            for detection_result in detection_results
        )
        results_text = (
            f'<span style="font-weight: 600">{video_result.video_path.name}</span> '
            f"<span>({movements_number_repr})</span><br>"
            f"<span>{detected_objects_repr}</span>"
        )
        self.results_list_layout.addWidget(
            QLabel(results_text), alignment=Qt.AlignmentFlag.AlignTop
        )

    def _add_error_result(self, video_result: UnprocessedVideoResult) -> None:
        self.results_list_layout.addWidget(
            QLabel(
                f'<span style="font-weight: 600">{video_result.video_path.name}</span> '
                f"<span>(chyba)</span><br>"
                f"<span>{video_result.error_message}</span>"
            ),
            alignment=Qt.AlignmentFlag.AlignTop,
        )

    def _format_result(self, result: DetectionResult) -> str:
        text = str(result.interval)
        if not self.object_detection_enabled:
            return text
        if not result.objects:
            return text + ": nerozpoznano"
        return text + f": {', '.join(str(obj) for obj in result.objects)}"

    def _add_results_path(self) -> None:
        widget = QWidget()
        layout = QHBoxLayout(widget)
        results_path_repr = f"Výsledky uloženy do složky:\n{self.results_path}"
        results_path_text = QLabel(results_path_repr)
        results_path_text.setTextInteractionFlags(
            Qt.TextInteractionFlag.TextSelectableByMouse
        )
        results_path_text.setWordWrap(True)
        layout.addWidget(results_path_text)
        self.general_layout.addWidget(widget)

    def _add_bottom_buttons(self) -> None:
        control_widget = QWidget()
        layout = QHBoxLayout(control_widget)
        layout.setAlignment(Qt.AlignmentFlag.AlignRight)
        self.close_btn = QPushButton("Zavřít")
        self.close_btn.clicked.connect(self.close)
        self.results_btn = QPushButton("Otevřít výsledky")
        self.results_btn.clicked.connect(self._open_results)
        layout.addWidget(self.results_btn)
        layout.addWidget(self.close_btn)
        self.general_layout.addWidget(control_widget)

    def _open_results(self) -> None:
        target_platform = platform.system()
        folder_path = self.results_path.as_posix()
        if target_platform == "Windows":
            subprocess_call_windows(f"start {folder_path}")
        elif target_platform == "Darwin":
            subprocess_call(["open", folder_path])
        elif target_platform == "Linux":
            subprocess_call(["xdg-open", folder_path])
        else:
            raise NotImplementedError(
                f"Opening results is not implemented for {target_platform}."
            )


def generate_movements_word(count: int) -> str:
    if count == 1:
        return "pohyb"
    elif 2 <= count <= 4:
        return "pohyby"
    else:
        return "pohybů"
