from __future__ import annotations

import pathlib

import _pytest.terminal
import pytest

_pytest.terminal._color_for_type['incompatible'] = 'red'
_pytest.terminal._color_for_type['passable'] = 'yellow'
_pytest.terminal._color_for_type['compatible'] = 'green'
_pytest.terminal._color_for_type['exact'] = 'green'


@pytest.hookimpl
def pytest_report_teststatus(report, config):
    """Customizes the reporting of test statuses."""
    if report.when != 'call':
        return None

    if isinstance(report, pytest.CollectReport) or report.outcome in ('skipped'):
        return None

    props = dict(report.user_properties)
    ahash = props.get('ahash:', -1)
    dhash = props.get('dhash:', -1)
    phash = props.get('phash:', -1)
    if ahash == dhash == phash == 0:
        if report.outcome == 'failed':
            return 'failed', 'E', ('EXACT', {'red': True})
        return 'exact', 'E', ('EXACT', {'green': True})
    if ahash >= 10 or dhash >= 10 or phash >= 10:
        return 'incompatible', 'I', ('INCOMPATIBLE', {'red': True})
    if 4 < ahash < 10 or 4 < dhash < 10 or 4 < phash < 10:
        return 'passable', 'P', ('PASSABLE', {'yellow': True})
    if ahash <= 4 or dhash <= 4 or phash <= 4:
        return 'compatible', 'C', ('COMPATIBLE', {'green': True})


def pytest_terminal_summary(terminalreporter, exitstatus, config):
    incompatible = terminalreporter._get_reports_to_display('incompatible')
    passable = terminalreporter._get_reports_to_display('passable')
    compatible = terminalreporter._get_reports_to_display('compatible')
    exact = terminalreporter._get_reports_to_display('exact')
    total = len(incompatible) + len(passable) + len(compatible) + len(exact)
    if total < 1:
        return
    incompatible_percent = int((len(incompatible)/total)*100)
    passable_percent = int((len(passable)/total)*100)
    compatible_percent = int((len(compatible)/total)*100)
    exact_percent = int((len(exact)/total)*100)
    final_percent = ((len(exact)+len(compatible))/total)*100

    parts = (
        (f'incompatible: {incompatible_percent:02d}%', {'red': True}),
        (f'passable: {passable_percent:02d}%', {'yellow': True}),
        (f'compatible: {compatible_percent:02d}%', {'green': True}),
        (f'exact: {exact_percent:02d}%', {'green': True}),
        (
            f'final: {final_percent:02.2f}%', {
                'green' if final_percent > 80 else 'red': True,
            },
        ),
    )
    line_parts = []
    for text, markup in parts:
        with_markup = terminalreporter._tw.markup(text, **markup)
        line_parts.append(with_markup)
    msg = ', '.join(line_parts)
    terminalreporter.write_line(msg)


def pytest_addoption(parser):
    parser.addoption(
        '--hasher', default='go run ./hashImage -file {}', help="The commandline image hasher to test ('go run ./hashImage -file {}')",
    )
    parser.addoption(
        '--image-dir', default='_examples/images', help='The file path to a directory of images to test',
    )
    parser.addoption(
        '--fail-skip', action='store_true', help="skip images that can't be decoded",
    )


def pytest_generate_tests(metafunc):
    if 'file' in metafunc.fixturenames:
        file = metafunc.config.getoption('--image-dir')
        files = []
        cwd = pathlib.Path('').absolute()
        for p in pathlib.Path(file).iterdir():
            if not p.is_file():
                continue
            p = p.absolute()
            if p.is_relative_to(cwd):
                files.append(str(p.relative_to(cwd)))
            else:
                files.append(str(p.absolute()))
        metafunc.parametrize('file', files)
