"""
DOOBAT - Tests de revalidation Odoo pour les demandes Telegram.
"""

import os
import sys
import types
import unittest
from unittest.mock import AsyncMock, MagicMock, patch

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

# Le runner minimal de test n'installe pas le transport Telegram.
sys.modules.setdefault(
    "aiohttp",
    types.SimpleNamespace(ClientTimeout=lambda **kwargs: MagicMock()),
)

from routes import telegram_webhook


class TestResolvePartnerPhoneValidation(unittest.IsolatedAsyncioTestCase):
    """Chaque demande doit revalider le telephone associe dans Odoo."""

    def setUp(self):
        self.auth = MagicMock()
        self.odoo = MagicMock()
        self.auth.find_partner_by_telegram.return_value = 42
        self.auth.get_linked_phone.return_value = "+33612345678"

        self.auth_patch = patch.object(telegram_webhook, "_auth", self.auth)
        self.odoo_patch = patch.object(telegram_webhook, "_odoo", self.odoo)
        self.auth_patch.start()
        self.odoo_patch.start()

    def tearDown(self):
        self.odoo_patch.stop()
        self.auth_patch.stop()

    async def test_accepts_phone_still_present_on_linked_contact(self):
        partner = {"id": 42, "name": "Contact Odoo"}
        self.odoo.find_partner_by_phone.return_value = partner

        result = await telegram_webhook._resolve_partner(100, {})

        self.assertEqual(result, partner)
        self.odoo.find_partner_by_phone.assert_called_once_with(
            "+33612345678", refresh=True
        )

    async def test_rejects_phone_removed_from_odoo_contacts(self):
        self.odoo.find_partner_by_phone.return_value = None

        result = await telegram_webhook._resolve_partner(100, {})

        self.assertIsNone(result)
        self.odoo.find_partner_by_phone.assert_called_once_with(
            "+33612345678", refresh=True
        )

    async def test_rejects_phone_now_attached_to_another_contact(self):
        self.odoo.find_partner_by_phone.return_value = {
            "id": 99,
            "name": "Autre contact Odoo",
        }

        result = await telegram_webhook._resolve_partner(100, {})

        self.assertIsNone(result)

    async def test_migrates_legacy_link_only_after_phone_validation(self):
        partner = {"id": 42, "name": "Contact Odoo", "phone": "0612345678"}
        self.auth.get_linked_phone.return_value = ""
        self.odoo.find_partner_by_id.return_value = partner
        self.odoo.get_partner_phone.return_value = "0612345678"
        self.odoo.find_partner_by_phone.return_value = partner

        result = await telegram_webhook._resolve_partner(100, {})

        self.assertEqual(result, partner)
        self.odoo.find_partner_by_id.assert_called_once_with(42, refresh=True)
        self.odoo.find_partner_by_phone.assert_called_once_with(
            "0612345678", refresh=True
        )
        self.auth.link_telegram_to_partner.assert_called_once_with(
            100, 42, "0612345678"
        )


class TestNaturalLanguageRequiresValidatedContact(unittest.IsolatedAsyncioTestCase):
    """Une demande metier ne doit pas atteindre l'IA sans contact Odoo valide."""

    async def test_request_is_blocked_before_analysis_when_phone_is_invalid(self):
        telegram = MagicMock()
        telegram.send_not_authorized = AsyncMock()
        ai = MagicMock()

        with (
            patch.object(
                telegram_webhook, "_resolve_partner", AsyncMock(return_value=None)
            ),
            patch.object(telegram_webhook, "_telegram", telegram),
            patch.object(telegram_webhook, "_ai", ai),
        ):
            await telegram_webhook._handle_natural_language(
                100, "factures fournisseurs", "Test", {}
            )

        telegram.send_not_authorized.assert_awaited_once_with(100)
        ai.analyze_message.assert_not_called()


if __name__ == "__main__":
    unittest.main(verbosity=2)
