#!/usr/bin/env python
# Copyright (c) 2019-2022, wradlib developers.
# Copyright (c) 2022-2024, openradar developers.
# Distributed under the MIT License. See LICENSE.txt for more info.
# Borrowed from xradar

import os
import sys

import nbformat
import pytest
from nbconvert.preprocessors import ExecutePreprocessor
from nbconvert.preprocessors.execute import CellExecutionError
from packaging.version import Version


def pytest_collect_file(parent, file_path):
    if file_path.suffix == ".ipynb":
        return NotebookFile.from_parent(parent, path=file_path)


class NotebookFile(pytest.File):
    if Version(pytest.__version__) < Version("5.4.0"):

        @classmethod
        def from_parent(cls, parent, path):
            return cls(parent=parent, path=path)

    def collect(self):
        for f in [self.path]:
            yield NotebookItem.from_parent(self, name=os.path.basename(f))

    def setup(self):
        kernel = "python%d" % sys.version_info[0]
        self.exproc = ExecutePreprocessor(kernel_name=kernel, timeout=600)


class NotebookItem(pytest.Item):
    def __init__(self, name, parent):
        super().__init__(name, parent)

    if Version(pytest.__version__) < Version("5.4.0"):

        @classmethod
        def from_parent(cls, parent, name):
            return cls(parent=parent, name=name)

    def runtest(self):
        # use current path to get coverage working
        cur_dir = os.getcwd()

        # See https://bugs.python.org/issue37373
        if (
            sys.version_info[0] == 3
            and sys.version_info[1] >= 8
            and sys.platform.startswith("win")
        ):
            import asyncio

            asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

        with self.path.open() as f:
            nb = nbformat.read(f, as_version=4)
            try:
                self.parent.exproc.preprocess(nb, {"metadata": {"path": cur_dir}})
            except CellExecutionError as e:
                raise NotebookException(e)

        with open(self.path, "w", encoding="utf-8") as f:
            nbformat.write(nb, f)

    def repr_failure(self, excinfo):
        if isinstance(excinfo.value, NotebookException):
            return excinfo.exconly()

        return super().repr_failure(excinfo)

    def reportinfo(self):
        return self.path, 0, f"TestCase: {self.name}"


class NotebookException(Exception):
    pass
