import datetime as dt
import json
from zoneinfo import ZoneInfo

import pytest
from django.core import management
from django.core.files.uploadedfile import SimpleUploadedFile
from django.utils.timezone import now
from django_scopes import scope, scopes_disabled
from lxml import etree

from pretalx.event.models import Event, Organiser, Team, TeamInvite
from pretalx.mail.models import MailTemplate
from pretalx.person.models import SpeakerInformation, SpeakerProfile, User
from pretalx.schedule.models import Availability, Room, TalkSlot
from pretalx.submission.models import (
    Answer,
    AnswerOption,
    Feedback,
    Question,
    QuestionVariant,
    Resource,
    Review,
    Submission,
    SubmissionType,
    SubmitterAccessCode,
    Tag,
    Track,
)
from pretalx.submission.models.question import QuestionRequired


@pytest.fixture(scope="session", autouse=True)
def collect_static(request):
    management.call_command("collectstatic", "--noinput", "--clear")


@pytest.fixture
def template_patch(monkeypatch):
    # Patch out template rendering for performance improvements
    monkeypatch.setattr(
        "django.template.backends.django.Template.render",
        lambda *args, **kwargs: "mocked template",
    )


@pytest.fixture
def organiser():
    with scopes_disabled():
        o = Organiser.objects.create(name="Super Organiser", slug="superorganiser")
        Team.objects.create(
            name="Organisers",
            organiser=o,
            can_create_events=True,
            can_change_teams=True,
            can_change_organiser_settings=True,
            can_change_event_settings=True,
            can_change_submissions=True,
        )
        Team.objects.create(
            name="Organisers and reviewers",
            organiser=o,
            can_create_events=True,
            can_change_teams=True,
            can_change_organiser_settings=True,
            can_change_event_settings=True,
            can_change_submissions=True,
            is_reviewer=True,
        )
        Team.objects.create(name="Reviewers", organiser=o, is_reviewer=True)
    return o


@pytest.fixture
def team(organiser):
    return organiser.teams.filter(is_reviewer=False).first()


@pytest.fixture
def reviewer_team(organiser):
    return organiser.teams.filter(
        is_reviewer=True, can_change_event_settings=False
    ).first()


@pytest.fixture
def other_organiser():
    with scopes_disabled():
        o = Organiser.objects.create(name="Different Organiser", slug="diffo")
        Team.objects.create(
            name="Organisers",
            organiser=o,
            can_create_events=True,
            can_change_teams=True,
            can_change_organiser_settings=True,
            can_change_event_settings=True,
            can_change_submissions=True,
        )
        Team.objects.create(
            name="Organisers and reviewers",
            organiser=o,
            can_create_events=True,
            can_change_teams=True,
            can_change_organiser_settings=True,
            can_change_event_settings=True,
            can_change_submissions=True,
            is_reviewer=True,
        )
        Team.objects.create(name="Reviewers", organiser=o, is_reviewer=True)
    return o


@pytest.fixture
def event(organiser):
    today = dt.date.today()
    with scopes_disabled():
        event = Event.objects.create(
            name="Fancy testevent",
            is_public=True,
            slug="test",
            email="orga@orga.org",
            date_from=today,
            date_to=today + dt.timedelta(days=3),
            organiser=organiser,
        )
        # exporting takes quite some time, so this speeds up our tests
        event.feature_flags["export_html_on_release"] = False
        event.save()
        for team in organiser.teams.all():
            team.limit_events.add(event)
    return event


@pytest.fixture
def other_event(other_organiser):
    with scopes_disabled():
        event = Event.objects.create(
            name="Boring testevent",
            is_public=True,
            slug="other",
            email="orga2@orga.org",
            date_from=dt.date.today() + dt.timedelta(days=1),
            date_to=dt.date.today() + dt.timedelta(days=1),
            organiser=other_organiser,
        )
        event.feature_flags["export_html_on_release"] = False
        event.save()
        for team in other_organiser.teams.all():
            team.limit_events.add(event)
    return event


