"""Tests for v1.4 workflow execution mode."""

from __future__ import annotations

import tempfile
import unittest
from unittest.mock import patch

from kiessclaw.providers.models import ProviderResult
from kiessclaw.runtime import build_agent_registry
from kiessclaw.workflow.runner import WorkflowRunner
from tests.test_helpers import base_config


class WorkflowRunnerTest(unittest.TestCase):
    """Validate workflow runner behavior across core use cases."""

    def _runner(self, workspace: str) -> WorkflowRunner:
        config = base_config()
        config["workspace"]["root"] = workspace
        registry = build_agent_registry(config)
        return WorkflowRunner(config=config, registry=registry)

    def test_outreach_sdr_dry_run_creates_zero_enrollments(self) -> None:
        """Dry-run should not persist enrollment records."""
        with tempfile.TemporaryDirectory() as tempdir:
            runner = self._runner(tempdir)
            result = runner.run(
                usecase_id="outreach_sdr",
                inputs={
                    "company": "Acme",
                    "domain": "acme.com",
                    "contacts": [{"email": "cto@acme.com", "title": "CTO", "industry": "software", "employee_count": 80}],
                },
                dry_run=True,
                auto_enroll=True,
            )
            self.assertEqual(0, len(runner.memory.load_data("enrollments")))
            self.assertEqual(0, result.enrolled)

    def test_outreach_sdr_live_creates_enrollments(self) -> None:
        """Non-dry-run with qualified contacts should create enrollments."""
        with tempfile.TemporaryDirectory() as tempdir:
            runner = self._runner(tempdir)
            result = runner.run(
                usecase_id="outreach_sdr",
                inputs={
                    "company": "Acme",
                    "domain": "acme.com",
                    "sender_email": "rep@acme.com",
                    "contacts": [{"email": "cto@acme.com", "title": "CTO", "industry": "software", "employee_count": 80}],
                },
                dry_run=False,
                auto_enroll=True,
            )
            self.assertGreaterEqual(result.enrolled, 1)
            self.assertGreaterEqual(len(runner.memory.load_data("enrollments")), 1)

    def test_enrichment_only_uses_active_provider(self) -> None:
        """Enrichment workflow should resolve and report active provider."""
        with tempfile.TemporaryDirectory() as tempdir:
            runner = self._runner(tempdir)
            result = runner.run(
                usecase_id="enrichment_only",
                inputs={"contacts": [{"email": "alex@acme.com"}]},
                dry_run=True,
            )
            self.assertEqual("mock", result.outputs.get("provider"))
            self.assertIn("enrich_contacts", result.steps_run)

    def test_unknown_usecase_returns_error(self) -> None:
        """Unknown use case IDs should return structured workflow errors."""
        with tempfile.TemporaryDirectory() as tempdir:
            runner = self._runner(tempdir)
            result = runner.run("not_a_real_usecase", inputs={}, dry_run=True)
            self.assertTrue(result.errors)
            self.assertIn("Unknown use case", result.errors[0])

    def test_crm_sync_skipped_gracefully_for_mock_provider(self) -> None:
        """CRM sync should be skipped without failing when crm provider is mock."""
        with tempfile.TemporaryDirectory() as tempdir:
            runner = self._runner(tempdir)
            result = runner.run(
                usecase_id="outreach_sdr",
                inputs={
                    "company": "Acme",
                    "domain": "acme.com",
                    "sender_email": "rep@acme.com",
                    "contacts": [{"email": "cto@acme.com", "title": "CTO", "industry": "software", "employee_count": 80}],
                },
                dry_run=False,
                auto_enroll=True,
            )
            crm_sync = result.outputs.get("crm_sync", {})
            self.assertTrue(isinstance(crm_sync, dict))
            self.assertTrue(crm_sync.get("skipped"))
            self.assertGreaterEqual(result.enrolled, 1)

    def test_crm_sync_error_does_not_fail_workflow(self) -> None:
        """CRM sync failures should surface as warnings without failing run."""

        class FailingCrmProvider:
            """CRM provider stub that always returns failure."""

            name = "hubspot"

            @staticmethod
            def create_contact(_: object) -> ProviderResult:
                """Return deterministic failed provider result."""
                return ProviderResult(ok=False, provider="hubspot", error="crm unavailable")

        with tempfile.TemporaryDirectory() as tempdir:
            config = base_config()
            config["workspace"]["root"] = tempdir
            config["providers"]["crm"] = "hubspot"
            registry = build_agent_registry(config)
            runner = WorkflowRunner(config=config, registry=registry)

            with patch("kiessclaw.workflow.runner.active_provider", return_value=FailingCrmProvider()):
                result = runner.run(
                    usecase_id="outreach_sdr",
                    inputs={
                        "company": "Acme",
                        "domain": "acme.com",
                        "sender_email": "rep@acme.com",
                        "contacts": [
                            {"email": "cto@acme.com", "title": "CTO", "industry": "software", "employee_count": 80}
                        ],
                    },
                    dry_run=False,
                    auto_enroll=True,
                )

            crm_sync = result.outputs.get("crm_sync", {})
            self.assertEqual("hubspot", crm_sync.get("provider"))
            self.assertEqual(1, crm_sync.get("attempted"))
            self.assertEqual(0, crm_sync.get("synced"))
            self.assertTrue(crm_sync.get("warnings"))
            self.assertFalse(result.errors)


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