from datetime import datetime, timedelta

import pytest
from rest_framework.test import APIClient

from django.contrib.auth.models import User
from django.core.files.uploadedfile import SimpleUploadedFile
from program.models import (
    FundingCategory,
    Host,
    Image,
    License,
    RRule,
    Schedule,
    Show,
    TimeSlot,
    Type,
)
from program.tests.factories import (
    CommonUserFactory,
    FundingCategoryFactory,
    HostFactory,
    ImageFactory,
    LicenseFactory,
    RRuleFactory,
    ScheduleFactory,
    ShowFactory,
    TimeslotFactory,
    TypeFactory,
)


def assert_data(response, data) -> None:
    if "schedule" in data:
        for key, value in data["schedule"].items():
            assert response.data[key] == value
    else:
        for key, value in data.items():
            if key == "password":
                continue
            assert response.data[key] == value


@pytest.fixture
def host() -> Host:
    return HostFactory()


@pytest.fixture
def image_file() -> SimpleUploadedFile:
    return SimpleUploadedFile("image.png", open("program/tests/data/image.png", "rb").read())


@pytest.fixture
def image(image_file) -> Image:
    return ImageFactory(image=image_file)


@pytest.fixture
def owned_image(image_file, common_user1) -> Image:
    return ImageFactory(image=image_file, owner=common_user1)


@pytest.fixture
def public_domain_license() -> License:
    return LicenseFactory()


@pytest.fixture
def owned_licensed_image(image_file, common_user1, public_domain_license) -> Image:
    return ImageFactory(image=image_file, owner=common_user1, license=LicenseFactory())


@pytest.fixture
def api_client() -> APIClient:
    """Unauthenticated API client"""

    return APIClient()


@pytest.fixture
def admin_api_client(api_client, admin_user) -> APIClient:
    """Authenticated admin user (superuser) API client"""

    api_client.force_authenticate(admin_user)
    yield api_client
    api_client.force_authenticate()


@pytest.fixture
def common_user1() -> User:
    return CommonUserFactory()


@pytest.fixture
def common_user2() -> User:
    return CommonUserFactory()


@pytest.fixture
def common_api_client1(api_client, common_user1) -> APIClient:
    """Authenticated common user 1 API client"""

    api_client.force_authenticate(common_user1)
    yield api_client
    api_client.force_authenticate()


@pytest.fixture
def common_api_client2(api_client, common_user2) -> APIClient:
    """Authenticated common user 2 API client"""

    api_client.force_authenticate(common_user2)
    yield api_client
    api_client.force_authenticate()


@pytest.fixture
def once_rrule() -> RRule:
    return RRuleFactory(freq=0)


@pytest.fixture
def show() -> Show:
    return ShowFactory()


@pytest.fixture
def owned_show(common_user1):
    show = ShowFactory()

    show.owners.set([common_user1])
    show.save()

    return show


@pytest.fixture
def owned_show_once_timeslot(common_user1, show, once_schedule) -> TimeSlot:
    show.owners.set([common_user1])
    show.save()

    timeslot = TimeslotFactory(schedule=once_schedule)

    return timeslot


@pytest.fixture
def once_timeslot(once_schedule) -> TimeSlot:
    return TimeslotFactory(schedule=once_schedule)


@pytest.fixture
def once_schedule(once_rrule, show) -> Schedule:
    start = datetime.now()
    end = start + timedelta(hours=1)

    return ScheduleFactory(
        end_time=end.strftime("%H:%M:%S"),
        first_date=start.strftime("%Y-%m-%d"),
        rrule=once_rrule,
        show=show,
        start_time=start.strftime("%H:%M:%S"),
    )


@pytest.fixture
def funding_category() -> FundingCategory:
    return FundingCategoryFactory()


@pytest.fixture
def type_() -> Type:
    return TypeFactory()