@pytest.fixture
def multilingual_event(organiser):
    with scopes_disabled():
        today = dt.date.today()
        event = Event.objects.create(
            name="Fancy testevent",
            is_public=True,
            slug="test2",
            email="orga@orga.org",
            date_from=today,
            date_to=today + dt.timedelta(days=3),
            locale_array="en,de",
            organiser=organiser,
        )
        event.feature_flags["export_html_on_release"] = False
        event.save()
        for team in organiser.teams.all():
            team.limit_events.add(event)
    return event


@pytest.fixture
def resource(submission):
    f = SimpleUploadedFile("testresource.txt", b"a resource")
    with scope(event=submission.event):
        return Resource.objects.create(
            submission=submission, resource=f, description="Test resource"
        )


@pytest.fixture
def confirmed_resource(confirmed_submission):
    f = SimpleUploadedFile("confirmed_testresource.txt", b"a confirmed resource")
    return Resource.objects.create(
        submission=confirmed_submission,
        resource=f,
        description="Confirmed test resource",
    )


@pytest.fixture
def other_resource(submission):
    f = SimpleUploadedFile("testresource2.txt", b"another resource")
    with scope(event=submission.event):
        return Resource.objects.create(
            submission=submission, resource=f, description="Test resource 2"
        )


@pytest.fixture
def question(event):
    with scope(event=event):
        return Question.objects.create(
            event=event,
            question="How much do you like green, on a scale from 1-10?",
            variant=QuestionVariant.NUMBER,
            target="submission",
            question_required=QuestionRequired.OPTIONAL,
            contains_personal_data=False,
            position=1,
        )


@pytest.fixture
def question_required_always(event):
    with scope(event=event):
        return Question.objects.create(
            event=event,
            question="How much do you like green, on a scale from 1-10?",
            variant=QuestionVariant.NUMBER,
            target="submission",
            question_required=QuestionRequired.REQUIRED,
            contains_personal_data=False,
            position=1,
        )


@pytest.fixture
def question_required_after_option_before_deadline(event):
    with scope(event=event):
        date_of_deadline = dt.datetime.now().replace(tzinfo=event.tz) + dt.timedelta(
            weeks=4
        )
        return Question.objects.create(
            event=event,
            question="How much do you like green, on a scale from 1-10?",
            variant=QuestionVariant.NUMBER,
            target="submission",
            deadline=date_of_deadline,
            question_required=QuestionRequired.AFTER_DEADLINE,
            contains_personal_data=False,
            position=1,
        )


@pytest.fixture
def question_freeze_after_option_before_deadline_question_required_optional(event):
    with scope(event=event):
        date_of_freeze = dt.datetime.now().replace(tzinfo=event.tz) + dt.timedelta(
            weeks=4
        )
        return Question.objects.create(
            event=event,
            question="How much do you like green, on a scale from 1-10?",
            variant=QuestionVariant.NUMBER,
            target="submission",
            freeze_after=date_of_freeze,
            question_required=QuestionRequired.OPTIONAL,
            contains_personal_data=False,
            position=1,
        )


@pytest.fixture
def question_freeze_after_option_after_deadline_question_required_optional(event):
    with scope(event=event):
        date_of_freeze = dt.datetime.now().replace(tzinfo=event.tz) - dt.timedelta(
            weeks=4
        )
        return Question.objects.create(
            event=event,
            question="How much do you like green, on a scale from 1-10?",
            variant=QuestionVariant.NUMBER,
            target="submission",
            freeze_after=date_of_freeze,
            question_required=QuestionRequired.OPTIONAL,
            contains_personal_data=False,
            position=1,
        )


@pytest.fixture
def question_freeze_after_option_before_deadline_question_required_required(event):
    with scope(event=event):
        date_of_freeze = dt.datetime.now().replace(tzinfo=event.tz) + dt.timedelta(
            weeks=4
        )
        return Question.objects.create(
            event=event,
            question="How much do you like green, on a scale from 1-10?",
            variant=QuestionVariant.NUMBER,
            target="submission",
            freeze_after=date_of_freeze,
            question_required=QuestionRequired.REQUIRED,
            contains_personal_data=False,
            position=1,
        )


