"""Tests for the campaign start_date scheduling gate on test execution.

Block 3 fix: `Campaign.start_date` was persisted and displayed but never
actually enforced — a test belonging to a campaign scheduled for the future
could still be started immediately. `start_execution` now blocks this.
"""

from datetime import datetime, timedelta

import pytest

from app.domain.errors import BusinessRuleViolation
from app.models.campaign import Campaign, CampaignTest
from app.models.enums import TestState
from app.models.technique import Technique
from app.models.test import Test
from app.services.test_workflow_service import start_execution


def _seed_test_in_campaign(db, owner_id, start_date):
    tech = Technique(mitre_id="T1059.003", name="Windows Command Shell", tactic="execution", platforms=["windows"])
    db.add(tech)
    db.flush()

    campaign = Campaign(name="Scheduled Campaign", type="custom", status="active", created_by=owner_id, start_date=start_date)
    db.add(campaign)
    db.flush()

    test = Test(technique_id=tech.id, name="Scheduled test", state=TestState.draft, created_by=owner_id)
    db.add(test)
    db.flush()

    db.add(CampaignTest(campaign_id=campaign.id, test_id=test.id, order_index=0))
    db.commit()
    db.refresh(test)
    return test


def test_start_execution_blocked_before_campaign_start_date(db, red_tech_user):
    future = datetime.utcnow() + timedelta(days=7)
    test = _seed_test_in_campaign(db, red_tech_user.id, future)

    with pytest.raises(BusinessRuleViolation):
        start_execution(db, test, red_tech_user)


def test_start_execution_allowed_after_campaign_start_date(db, red_tech_user):
    past = datetime.utcnow() - timedelta(days=1)
    test = _seed_test_in_campaign(db, red_tech_user.id, past)

    result = start_execution(db, test, red_tech_user)

    assert result.state == TestState.red_executing


def test_start_execution_allowed_for_standalone_test(db, red_tech_user):
    """A test with no campaign at all is never gated by this check."""
    tech = Technique(mitre_id="T1059.004", name="Unix Shell", tactic="execution", platforms=["linux"])
    db.add(tech)
    db.flush()
    test = Test(technique_id=tech.id, name="Standalone test", state=TestState.draft, created_by=red_tech_user.id)
    db.add(test)
    db.commit()
    db.refresh(test)

    result = start_execution(db, test, red_tech_user)

    assert result.state == TestState.red_executing


def test_start_execution_allowed_when_campaign_has_no_start_date(db, red_tech_user):
    test = _seed_test_in_campaign(db, red_tech_user.id, None)

    result = start_execution(db, test, red_tech_user)

    assert result.state == TestState.red_executing
