"""Slice B.3 · transition_to_judging + announce_winners.

Asserts:
* OPEN → JUDGING via service.
* JUDGING challenges accept winner announcement.
* Non-OPEN challenges are rejected.
"""
from __future__ import annotations

from datetime import timedelta

import pytest
from django.contrib.auth import get_user_model
from django.utils import timezone

from apps.core.permissions.roles import UserRole
from apps.smehub.showcasing import services
from apps.smehub.showcasing.models import (
    ChallengeRubricSection,
    ChallengeScoringRubric,
    InnovationChallenge,
)

User = get_user_model()
pytestmark = pytest.mark.django_db


@pytest.fixture
def admin():
    return User.objects.create_user(
        email="adm-judge@example.com", password="x",
        is_superuser=True, is_staff=True, role=UserRole.SYSTEM_ADMIN,
    )


@pytest.fixture
def organiser():
    return User.objects.create_user(
        email="org-judge@example.com", password="x", role=UserRole.SME_ADMIN, is_staff=True,
    )


@pytest.fixture
def challenge(organiser):
    ch = services.create_challenge(
        organiser=organiser,
        title="J-Challenge",
        application_deadline=timezone.now() + timedelta(days=7),
    )
    # Add a single complete-rubric section so publish doesn't bail out.
    rubric = ch.rubric
    ChallengeRubricSection.objects.create(
        rubric=rubric, title="Innovation", weight="1.0", max_marks=10, order=0,
    )
    return ch


def test_transition_to_judging_rejects_draft(challenge, admin):
    """Draft challenges can't go to judging without first being published."""
    assert challenge.status == InnovationChallenge.Status.DRAFT
    with pytest.raises(services.ShowcasingStateError):
        services.transition_to_judging(challenge, by_user=admin)


def test_transition_to_judging_succeeds_on_open(challenge, organiser, admin):
    services.publish_challenge(challenge, by_user=organiser)
    challenge.refresh_from_db()
    assert challenge.status == InnovationChallenge.Status.OPEN

    services.transition_to_judging(challenge, by_user=admin)
    challenge.refresh_from_db()
    assert challenge.status == InnovationChallenge.Status.JUDGING


def test_announce_winners_accepts_judging(challenge, organiser, admin):
    services.publish_challenge(challenge, by_user=organiser)
    services.transition_to_judging(challenge, by_user=admin)
    services.announce_winners(challenge, winners=[], by_user=admin)
    challenge.refresh_from_db()
    assert challenge.status == InnovationChallenge.Status.ANNOUNCED


def test_transition_to_judging_idempotent_rejection(challenge, organiser, admin):
    """A JUDGING challenge can't transition to JUDGING again."""
    services.publish_challenge(challenge, by_user=organiser)
    services.transition_to_judging(challenge, by_user=admin)
    with pytest.raises(services.ShowcasingStateError):
        services.transition_to_judging(challenge, by_user=admin)