@pytest.fixture
def question_freeze_after_option_after_deadline_question_required_required(event):
    with scope(event=event):
        date_of_freeze = dt.datetime.now().replace(tzinfo=event.tz) - dt.timedelta(
            weeks=4
        )
        return Question.objects.create(
            event=event,
            question="How much do you like green, on a scale from 1-10?",
            variant=QuestionVariant.NUMBER,
            target="submission",
            freeze_after=date_of_freeze,
            question_required=QuestionRequired.REQUIRED,
            contains_personal_data=False,
            position=1,
        )


@pytest.fixture
def question_freeze_after_option_after_deadline(event):
    with scope(event=event):
        date_of_freeze = dt.datetime.now().replace(tzinfo=event.tz) - dt.timedelta(
            weeks=4
        )
        return Question.objects.create(
            event=event,
            question="How much do you like green, on a scale from 1-10?",
            variant=QuestionVariant.NUMBER,
            target="submission",
            freeze_after=date_of_freeze,
            contains_personal_data=False,
            position=1,
        )


@pytest.fixture
def question_freeze_after_option_before_deadline(event):
    with scope(event=event):
        date_of_freeze = dt.datetime.now().replace(tzinfo=event.tz) + dt.timedelta(
            weeks=4
        )
        return Question.objects.create(
            event=event,
            question="How much do you like green, on a scale from 1-10?",
            variant=QuestionVariant.NUMBER,
            target="submission",
            freeze_after=date_of_freeze,
            contains_personal_data=False,
            position=1,
        )


@pytest.fixture
def question_required_after_option_after_deadline(event):
    with scope(event=event):
        date_of_deadline = dt.datetime.now().replace(tzinfo=event.tz) - dt.timedelta(
            weeks=4
        )
        return Question.objects.create(
            event=event,
            question="How much do you like green, on a scale from 1-10?",
            variant=QuestionVariant.NUMBER,
            target="submission",
            deadline=date_of_deadline,
            question_required=QuestionRequired.AFTER_DEADLINE,
            contains_personal_data=False,
            position=1,
        )


@pytest.fixture
def inactive_question(event):
    with scope(event=event):
        return Question.objects.create(
            event=event,
            question="So, on a scale from 1–100, how much do you like red?",
            variant=QuestionVariant.NUMBER,
            target="submission",
            question_required=QuestionRequired.OPTIONAL,
            active=False,
            position=2,
        )


@pytest.fixture
def answer(event, submission, question):
    with scope(event=event):
        return Answer.objects.create(
            answer="11", submission=submission, question=question
        )


@pytest.fixture
def speaker_answer(event, submission, speaker_question):
    with scope(event=event):
        return Answer.objects.create(
            answer="11", person=submission.speakers.first(), question=speaker_question
        )


@pytest.fixture
def speaker_question(event):
    with scope(event=event):
        return Question.objects.create(
            event=event,
            question="What is your favourite color?",
            variant=QuestionVariant.STRING,
            target="speaker",
            question_required=QuestionRequired.OPTIONAL,
            position=3,
        )


@pytest.fixture
def review_question(event):
    with scope(event=event):
        return Question.objects.create(
            event=event,
            question="What is your favourite color?",
            variant=QuestionVariant.STRING,
            target="reviewer",
            question_required=QuestionRequired.REQUIRED,
            position=4,
        )


@pytest.fixture
def speaker_boolean_question(event):
    with scope(event=event):
        return Question.objects.create(
            event=event,
            question="Do you like green?",
            variant=QuestionVariant.BOOLEAN,
            target="speaker",
            question_required=QuestionRequired.OPTIONAL,
            position=5,
        )


@pytest.fixture
def boolean_question(event):
    with scope(event=event):
        return Question.objects.create(
            event=event,
            question="Do you like green?",
            variant=QuestionVariant.BOOLEAN,
            target="submission",
            question_required=QuestionRequired.OPTIONAL,
            position=6,
        )


