import tempfile
from unittest.mock import Mock, patch

from django.test import TestCase

from core.clients import transport


class SignalUnlinkFallbackTests(TestCase):
    def test_signal_wipe_uses_project_signal_cli_config_dir(self):
        with tempfile.TemporaryDirectory() as tmpdir:
            signal_root = os.path.join(tmpdir, "signal-cli-config")
            os.makedirs(signal_root, exist_ok=True)
            account_dir = os.path.join(signal_root, "account-data")
            os.makedirs(account_dir, exist_ok=True)
            keep_file = os.path.join(signal_root, "jsonrpc2.yml")
            with open(keep_file, "w", encoding="utf-8") as handle:
                handle.write("jsonrpc")
            data_file = os.path.join(account_dir, "state.db")
            with open(data_file, "w", encoding="utf-8") as handle:
                handle.write("state")

            with patch.object(transport.settings, "BASE_DIR", tmpdir):
                result = transport._wipe_signal_cli_local_state()

            self.assertTrue(result)
            self.assertTrue(os.path.exists(keep_file))
            self.assertFalse(os.path.exists(account_dir))

    @patch("requests.get")
    def test_signal_list_accounts_uses_fast_timeout(self, mock_get):
        ok_response = Mock()
        ok_response.ok = True
        ok_response.text = "[]"
        mock_get.return_value = ok_response

        result = transport.list_accounts("signal")

        self.assertEqual([], result)
        mock_get.assert_called_once()
        _, kwargs = mock_get.call_args
        self.assertEqual(5, int(kwargs.get("timeout") or 0))

    @patch("core.clients.transport._wipe_signal_cli_local_state")
    @patch("requests.delete")
    def test_signal_unlink_uses_rest_delete_when_available(
        self,
        mock_delete,
        mock_wipe,
    ):
        ok_response = Mock()
        ok_response.ok = True
        mock_delete.return_value = ok_response

        result = transport.unlink_account("signal", "+447700900000")

        self.assertTrue(result)
        self.assertTrue(mock_delete.called)
        mock_wipe.assert_not_called()

    @patch("core.clients.transport._wipe_signal_cli_local_state")
    @patch("requests.delete")
    def test_signal_unlink_falls_back_to_local_wipe(
        self,
        mock_delete,
        mock_wipe,
    ):
        bad_response = Mock()
        bad_response.ok = False
        mock_delete.return_value = bad_response
        mock_wipe.return_value = True

        result = transport.unlink_account("signal", "+447700900000")

        self.assertTrue(result)
        self.assertEqual(2, mock_delete.call_count)
        mock_wipe.assert_called_once()

    @patch("core.clients.transport.list_accounts")
    @patch("core.clients.transport._wipe_signal_cli_local_state")
    @patch("requests.delete")
    def test_signal_unlink_returns_false_when_account_still_listed_after_wipe(
        self,
        mock_delete,
        mock_wipe,
        mock_list_accounts,
    ):
        bad_response = Mock()
        bad_response.ok = False
        mock_delete.return_value = bad_response
        mock_wipe.return_value = True
        mock_list_accounts.return_value = ["+447700900000"]

        result = transport.unlink_account("signal", "+447700900000")

        self.assertFalse(result)
        self.assertEqual(2, mock_delete.call_count)
        mock_wipe.assert_called_once()
        mock_list_accounts.assert_called_once_with("signal")
