"""
Tests for the research scheduler API routes.

Tests cover:
- Get scheduler status endpoint
- Trigger manual run endpoint
- Authentication handling
"""

from unittest.mock import Mock, patch

import pytest


class TestSchedulerRoutes:
    """Tests for the scheduler API routes."""

    @pytest.fixture
    def app(self):
        """Create a test Flask app with the scheduler blueprint."""
        from flask import Flask

        from local_deep_research.research_scheduler.routes import (
            scheduler_bp,
        )
        from local_deep_research.web.auth import auth_bp

        app = Flask(__name__)
        app.secret_key = "test-secret-key"
        app.register_blueprint(auth_bp)
        app.register_blueprint(scheduler_bp)
        return app

    @pytest.fixture
    def client(self, app):
        """Create a test client."""
        return app.test_client()

    def test_get_scheduler_status_unauthenticated(self, client):
        """Test status endpoint returns 401 when not authenticated."""
        response = client.get("/api/scheduler/status")

        assert response.status_code == 401
        data = response.get_json()
        assert "error" in data
        assert "authentication required" in data["error"].lower()

    def test_get_scheduler_status_authenticated(self, client, app):
        """Test status endpoint returns status when authenticated."""
        with (
            patch(
                "local_deep_research.research_scheduler.routes.get_document_scheduler"
            ) as mock_get_scheduler,
            patch(
                "local_deep_research.web.auth.decorators.db_manager"
            ) as mock_db,
        ):
            mock_db.connections = {"testuser": True}
            mock_scheduler = Mock()
            mock_scheduler.get_status.return_value = {
                "is_running": False,
                "last_run": "2024-01-01T00:00:00",
                "next_run": "2024-01-02T00:00:00",
            }
            mock_get_scheduler.return_value = mock_scheduler

            with client.session_transaction() as sess:
                sess["username"] = "testuser"

            response = client.get("/api/scheduler/status")

            assert response.status_code == 200
            data = response.get_json()
            assert data["is_running"] is False
            mock_scheduler.get_status.assert_called_once_with("testuser")

    def test_get_scheduler_status_error(self, client, app):
        """Test status endpoint handles errors gracefully."""
        with (
            patch(
                "local_deep_research.research_scheduler.routes.get_document_scheduler"
            ) as mock_get_scheduler,
            patch(
                "local_deep_research.web.auth.decorators.db_manager"
            ) as mock_db,
        ):
            mock_db.connections = {"testuser": True}
            mock_get_scheduler.side_effect = Exception("Database error")

            with client.session_transaction() as sess:
                sess["username"] = "testuser"

            response = client.get("/api/scheduler/status")

            assert response.status_code == 500
            data = response.get_json()
            assert "error" in data

    def test_trigger_manual_run_unauthenticated(self, client):
        """Test manual run endpoint returns 401 when not authenticated."""
        response = client.post("/api/scheduler/run-now")

        assert response.status_code == 401
        data = response.get_json()
        assert "error" in data
        assert "authentication required" in data["error"].lower()

    def test_trigger_manual_run_success(self, client, app):
        """Test manual run endpoint triggers run successfully."""
        with (
            patch(
                "local_deep_research.research_scheduler.routes.get_document_scheduler"
            ) as mock_get_scheduler,
            patch(
                "local_deep_research.web.auth.decorators.db_manager"
            ) as mock_db,
        ):
            mock_db.connections = {"testuser": True}
            mock_scheduler = Mock()
            mock_scheduler.trigger_manual_run.return_value = (
                True,
                "Processing started",
            )
            mock_get_scheduler.return_value = mock_scheduler

            with client.session_transaction() as sess:
                sess["username"] = "testuser"

            response = client.post("/api/scheduler/run-now")

            assert response.status_code == 200
            data = response.get_json()
            assert "message" in data
            assert data["message"] == "Processing started"
            mock_scheduler.trigger_manual_run.assert_called_once_with(
                "testuser"
            )

    def test_trigger_manual_run_failure(self, client, app):
        """Test manual run endpoint handles failure."""
        with (
            patch(
                "local_deep_research.research_scheduler.routes.get_document_scheduler"
            ) as mock_get_scheduler,
            patch(
                "local_deep_research.web.auth.decorators.db_manager"
            ) as mock_db,
        ):
            mock_db.connections = {"testuser": True}
            mock_scheduler = Mock()
            mock_scheduler.trigger_manual_run.return_value = (
                False,
                "Already running",
            )
            mock_get_scheduler.return_value = mock_scheduler

            with client.session_transaction() as sess:
                sess["username"] = "testuser"

            response = client.post("/api/scheduler/run-now")

            assert response.status_code == 400
            data = response.get_json()
            assert "error" in data
            assert data["error"] == "Already running"

    def test_trigger_manual_run_error(self, client, app):
        """Test manual run endpoint handles exceptions."""
        with (
            patch(
                "local_deep_research.research_scheduler.routes.get_document_scheduler"
            ) as mock_get_scheduler,
            patch(
                "local_deep_research.web.auth.decorators.db_manager"
            ) as mock_db,
        ):
            mock_db.connections = {"testuser": True}
            mock_get_scheduler.side_effect = Exception("Scheduler error")

            with client.session_transaction() as sess:
                sess["username"] = "testuser"

            response = client.post("/api/scheduler/run-now")

            assert response.status_code == 500
            data = response.get_json()
            assert "error" in data