@pytest.fixture
def file_question(event):
    with scope(event=event):
        return Question.objects.create(
            event=event,
            question="Please submit your paper.",
            variant=QuestionVariant.FILE,
            target="submission",
            question_required=QuestionRequired.OPTIONAL,
            position=7,
        )


@pytest.fixture
def speaker_file_question(event):
    with scope(event=event):
        return Question.objects.create(
            event=event,
            question="Please submit your CV.",
            variant=QuestionVariant.FILE,
            target="speaker",
            question_required=QuestionRequired.OPTIONAL,
            position=8,
        )


@pytest.fixture
def choice_question(event):
    with scope(event=event):
        question = Question.objects.create(
            event=event,
            question="How much do you like green?",
            variant=QuestionVariant.CHOICES,
            target="speaker",
            question_required=QuestionRequired.OPTIONAL,
            position=9,
        )
        for answer in ("very", "incredibly", "omggreen"):
            AnswerOption.objects.create(question=question, answer=answer)
    return question


@pytest.fixture
def answered_choice_question(choice_question, submission, speaker):
    with scope(event=submission.event):
        a = Answer.objects.create(
            submission=submission, question=choice_question, person=speaker
        )
        a.options.set([choice_question.options.first()])
        a.save()
    return choice_question


@pytest.fixture
def multiple_choice_question(event):
    with scope(event=event):
        question = Question.objects.create(
            event=event,
            question="Which colors other than green do you like?",
            variant=QuestionVariant.MULTIPLE,
            target="speaker",
            question_required=QuestionRequired.OPTIONAL,
            position=10,
        )
        for answer in ("yellow", "blue", "black"):
            AnswerOption.objects.create(question=question, answer=answer)
    return question


@pytest.fixture
def speaker_text_question(event):
    with scope(event=event):
        return Question.objects.create(
            event=event,
            question="Please elaborat on your like/dislike of green.",
            variant=QuestionVariant.TEXT,
            target="speaker",
            question_required=QuestionRequired.OPTIONAL,
            position=11,
        )


@pytest.fixture
def personal_question(submission):
    with scope(event=submission.event):
        return Question.objects.create(
            event=submission.event,
            target="submission",
            variant="boolean",
            question="Do you identify as a hacker?",
            contains_personal_data=True,
            position=12,
        )


@pytest.fixture
def impersonal_answer(question, speaker, submission):
    with scope(event=question.event):
        return Answer.objects.create(
            answer="True", submission=submission, person=speaker, question=question
        )


@pytest.fixture
def personal_answer(personal_question, speaker, submission):
    with scope(event=personal_question.event):
        return Answer.objects.create(
            answer="True",
            person=speaker,
            question=personal_question,
            submission=submission,
        )


@pytest.fixture
def user():
    with scopes_disabled():
        return User.objects.create_user(
            email="testuser@example.com", password="testpassw0rd!"
        )


@pytest.fixture
def administrator():
    with scopes_disabled():
        u = User.objects.create_superuser(
            email="testuser@examplecom", password="testpassw0rd!"
        )
        u.is_administrator = True
        u.save()
    return u


@pytest.fixture
def orga_user(event):
    with scopes_disabled():
        user = User.objects.create_user(
            password="orgapassw0rd",
            email="orgauser@orga.org",
            name="Orga User",
        )
        team = event.organiser.teams.filter(
            can_change_organiser_settings=True, is_reviewer=False
        ).first()
        team.members.add(user)
        team.save()
    return user


@pytest.fixture
def other_orga_user(event):
    with scopes_disabled():
        user = User.objects.create_user(
            password="orgapassw0rd", email="evilorgauser@orga.org"
        )
        team = event.organiser.teams.filter(
            can_change_organiser_settings=True, is_reviewer=False
        ).first()
        team.members.add(user)
        team.save()
    return user


