"""Tests for the delete_email skill."""

import imaplib
import os
from unittest.mock import MagicMock, call, 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, "delete_email"))


def test_delete_email_schema():
    skill = _load_skill()
    schema = skill.schema()
    assert schema["name"] == "delete_email"
    assert "message_id" in schema["parameters"]["properties"]
    assert set(schema["parameters"]["required"]) == {"message_id"}


async def test_delete_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({"message_id": "123"})


async def test_delete_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({"message_id": "123"})


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

    mock_conn = MagicMock()
    mock_conn.login.return_value = ("OK", [])
    mock_conn.select.return_value = ("OK", [b"1"])
    mock_conn.uid.return_value = ("OK", [b"1 (FLAGS (\\Deleted))"])
    mock_conn.expunge.return_value = ("OK", [])
    mock_conn.logout.return_value = ("OK", [])

    with patch("imaplib.IMAP4_SSL", return_value=mock_conn):
        result = await skill.execute({"message_id": "456"})

    assert "456" in result["status"]
    assert "deleted" in result["status"].lower() or "trash" in result["status"].lower()
    mock_conn.uid.assert_has_calls([
        call("copy", "456", "[Gmail]/Trash"),
        call("store", "456", "+FLAGS", "\\Deleted"),
    ])
    mock_conn.expunge.assert_called_once()


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

    mock_conn = MagicMock()
    mock_conn.login.return_value = ("OK", [])
    mock_conn.select.return_value = ("OK", [b"1"])
    mock_conn.uid.side_effect = imaplib.IMAP4.error("UID not found")
    mock_conn.logout.return_value = ("OK", [])

    with patch("imaplib.IMAP4_SSL", return_value=mock_conn):
        with pytest.raises(ValueError, match="IMAP error"):
            await skill.execute({"message_id": "999"})


async def test_delete_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()

    mock_conn = MagicMock()
    mock_conn.login.return_value = ("OK", [])
    mock_conn.select.return_value = ("OK", [b"1"])
    mock_conn.uid.return_value = ("OK", [b"1 (FLAGS (\\Deleted))"])
    mock_conn.expunge.return_value = ("OK", [])
    mock_conn.logout.return_value = ("OK", [])

    with patch("imaplib.IMAP4_SSL", return_value=mock_conn):
        result = await skill.execute({
            "message_id": "789",
        })

    assert "789" in result["status"]
    mock_conn.login.assert_called_once_with("work@gmail.com", "work-pass")
