from datetime import time, timedelta
import itertools
import logging

from django.conf import settings
from django.contrib.auth.models import User
from django.test import RequestFactory

import pytest
from model_bakery import baker

from aircox import models
from aircox.test import Interface


req_factory = RequestFactory()
"""Request Factory used among different tests."""


settings.ALLOWED_HOSTS = list(settings.ALLOWED_HOSTS) + [
    "sub.server.org",
    "server.org",
]


@pytest.fixture
def staff_user():
    return baker.make(User, is_active=True, is_staff=True)


@pytest.fixture
def logger():
    logger = Interface(logging, {"info": None, "debug": None, "error": None, "warning": None})
    return logger


@pytest.fixture
def station():
    return baker.make(
        models.Station,
        hosts="server.org",
        audio_streams="stream 1\nstream 2",
        default=True,
    )


@pytest.fixture
def sub_station():
    """Non-default station."""
    return baker.make(models.Station, hosts="sub.server.org", default=False)


@pytest.fixture
def stations(station, sub_station):
    return [station, sub_station]


@pytest.fixture
def programs(stations):
    items = list(
        itertools.chain(
            *(
                baker.make(
                    models.Program,
                    station=station,
                    cover=None,
                    status=models.Program.STATUS_PUBLISHED,
                    _quantity=2,
                )
                for station in stations
            )
        )
    )
    for item in items:
        item.save()
    return items


@pytest.fixture
def program(programs):
    return programs[0]


@pytest.fixture
def sched_initials(programs):
    # use concrete class; timezone is provided in order to ensure DST
    items = [
        baker.prepare(
            models.Schedule,
            program=program,
            time=time(16, 00),
            timezone="Europe/Brussels",
        )
        for program in programs
    ]
    models.Schedule.objects.bulk_create(items)
    return items


@pytest.fixture
def sched_reruns(sched_initials):
    # use concrete class
    items = [
        baker.prepare(
            models.Schedule,
            initial=initial,
            program=initial.program,
            date=initial.date,
            time=(initial.start + timedelta(hours=1)).time(),
        )
        for initial in sched_initials
    ]
    models.Schedule.objects.bulk_create(items)
    return items


@pytest.fixture
def schedules(sched_initials, sched_reruns):
    return sched_initials + sched_reruns


@pytest.fixture
def episodes(programs):
    return [baker.make(models.Episode, parent=program, cover=None) for program in programs]


@pytest.fixture
def episode(episodes):
    return episodes[0]


@pytest.fixture
def podcasts(episodes):
    items = []
    for episode in episodes:
        sounds = baker.prepare(
            models.Sound,
            episode=episode,
            program=episode.program,
            is_public=True,
            _quantity=2,
        )
        for i, sound in enumerate(sounds):
            sound.file = f"test_sound_{episode.pk}_{i}.mp3"
        items += sounds
    return items


@pytest.fixture
def sound(program):
    return baker.make(models.Sound, file="tmp/test.wav", program=program)


@pytest.fixture
def tracks(episode, sound):
    items = [baker.prepare(models.Track, episode=episode, position=i, timestamp=i * 60) for i in range(0, 3)]
    items += [baker.prepare(models.Track, sound=sound, position=i, timestamp=i * 60) for i in range(0, 3)]
    models.Track.objects.bulk_create(items)
    return items


@pytest.fixture
def user():
    return User.objects.create_user(username="user1", password="bar")