@pytest.fixture
def review_user(organiser, event):
    with scopes_disabled():
        user = User.objects.create_user(
            password="reviewpassw0rd",
            email="reviewuser@orga.org",
            name="Review User",
        )
        if not event.organiser:
            event.organiser = organiser
            event.save()
        team, _ = event.organiser.teams.get_or_create(
            can_change_organiser_settings=False, is_reviewer=True
        )
        team.members.add(user)
        team.save()
    return user


@pytest.fixture
def other_review_user(event):
    with scopes_disabled():
        user = User.objects.create_user(
            password="reviewpassw0rd", email="evilreviewuser@orga.org"
        )
        team = event.organiser.teams.filter(
            can_change_organiser_settings=False, is_reviewer=True
        ).first()
        team.members.add(user)
        team.save()
    return user


@pytest.fixture
def orga_reviewer_user(event):
    with scopes_disabled():
        user = User.objects.create_user(
            password="orgapassw0rd", email="multiuser@orga.org"
        )
        team = event.organiser.teams.filter(
            can_change_organiser_settings=True, is_reviewer=True
        ).first()
        team.members.add(user)
        team.save()
    return user


@pytest.fixture
def orga_client(orga_user, client):
    client.force_login(orga_user)
    return client


@pytest.fixture
def review_client(review_user, client):
    client.force_login(review_user)
    return client


@pytest.fixture
def other_review_client(other_review_user, client):
    client.force_login(other_review_user)
    return client


@pytest.fixture
def administrator_client(administrator, client):
    client.force_login(administrator)
    return client


@pytest.fixture
def submission_type(event):
    with scope(event=event):
        return SubmissionType.objects.create(
            name="Workshop", event=event, default_duration=60
        )


@pytest.fixture
def default_submission_type(event):
    return event.cfp.default_type


@pytest.fixture
def speaker(event):
    with scopes_disabled():
        user = User.objects.create_user(
            password="speakerpwd1!", name="Jane Speaker", email="jane@speaker.org"
        )
    with scope(event=event):
        SpeakerProfile.objects.create(
            user=user, event=event, biography="Best speaker in the world."
        )
    return user


@pytest.fixture
def speaker_client(client, speaker):
    client.force_login(speaker)
    return client


@pytest.fixture
def other_speaker(event):
    with scopes_disabled():
        user = User.objects.create_user(
            email="speaker2@example.com", password="speakerpwd1!", name="Krümelmonster"
        )
    with scope(event=event):
        SpeakerProfile.objects.create(user=user, event=event, biography="COOKIIIIES!!")
    return user


@pytest.fixture
def other_speaker_client(client, other_speaker):
    client.force_login(other_speaker)
    return client


@pytest.fixture
def submission_data(event, submission_type):
    return {
        "title": "Lametta im Wandel der Zeiten",
        "submission_type": submission_type,
        "description": "Früher war es nämlich mehr. Und wir mussten es bügeln.",
        "abstract": "Ich habe Quellen!",
        "notes": "Und mein Enkel braucht auch noch ein Geschenk.",
        "internal_notes": "Ich habe gestern mit dem Redner telefoniert. -- slubby",
        "content_locale": "en",
        "event": event,
    }


@pytest.fixture
def submission(submission_data, speaker, event):
    with scope(event=event):
        sub = Submission.objects.create(**submission_data)
        sub.save()
        sub.speakers.add(speaker)
        return sub


@pytest.fixture
def other_submission(event, other_speaker):
    with scope(event=event):
        sub = Submission.objects.create(
            title="Albrecht Dürer. Sein Leben, seine Zeit",
            event=event,
            submission_type=event.cfp.default_type,
            description="1 guter Talk",
            abstract="Verstehste?",
            notes="I like cookies A LOT",
            content_locale="en",
        )
        sub.save()
        sub.speakers.add(other_speaker)
        return sub


@pytest.fixture
def accepted_submission(speaker, submission_data, event):
    with scope(event=event):
        sub = Submission.objects.create(**submission_data)
        sub.save()
        sub.speakers.add(speaker)
        sub.accept()
        return sub


@pytest.fixture
def other_accepted_submission(other_submission):
    with scope(event=other_submission.event):
        other_submission.accept()
        return other_submission


