"""Website contact and enterprise inquiry admin-notification tests."""
from __future__ import annotations
from types import SimpleNamespace
from unittest.mock import AsyncMock, MagicMock
from uuid import uuid4

import pytest

from src.config import Settings
from src.core.protocols import SendResult
from src.domain.billing.inquiry_service import EnterpriseInquiryService
from src.domain.billing.inquiry_templates import render_enterprise_inquiry_notification
from src.domain.public.service import ContactInquiryService
from src.domain.public.templates import render_contact_notification
from src.integrations.ops_notifier import EmailOpsNotifier


class FakeEmailProvider:
    def __init__(self, *, fail_for: set[str] | None = None):
        self.fail_for = fail_for or set()
        self.sent: list[dict] = []

    async def send(self, to, subject, html, text=None, reply_to=None):
        self.sent.append(
            {"to": to, "subject": subject, "html": html, "text": text, "reply_to": reply_to}
        )
        if to in self.fail_for:
            return SendResult(success=False, error="boom")
        return SendResult(success=True, message_id="msg_1")


@pytest.mark.asyncio
async def test_ops_notifier_fans_out_with_reply_to():
    provider = FakeEmailProvider()
    notifier = EmailOpsNotifier(provider, ["ops@p2hs.com", "sales@p2hs.com"])

    await notifier.notify(
        subject="Lead",
        html="<p>Hi</p>",
        text="Hi",
        reply_to="jane@example.com",
    )

    assert [item["to"] for item in provider.sent] == ["ops@p2hs.com", "sales@p2hs.com"]
    assert provider.sent[0]["reply_to"] == "jane@example.com"


@pytest.mark.asyncio
async def test_ops_notifier_skips_when_email_is_unconfigured():
    notifier = EmailOpsNotifier(None, ["ops@p2hs.com"])
    await notifier.notify(subject="Lead", html="<p>Hi</p>", text="Hi")


@pytest.mark.asyncio
async def test_ops_notifier_continues_after_recipient_failure():
    provider = FakeEmailProvider(fail_for={"bad@p2hs.com"})
    notifier = EmailOpsNotifier(provider, ["bad@p2hs.com", "ops@p2hs.com"])

    await notifier.notify(subject="Lead", html="<p>Hi</p>", text="Hi")

    assert len(provider.sent) == 2


@pytest.mark.asyncio
async def test_contact_inquiry_service_persists_then_notifies():
    repo = MagicMock()
    row = SimpleNamespace(
        id=uuid4(),
        first_name="Jane",
        last_name="Smith",
        email="jane@example.com",
        company="Acme",
        subject="sales",
        message="We want a custom workspace.",
    )
    repo.create = AsyncMock(return_value=row)
    notifier = MagicMock()
    notifier.notify = AsyncMock()
    service = ContactInquiryService(repo, notifier)

    created = await service.create(
        first_name="Jane",
        last_name="Smith",
        email="jane@example.com",
        company="Acme",
        subject="sales",
        message="We want a custom workspace.",
    )
    await service.notify_admins(created)

    repo.create.assert_awaited_once()
    notifier.notify.assert_awaited_once()
    kwargs = notifier.notify.await_args.kwargs
    assert kwargs["reply_to"] == "jane@example.com"
    assert "Sales / Enterprise" in kwargs["subject"]


@pytest.mark.asyncio
async def test_contact_notify_failure_does_not_raise():
    row = SimpleNamespace(
        id=uuid4(),
        first_name="Jane",
        last_name="Smith",
        email="jane@example.com",
        company=None,
        subject="general",
        message="Hello there team.",
    )
    notifier = MagicMock()
    notifier.notify = AsyncMock(side_effect=RuntimeError("smtp down"))
    service = ContactInquiryService(MagicMock(), notifier)

    await service.notify_admins(row)


@pytest.mark.asyncio
async def test_enterprise_inquiry_service_notifies_ops():
    repo = MagicMock()
    row = SimpleNamespace(
        id=uuid4(),
        first_name="Jane",
        last_name="Smith",
        email="jane@example.com",
        phone="+1-555-0100",
        website_count=12,
        ai_credit_minutes_desired=500,
        is_agency_account=True,
        employee_count=40,
        additional_features="SSO and SLA",
        plan_slug="enterprise",
        workspace_id=uuid4(),
    )
    repo.create = AsyncMock(return_value=row)
    notifier = MagicMock()
    notifier.notify = AsyncMock()
    service = EnterpriseInquiryService(repo, notifier)

    created = await service.create(
        workspace_id=row.workspace_id,
        user_id=None,
        first_name="Jane",
        last_name="Smith",
        email="jane@example.com",
        phone="+1-555-0100",
        website_count=12,
        ai_credit_minutes_desired=500,
        is_agency_account=True,
        employee_count=40,
        additional_features="SSO and SLA",
        plan_slug="enterprise",
    )
    await service.notify_admins(created)

    kwargs = notifier.notify.await_args.kwargs
    assert kwargs["reply_to"] == "jane@example.com"
    assert "Enterprise inquiry" in kwargs["subject"]
    assert "SSO and SLA" in kwargs["text"]


def test_contact_template_escapes_html():
    row = SimpleNamespace(
        first_name="<script>",
        last_name="Alert",
        email="jane@example.com",
        company="Acme",
        subject="sales",
        message="Hello <b>team</b>\nNext line",
    )
    subject, html, text = render_contact_notification(row)
    assert "<script>" not in html
    assert "&lt;script&gt;" in html
    assert "Hello &lt;b&gt;team&lt;/b&gt;<br>Next line" in html
    assert "jane@example.com" in text
    assert "Sales / Enterprise" in subject


def test_enterprise_template_includes_sales_fields():
    row = SimpleNamespace(
        first_name="Jane",
        last_name="Smith",
        email="jane@example.com",
        phone="555-0100",
        website_count=3,
        ai_credit_minutes_desired=120,
        is_agency_account=False,
        employee_count=8,
        additional_features="Need <b>SSO</b>",
        plan_slug="enterprise",
        workspace_id=None,
    )
    subject, html, text = render_enterprise_inquiry_notification(row)
    assert "&lt;b&gt;SSO&lt;/b&gt;" in html
    assert "<b>SSO</b>" not in html
    assert "Need <b>SSO</b>" in text
    assert "jane@example.com" in text
    assert subject.startswith("[P2HS] Enterprise inquiry")


def test_ops_notify_email_list_dedupes_and_normalizes():
    settings = Settings(
        ops_notify_emails="  Support@p2hs.com, mohsin@pie-solutions.com, support@p2hs.com "
    )
    assert settings.ops_notify_email_list == [
        "support@p2hs.com",
        "mohsin@pie-solutions.com",
    ]
