"""Tests for the send_email skill."""

import os
from unittest.mock import MagicMock, patch

import pytest

from fliiq.runtime.package_data import bundled_skills_dir
from fliiq.runtime.skills.base import SkillBase

SKILLS_DIR = str(bundled_skills_dir())


def _load_skill() -> SkillBase:
    return SkillBase(os.path.join(SKILLS_DIR, "send_email"))


def test_send_email_schema():
    skill = _load_skill()
    schema = skill.schema()
    assert schema["name"] == "send_email"
    assert "to" in schema["parameters"]["properties"]
    assert "subject" in schema["parameters"]["properties"]
    assert "body" in schema["parameters"]["properties"]
    assert set(schema["parameters"]["required"]) == {"to", "subject", "body"}


async def test_send_email_missing_gmail_address(monkeypatch):
    monkeypatch.delenv("GMAIL_ADDRESS", raising=False)
    monkeypatch.delenv("GMAIL_APP_PASSWORD", raising=False)
    skill = _load_skill()
    with pytest.raises(ValueError, match="GMAIL_ADDRESS"):
        await skill.execute({"to": "a@b.com", "subject": "Hi", "body": "Test"})


async def test_send_email_missing_app_password(monkeypatch):
    monkeypatch.setenv("GMAIL_ADDRESS", "test@gmail.com")
    monkeypatch.delenv("GMAIL_APP_PASSWORD", raising=False)
    skill = _load_skill()
    with pytest.raises(ValueError, match="GMAIL_APP_PASSWORD"):
        await skill.execute({"to": "a@b.com", "subject": "Hi", "body": "Test"})


async def test_send_email_no_recipients(monkeypatch):
    monkeypatch.setenv("GMAIL_ADDRESS", "test@gmail.com")
    monkeypatch.setenv("GMAIL_APP_PASSWORD", "fake-password")
    skill = _load_skill()
    with pytest.raises(ValueError, match="No valid recipient"):
        await skill.execute({"to": "  ", "subject": "Hi", "body": "Test"})


async def test_send_email_success(monkeypatch):
    monkeypatch.setenv("GMAIL_ADDRESS", "test@gmail.com")
    monkeypatch.setenv("GMAIL_APP_PASSWORD", "fake-password")
    skill = _load_skill()

    with patch("smtplib.SMTP") as mock_smtp:
        mock_server = MagicMock()
        mock_smtp.return_value.__enter__ = MagicMock(return_value=mock_server)
        mock_smtp.return_value.__exit__ = MagicMock(return_value=False)
        result = await skill.execute({"to": "a@b.com", "subject": "Hi", "body": "Test"})

    assert "sent" in result["status"].lower()
    assert "a@b.com" in result["status"]


async def test_send_email_multiple_recipients(monkeypatch):
    monkeypatch.setenv("GMAIL_ADDRESS", "test@gmail.com")
    monkeypatch.setenv("GMAIL_APP_PASSWORD", "fake-password")
    skill = _load_skill()

    with patch("smtplib.SMTP") as mock_smtp:
        mock_server = MagicMock()
        mock_smtp.return_value.__enter__ = MagicMock(return_value=mock_server)
        mock_smtp.return_value.__exit__ = MagicMock(return_value=False)
        result = await skill.execute({
            "to": "a@b.com, c@d.com",
            "subject": "Hi",
            "body": "Test",
        })

    assert "a@b.com" in result["status"]
    assert "c@d.com" in result["status"]


async def test_send_email_env_override(monkeypatch):
    """Env var override: FLIIQ_GMAIL_* env vars configure credentials."""
    monkeypatch.setenv("FLIIQ_GMAIL_ADDRESS", "work@gmail.com")
    monkeypatch.setenv("FLIIQ_GMAIL_APP_PASSWORD", "work-pass")
    skill = _load_skill()

    with patch("smtplib.SMTP") as mock_smtp:
        mock_server = MagicMock()
        mock_smtp.return_value.__enter__ = MagicMock(return_value=mock_server)
        mock_smtp.return_value.__exit__ = MagicMock(return_value=False)
        result = await skill.execute({
            "to": "a@b.com",
            "subject": "Hi",
            "body": "Test",
        })

    assert "sent" in result["status"].lower()
    mock_server.login.assert_called_once_with("work@gmail.com", "work-pass")