@pytest.fixture
def rejected_submission(submission_data, other_speaker, event):
    with scope(event=event):
        sub = Submission.objects.create(**submission_data)
        sub.save()
        sub.speakers.add(other_speaker)
        sub.reject()
        return sub


@pytest.fixture
def confirmed_submission(submission_data, speaker, event):
    with scope(event=event):
        sub = Submission.objects.create(**submission_data)
        sub.save()
        sub.speakers.add(speaker)
        sub.accept()
        sub.confirm()
        return sub


@pytest.fixture
def other_confirmed_submission(other_accepted_submission, event):
    with scope(event=event):
        other_accepted_submission.confirm()
        return other_accepted_submission


@pytest.fixture
def canceled_submission(submission_data, speaker, event):
    with scope(event=event):
        sub = Submission.objects.create(**submission_data)
        sub.save()
        sub.speakers.add(speaker)
        sub.cancel(force=True)
        return sub


@pytest.fixture
def withdrawn_submission(submission_data, speaker, event):
    with scope(event=event):
        sub = Submission.objects.create(**submission_data)
        sub.save()
        sub.speakers.add(speaker)
        sub.withdraw(force=True)
        return sub


@pytest.fixture
def deleted_submission(event, submission_data, other_speaker):
    with scope(event=event):
        sub = Submission.objects.create(**submission_data)
        sub.speakers.add(other_speaker)
        sub.remove(force=True)
        return sub


@pytest.fixture
def invitation(event):
    with scope(event=event):
        team = event.organiser.teams.filter(
            can_change_organiser_settings=True, is_reviewer=False
        ).first()
        return TeamInvite.objects.create(
            team=team, token="testtoken", email="some@test.mail"
        )


@pytest.fixture
def mail_template(event):
    with scope(event=event):
        return MailTemplate.objects.create(
            event=event,
            subject="Some Mail",
            text="Whee mail content!",
            reply_to="orga@orga.org",
        )


@pytest.fixture(scope="function")
def mail(mail_template, speaker, event):
    with scope(event=event):
        return mail_template.to_mail(speaker, event)


@pytest.fixture(scope="function")
def other_mail(mail_template, event, speaker):
    with scope(event=event):
        return mail_template.to_mail(speaker, event)


@pytest.fixture
def sent_mail(mail_template, speaker, event):
    with scope(event=event):
        mail = mail_template.to_mail(speaker, event)
        mail.send()
        return mail


@pytest.fixture
def room(event):
    with scope(event=event):
        return Room.objects.create(
            event=event,
            name="Testroom",
            description="A fancy room",
            position=2,
            capacity=50,
        )


@pytest.fixture
def room_availability(event, room, availability):
    with scope(event=event):
        availability.room = room
        availability.save()
        return availability


@pytest.fixture
def other_room(event):
    with scope(event=event):
        return Room.objects.create(
            event=event,
            name="Second Testroom",
            description="A less fancy room",
            position=1,
            capacity=10,
        )


@pytest.fixture
def availability(event):
    with scope(event=event):
        return Availability(
            event=event,
            start=dt.datetime.combine(
                event.date_from, dt.time.min, tzinfo=ZoneInfo("UTC")
            ),
            end=dt.datetime.combine(event.date_to, dt.time.max, tzinfo=ZoneInfo("UTC")),
        )


@pytest.fixture
def schedule(event):
    with scope(event=event):
        event.release_schedule("🍪 Version")
        return event.current_schedule


@pytest.fixture
def slot(confirmed_submission, room, schedule):
    with scope(event=room.event):
        TalkSlot.objects.update_or_create(
            submission=confirmed_submission,
            schedule=room.event.wip_schedule,
            defaults={"is_visible": True},
        )
        TalkSlot.objects.update_or_create(
            submission=confirmed_submission,
            schedule=schedule,
            defaults={"is_visible": True},
        )
        slots = TalkSlot.objects.filter(submission=confirmed_submission)
        slots.update(
            start=room.event.datetime_from,
            end=room.event.datetime_from + dt.timedelta(minutes=60),
            room=room,
        )
        return slots.get(schedule=schedule)


