# #region Test.OrchestratorValidation [C:3] [TYPE Module] [SEMANTICS test, translate, validation, preconditions]
# @BRIEF Tests for orchestrator_validation.py — validate_job_preconditions.
# @RELATION BINDS_TO -> [validate_job_preconditions]
# @TEST_CONTRACT: validate_job_preconditions -> None | raises ValueError on precondition failure
# @TEST_EDGE: draft_status_fails
# @TEST_EDGE: missing_target_table
# @TEST_EDGE: missing_provider_id
# @TEST_EDGE: missing_translation_column
# @TEST_EDGE: no_accepted_preview_session

import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent / "src"))

import os
os.environ.setdefault("SECRET_KEY", "test-secret-key-for-testing")
os.environ.setdefault("DATABASE_URL", "sqlite:///:memory:")
os.environ.setdefault("AUTH_DATABASE_URL", "sqlite:///:memory:")

from unittest.mock import MagicMock, patch

import pytest

from src.plugins.translate.orchestrator_validation import validate_job_preconditions


class TestValidateJobPreconditions:
    """validate_job_preconditions — precondition checks."""

    def _make_job(self, overrides: dict | None = None) -> MagicMock:
        """Create a mock job with valid defaults."""
        job = MagicMock()
        job.id = "job-1"
        job.status = "READY"
        job.target_table = "target_table"
        job.provider_id = "provider-1"
        job.translation_column = "name"
        job.source_datasource_id = None
        if overrides:
            for k, v in overrides.items():
                setattr(job, k, v)
        return job

    def test_ready_passes_with_source_datasource(self):
        """READY job with source datasource passes without preview session."""
        job = self._make_job({"source_datasource_id": "ds-1"})
        db = MagicMock()
        # Should not query preview sessions
        validate_job_preconditions(job, db)
        db.query.assert_not_called()

    def test_ready_no_datasource_needs_preview(self):
        """READY job without datasource and no accepted preview fails."""
        job = self._make_job({"source_datasource_id": None})
        db = MagicMock()
        db.query.return_value.filter.return_value.order_by.return_value.first.return_value = None
        with pytest.raises(ValueError, match="no accepted preview session"):
            validate_job_preconditions(job, db)

    def test_ready_no_datasource_with_preview_passes(self):
        """READY job without datasource but with accepted preview passes."""
        job = self._make_job({"source_datasource_id": None})
        db = MagicMock()
        mock_session = MagicMock()
        mock_session.status = "APPLIED"
        db.query.return_value.filter.return_value.order_by.return_value.first.return_value = mock_session
        validate_job_preconditions(job, db)

    def test_draft_status_fails(self):
        """DRAFT job raises ValueError."""
        job = self._make_job({"status": "DRAFT"})
        db = MagicMock()
        with pytest.raises(ValueError, match="Cannot run job.*DRAFT"):
            validate_job_preconditions(job, db)

    def test_missing_target_table(self):
        """Job with no target_table raises ValueError."""
        job = self._make_job({"target_table": None})
        db = MagicMock()
        with pytest.raises(ValueError, match="no target table"):
            validate_job_preconditions(job, db)

    def test_missing_provider_id(self):
        """Job with no provider_id raises ValueError."""
        job = self._make_job({"provider_id": None})
        db = MagicMock()
        with pytest.raises(ValueError, match="no LLM provider"):
            validate_job_preconditions(job, db)

    def test_missing_translation_column(self):
        """Job with no translation_column raises ValueError."""
        job = self._make_job({"translation_column": None})
        db = MagicMock()
        with pytest.raises(ValueError, match="no translation column"):
            validate_job_preconditions(job, db)

    def test_scheduled_run_skips_preview_check(self):
        """Scheduled run (is_scheduled=True) skips preview session check."""
        job = self._make_job({"source_datasource_id": None})
        db = MagicMock()
        # Would fail without is_scheduled=True, but should pass with it
        validate_job_preconditions(job, db, is_scheduled=True)
        db.query.assert_not_called()

    def test_validation_order_draft_checked_first(self):
        """DRAFT is checked before target_table."""
        job = self._make_job({"status": "DRAFT", "target_table": None})
        db = MagicMock()
        with pytest.raises(ValueError, match="DRAFT"):
            validate_job_preconditions(job, db)
# #endregion Test.OrchestratorValidation
