#!/usr/bin/python3
# -*- coding: utf-8 -*-

from unittest.mock import MagicMock, patch

from sun.utils import Utilities


class TestGetDaemonPid:

    def test_pid_file_exists(self, tmp_path):
        pid_file = tmp_path / 'sun-daemon.pid'
        pid_file.write_text('12345\n', encoding='utf-8')
        with patch('sun.utils.DAEMON_PID_FILE', pid_file):
            utils = Utilities()
            assert utils.get_daemon_pid() == '12345'

    def test_no_pid_file(self, tmp_path):
        pid_file = tmp_path / 'sun-daemon.pid'
        with patch('sun.utils.DAEMON_PID_FILE', pid_file):
            utils = Utilities()
            assert utils.get_daemon_pid() == ''


class TestOsInfoHtml:

    def test_contains_os_name(self):
        utils = Utilities()
        html = utils.os_info_html()
        assert 'Slackware 15.0' in html

    def test_contains_hostname(self):
        utils = Utilities()
        html = utils.os_info_html()
        assert 'testhost' in html

    def test_contains_sections(self):
        utils = Utilities()
        html = utils.os_info_html()
        assert '[System]' in html
        assert '[Processor]' in html
        assert '[Memory]' in html
        assert '[Disk]' in html
        assert '[GPU]' in html


class TestConfigHtml:

    def test_contains_sections(self):
        utils = Utilities()
        html = utils.config_html()
        assert '[REPOSITORY]' in html
        assert '[TIME]' in html
        assert '[TRAY_ICON]' in html

    def test_contains_keys(self):
        utils = Utilities()
        html = utils.config_html()
        assert 'HTTP_MIRROR' in html
        assert 'INTERVAL' in html
        assert 'LOG_FONT_SIZE' in html

    def test_aligned_equals(self):
        utils = Utilities()
        html = utils.config_html()
        # All key=value lines should use the same separator
        assert '  =  ' in html

    def test_empty_config_returns_empty(self, tmp_path):
        utils = Utilities()
        (tmp_path / 'sun.conf').write_text('', encoding='utf-8')
        with patch.object(utils.configs, 'data_configs', {'sun_conf_path': tmp_path}):
            result = utils.config_html()
        assert result == ''


class TestFetchIfModified:

    def test_returns_content_on_success(self):
        utils = Utilities()
        mock_response = MagicMock()
        mock_response.status = 200
        mock_response.data = b'changelog content'
        mock_response.headers.get.return_value = 'Mon, 01 Jan 2026 00:00:00 GMT'
        with patch('urllib3.PoolManager') as mock_pm:
            mock_pm.return_value.request.return_value = mock_response
            content, lm = utils.fetch_if_modified()
        assert content == 'changelog content'
        assert lm == 'Mon, 01 Jan 2026 00:00:00 GMT'

    def test_returns_none_on_304(self):
        utils = Utilities()
        mock_response = MagicMock()
        mock_response.status = 304
        with patch('urllib3.PoolManager') as mock_pm:
            mock_pm.return_value.request.return_value = mock_response
            content, lm = utils.fetch_if_modified('old-lm')
        assert content is None
        assert lm == 'old-lm'

    def test_http_error_returns_none(self):
        utils = Utilities()
        from urllib3.exceptions import HTTPError
        with patch('urllib3.PoolManager') as mock_pm:
            mock_pm.return_value.request.side_effect = HTTPError()
            content, lm = utils.fetch_if_modified()
        assert content is None

    def test_ftp_not_supported_returns_none(self):
        utils = Utilities()
        import urllib3
        with patch('urllib3.PoolManager') as mock_pm:
            mock_pm.return_value.request.side_effect = urllib3.exceptions.LocationValueError()
            content, lm = utils.fetch_if_modified()
        assert content is None


class TestReadRepoTextFile:

    def test_successful_request(self):
        utils = Utilities()
        mock_response = MagicMock()
        mock_response.data = b'ChangeLog content'
        with patch('urllib3.PoolManager') as mock_pm:
            mock_pm.return_value.request.return_value = mock_response
            result = utils.read_repo_text_file()
            assert result == 'ChangeLog content'

    def test_http_error(self, capsys):
        utils = Utilities()
        from urllib3.exceptions import HTTPError
        with patch('urllib3.PoolManager') as mock_pm:
            mock_pm.return_value.request.side_effect = HTTPError()
            result = utils.read_repo_text_file()
            assert result == ''
            assert 'Failed to connect' in capsys.readouterr().out

    def test_ftp_not_supported(self, capsys):
        utils = Utilities()
        import urllib3
        with patch('urllib3.PoolManager') as mock_pm:
            mock_pm.return_value.request.side_effect = urllib3.exceptions.LocationValueError()
            result = utils.read_repo_text_file()
            assert result == ''
            assert 'Ftp mirror not supported' in capsys.readouterr().out


class TestProcessPids:

    def test_found_processes(self):
        ps_output = 'user 1234 0.0 0.0 sun-tray\nuser 5678 0.0 0.0 sun-tray\n'
        with patch('subprocess.check_output', return_value=ps_output.encode()):
            pids = Utilities.process_pids('sun-tray')
            assert 1234 in pids
            assert 5678 in pids

    def test_no_processes(self):
        ps_output = 'user 1234 0.0 0.0 other-process\n'
        with patch('subprocess.check_output', return_value=ps_output.encode()):
            pids = Utilities.process_pids('sun-tray')
            assert pids == []

    def test_called_process_error(self, capsys):
        import subprocess
        with patch('subprocess.check_output', side_effect=subprocess.CalledProcessError(1, 'ps')):
            pids = Utilities.process_pids('sun-tray')
            assert pids == []
            assert 'Error executing' in capsys.readouterr().out

    def test_malformed_line_skipped(self):
        ps_output = 'sun-tray\nuser 1234 0.0 0.0 sun-tray\n'
        with patch('subprocess.check_output', return_value=ps_output.encode()):
            pids = Utilities.process_pids('sun-tray')
            assert pids == [1234]