@pytest.fixture
def unreleased_slot(confirmed_submission, room):
    with scope(event=room.event):
        schedule = confirmed_submission.event.wip_schedule
        slot = schedule.talks.filter(submission=confirmed_submission)
        slot.update(
            start=room.event.datetime_from,
            end=room.event.datetime_from + dt.timedelta(minutes=30),
            room=room,
            schedule=schedule,
            is_visible=True,
        )
        return slot.first()


@pytest.fixture
def past_slot(other_confirmed_submission, room, schedule, speaker):
    with scope(event=room.event):
        slot = (
            other_confirmed_submission.slots.filter(schedule=schedule).first()
            or other_confirmed_submission.slots.first()
        )
        slot.start = now() - dt.timedelta(minutes=60)
        slot.end = now() - dt.timedelta(minutes=30)
        slot.room = room
        slot.schedule = schedule
        slot.is_visible = True
        slot.save()
        return slot


@pytest.fixture
def break_slot(room, schedule):
    with scope(event=schedule.event):
        TalkSlot.objects.create(
            description="Break",
            schedule=schedule.event.wip_schedule,
        )
        slot = TalkSlot.objects.create(
            description="Break",
            schedule=schedule,
            is_visible=True,
        )
        slots = TalkSlot.objects.filter(submission__isnull=True)
        slots.update(
            start=room.event.datetime_from + dt.timedelta(minutes=90),
            end=room.event.datetime_from + dt.timedelta(minutes=120),
            room=room,
        )
        return slot


@pytest.fixture
def canceled_talk(past_slot):
    with scope(event=past_slot.submission.event):
        past_slot.submission.cancel(force=True)
        past_slot.submission.event.wip_schedule.freeze("vcanceled")
        return past_slot


@pytest.fixture
def feedback(past_slot):
    with scope(event=past_slot.submission.event):
        return Feedback.objects.create(talk=past_slot.submission, review="I liked it!")


@pytest.fixture
def other_slot(other_confirmed_submission, room, schedule):
    with scope(event=room.event):
        return TalkSlot.objects.create(
            start=room.event.datetime_from + dt.timedelta(minutes=60),
            end=room.event.datetime_from + dt.timedelta(minutes=90),
            submission=other_confirmed_submission,
            room=room,
            schedule=schedule,
            is_visible=True,
        )


@pytest.fixture
def schedule_schema_xml():
    with open("tests/fixtures/schedule.xsd") as xsd:
        source = xsd.read()
    schema = etree.XML(source)
    return etree.XMLSchema(schema)


@pytest.fixture
def schedule_schema_json():
    with open("tests/fixtures/schedule.json") as js:
        source = json.load(js)
    return source


@pytest.fixture
def review(submission, review_user):
    with scope(event=submission.event):
        return Review.objects.create(
            score=1, submission=submission, user=review_user, text="Looks great!"
        )


@pytest.fixture
def other_review(other_submission, other_review_user):
    with scope(event=other_submission.event):
        return Review.objects.create(
            score=0,
            submission=other_submission,
            user=other_review_user,
            text="Looks horrible!",
        )


@pytest.fixture
def information(event):
    with scope(event=event):
        return SpeakerInformation.objects.create(
            event=event, title="Information title", text="Important information"
        )


@pytest.fixture
def track(event):
    with scope(event=event):
        event.feature_flags["use_tracks"] = True
        event.save()
        return Track.objects.create(name="Test Track", color="00ff00", event=event)


@pytest.fixture
def other_track(event):
    with scope(event=event):
        event.feature_flags["use_tracks"] = True
        event.save()
        return Track.objects.create(
            name="Second Test Track", color="ff0000", event=event
        )


@pytest.fixture
def access_code(event):
    with scope(event=event):
        return SubmitterAccessCode.objects.create(event=event)


@pytest.fixture
def tag(event):
    return Tag.objects.create(tag="testtag", event=event)
