#!/usr/bin/python3
"""Tests for sbo_create.models dataclasses and label helpers."""

import sys
from unittest.mock import patch

import pytest

from sbo_create.models import AppContext, InfoData, MaintainerData, set_arm_labels, set_x86_labels, set_color, colorize, confirm, _Color


# ---------------------------------------------------------------------------
# InfoData defaults
# ---------------------------------------------------------------------------

def test_info_data_defaults() -> None:
    info = InfoData()
    assert info.version == ''
    assert info.homepage == ''
    assert info.download_x86 == ''
    assert info.md5sum_x86 == ''
    assert info.download_x86_64 == ''
    assert info.md5sum_x86_64 == ''
    assert info.requires == ''
    assert info.arm_support is False


# ---------------------------------------------------------------------------
# MaintainerData defaults
# ---------------------------------------------------------------------------

def test_maintainer_data_defaults() -> None:
    m = MaintainerData()
    assert m.name == ''
    assert m.email == ''
    assert m.where_you_live == ''
    assert m.editor == ''
    assert m.editor_options == ''
    assert m.sbo_repo_version == '15.0'


# ---------------------------------------------------------------------------
# AppContext defaults
# ---------------------------------------------------------------------------

def test_app_context_default_prg_name() -> None:
    ctx = AppContext()
    assert ctx.prg_name == ''


def test_app_context_config_path_in_home() -> None:
    ctx = AppContext()
    assert '.config' in str(ctx.config_path)
    assert 'sbo-create' in str(ctx.config_path)


def test_app_context_templates_path_in_local_share() -> None:
    ctx = AppContext()
    assert '.local' in str(ctx.templates_path)
    assert 'sbo-create' in str(ctx.templates_path)
    assert 'templates' in str(ctx.templates_path)


# ---------------------------------------------------------------------------
# set_x86_labels
# ---------------------------------------------------------------------------

def test_set_x86_labels_clears_arm_support() -> None:
    info = InfoData(arm_support=True)
    set_x86_labels(info)
    assert info.arm_support is False


def test_set_x86_labels_contains_x86_64() -> None:
    info = InfoData()
    set_x86_labels(info)
    assert any('x86_64' in lbl for lbl in info.labels)


def test_set_x86_labels_count() -> None:
    info = InfoData()
    set_x86_labels(info)
    assert len(info.labels) == 10


# ---------------------------------------------------------------------------
# set_arm_labels
# ---------------------------------------------------------------------------

def test_set_arm_labels_sets_arm_support() -> None:
    info = InfoData()
    set_arm_labels(info)
    assert info.arm_support is True


def test_set_arm_labels_contains_arm64() -> None:
    info = InfoData()
    set_arm_labels(info)
    assert any('ARM64' in lbl for lbl in info.labels)


def test_set_arm_labels_no_x86_64() -> None:
    info = InfoData()
    set_arm_labels(info)
    assert not any('x86_64' in lbl for lbl in info.labels)


def test_set_arm_labels_count() -> None:
    info = InfoData()
    set_arm_labels(info)
    assert len(info.labels) == 10


# ---------------------------------------------------------------------------
# set_color / colorize
# ---------------------------------------------------------------------------

def test_colorize_disabled_returns_plain_text() -> None:
    set_color(False)
    try:
        assert colorize('hello', 'green') == 'hello'
    finally:
        set_color(True)


def test_colorize_enabled_state_restored() -> None:
    set_color(False)
    set_color(True)
    assert _Color.enabled is True


def test_colorize_returns_ansi_when_tty() -> None:
    set_color(True)
    with patch.object(sys.stdout, 'isatty', return_value=True):
        result = colorize('hello', 'green')
    assert '\033[' in result
    assert 'hello' in result


# ---------------------------------------------------------------------------
# confirm — exception paths
# ---------------------------------------------------------------------------

def test_confirm_keyboard_interrupt_exits_0() -> None:
    with patch('builtins.input', side_effect=KeyboardInterrupt):
        with pytest.raises(SystemExit) as exc_info:
            confirm('sure?')
    assert exc_info.value.code == 0


def test_confirm_eof_exits_0() -> None:
    with patch('builtins.input', side_effect=EOFError):
        with pytest.raises(SystemExit) as exc_info:
            confirm('sure?')
    assert exc_info.value.code == 0
