# Copyright 2015-2025 Earth Sciences Department, BSC-CNS
#
# This file is part of Autosubmit.
#
# Autosubmit is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Autosubmit is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Autosubmit.  If not, see <http://www.gnu.org/licenses/>.

import pytest
from portalocker.exceptions import BaseLockException

from autosubmit.log.log import AutosubmitCritical, AutosubmitError
from autosubmit.scripts.autosubmit import delete_lock_file, exit_from_error


def test_delete_lockfile(tmp_path):
    fake_lock = tmp_path / 'autosubmit.lock'
    fake_lock.touch()

    delete_lock_file(str(tmp_path), 'not-found')

    assert fake_lock.exists()
    delete_lock_file(str(tmp_path), fake_lock.name)
    assert not fake_lock.exists()


def test_log_critical_raises_error(mocker):
    """TODO: this probably should never happen?"""

    def _fn():
        raise ValueError

    try:
        _fn()
    except BaseException as e:
        mocker.patch('autosubmit.scripts.autosubmit._exit')  # mock this to avoid the system from exiting
        mocked_log = mocker.patch('autosubmit.scripts.autosubmit.Log')
        mocked_print = mocker.patch('autosubmit.scripts.autosubmit.print')

        mocked_log.critical.side_effect = BaseException()
        with pytest.raises(BaseException):
            exit_from_error(e)

        assert mocked_print.called


_TEST_EXCEPTION = AutosubmitCritical()
_TEST_EXCEPTION.trace = 'a trace'


@pytest.mark.parametrize(
    'exception,debug_calls,critical_calls,delete_called',
    [
        (ValueError, 0, 2, True),
        (BaseLockException, 0, 1, False),
        (AutosubmitCritical, 0, 2, True),
        (_TEST_EXCEPTION, 1, 2, True),
        (AutosubmitError, 0, 2, True)
    ],
    ids=[
        'normal_exception',
        'portalocker_exception',
        'autosubmit_critical',
        'autosubmit_critical_with_trace',
        'autosubmit_error'
    ]
)
def test_exit_from_error(
        mocker,
        tmp_path,
        exception: BaseException,
        debug_calls: int,
        critical_calls: int,
        delete_called: bool
):
    def _fn():
        raise exception

    try:
        _fn()
    except BaseException as e:
        mocker.patch('autosubmit.scripts.autosubmit._exit')  # mock this to avoid the system from exiting
        mocked_log = mocker.patch('autosubmit.scripts.autosubmit.Log')
        mocked_delete = mocker.patch('autosubmit.scripts.autosubmit.delete_lock_file')

        exit_from_error(e)

        assert mocked_log.debug.call_count == debug_calls
        assert mocked_log.critical.call_count == critical_calls
        assert mocked_delete.called == delete_called
