import django
import pytest
from django.conf import settings
from pathlib import Path

from django.test import Client

from tests.lib.helper.user import user_viewset_permission


def pytest_configure():
    settings.configure(
        BASE_DIR=Path(__file__).resolve().parent.parent,
        SECRET_KEY="django-testing",
        DEBUG=True,
        ALLOWED_HOSTS=[],
        INSTALLED_APPS=[
            "django.contrib.admin",
            "django.contrib.auth",
            "django.contrib.contenttypes",
            "django.contrib.sessions",
            "django.contrib.messages",
            "django.contrib.staticfiles",
            "django_bootstrap5",
            "crispy_forms",
            "crispy_bootstrap5",
            "polymorphic",
            "ordered_model",
            "django_tables2",
            "django_object_detail",
            "crud_views.apps.CrudViewsConfig",
            "django_fsm",
            "crud_views_workflow.apps.CrudViewsWorkflowConfig",
            "crud_views_polymorphic.apps.CrudViewsPolymorphicConfig",
            "tests.test1.app",
        ],
        MIDDLEWARE=[
            "django.middleware.security.SecurityMiddleware",
            "django.contrib.sessions.middleware.SessionMiddleware",
            "django.middleware.common.CommonMiddleware",
            "django.middleware.csrf.CsrfViewMiddleware",
            "django.contrib.auth.middleware.AuthenticationMiddleware",
            "django.contrib.messages.middleware.MessageMiddleware",
            "django.middleware.clickjacking.XFrameOptionsMiddleware",
        ],
        ROOT_URLCONF="tests.test1.project.urls",
        TEMPLATES=[
            {
                "BACKEND": "django.template.backends.django.DjangoTemplates",
                "DIRS": [],
                "APP_DIRS": True,
                "OPTIONS": {
                    "context_processors": [
                        "django.template.context_processors.debug",
                        "django.template.context_processors.request",
                        "django.contrib.auth.context_processors.auth",
                        "django.contrib.messages.context_processors.messages",
                        "crud_views.lib.context_processor.crud_views_context",
                    ],
                },
            },
        ],
        DATABASES={
            "default": {
                "ENGINE": "django.db.backends.sqlite3",
                "NAME": ":memory:",
            }
        },
        # Internationalization
        LANGUAGE_CODE="en-us",
        TIME_ZONE="UTC",
        USE_I18N=True,
        USE_TZ=True,
        STATIC_URL="static/",
        DEFAULT_AUTO_FIELD="django.db.models.BigAutoField",
        # Django ViewSet configuration
        CRUD_VIEWS_EXTENDS="app/crud_views.html",
        CRUD_VIEWS_MANAGE_VIEWS_ENABLED="yes",
        # crispy
        CRISPY_TEMPLATE_PACK="bootstrap5",
        CRISPY_ALLOWED_TEMPLATE_PACKS="bootstrap5",
        # django_tables2
        DJANGO_TABLES2_TEMPLATE="django_tables2/bootstrap5.html",
    )

    django.setup()


@pytest.fixture
def user_a():
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_a", password="password")
    return user


@pytest.fixture
def cv_author():
    from tests.test1.app.views import cv_author as ret

    return ret


@pytest.fixture
def user_author_view(cv_author):
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_author_view", password="password")

    user_viewset_permission(user, cv_author, "view")

    return user


@pytest.fixture
def client() -> Client:
    return Client()


@pytest.fixture
def client_user_author_view(client, user_author_view) -> Client:
    client.force_login(user_author_view)
    return client


@pytest.fixture
def user_author_change(cv_author):
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_author_change", password="password")

    user_viewset_permission(user, cv_author, "change")

    return user


@pytest.fixture
def user_author_delete(cv_author):
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_author_delete", password="password")

    user_viewset_permission(user, cv_author, "delete")

    return user


@pytest.fixture
def author_douglas_adams():
    from tests.test1.app.models import Author

    return Author.objects.create(first_name="Douglas", last_name="Adams")


@pytest.fixture
def user_author_add(cv_author):
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_author_add", password="password")

    user_viewset_permission(user, cv_author, "add")

    return user


@pytest.fixture
def client_user_author_change(client, user_author_change) -> Client:
    client.force_login(user_author_change)
    return client


@pytest.fixture
def client_user_author_delete(client, user_author_delete) -> Client:
    client.force_login(user_author_delete)
    return client


@pytest.fixture
def client_user_author_add(client, user_author_add) -> Client:
    client.force_login(user_author_add)
    return client


@pytest.fixture
def client_user_a(client, user_a) -> Client:
    client.force_login(user_a)
    return client


@pytest.fixture
def author_terry_pratchett():
    from tests.test1.app.models import Author

    return Author.objects.create(first_name="Terry", last_name="Pratchett")


# --- Publisher fixtures ---


@pytest.fixture
def cv_publisher():
    from tests.test1.app.views import cv_publisher as ret

    return ret


@pytest.fixture
def publisher_penguin():
    from tests.test1.app.models import Publisher

    return Publisher.objects.create(name="Penguin")


@pytest.fixture
def publisher_harpercollins():
    from tests.test1.app.models import Publisher

    return Publisher.objects.create(name="HarperCollins")


@pytest.fixture
def user_publisher_view(cv_publisher):
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_publisher_view", password="password")
    user_viewset_permission(user, cv_publisher, "view")
    return user


@pytest.fixture
def client_user_publisher_view(client, user_publisher_view) -> Client:
    client.force_login(user_publisher_view)
    return client


@pytest.fixture
def user_publisher_add(cv_publisher):
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_publisher_add", password="password")
    user_viewset_permission(user, cv_publisher, "add")
    return user


@pytest.fixture
def client_user_publisher_add(client, user_publisher_add) -> Client:
    client.force_login(user_publisher_add)
    return client


@pytest.fixture
def user_publisher_change(cv_publisher):
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_publisher_change", password="password")
    user_viewset_permission(user, cv_publisher, "change")
    return user


@pytest.fixture
def client_user_publisher_change(client, user_publisher_change) -> Client:
    client.force_login(user_publisher_change)
    return client


@pytest.fixture
def user_publisher_delete(cv_publisher):
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_publisher_delete", password="password")
    user_viewset_permission(user, cv_publisher, "delete")
    return user


@pytest.fixture
def client_user_publisher_delete(client, user_publisher_delete) -> Client:
    client.force_login(user_publisher_delete)
    return client


# --- Book fixtures ---


@pytest.fixture
def cv_book():
    from tests.test1.app.views import cv_book as ret

    return ret


@pytest.fixture
def book_hitchhiker(publisher_penguin):
    from tests.test1.app.models import Book

    return Book.objects.create(title="The Hitchhiker's Guide to the Galaxy", publisher=publisher_penguin)


@pytest.fixture
def book_other_publisher(publisher_harpercollins):
    from tests.test1.app.models import Book

    return Book.objects.create(title="Other Book", publisher=publisher_harpercollins)


@pytest.fixture
def user_book_view(cv_book):
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_book_view", password="password")
    user_viewset_permission(user, cv_book, "view")
    return user


@pytest.fixture
def client_user_book_view(client, user_book_view) -> Client:
    client.force_login(user_book_view)
    return client


@pytest.fixture
def user_book_add(cv_book):
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_book_add", password="password")
    user_viewset_permission(user, cv_book, "add")
    return user


@pytest.fixture
def client_user_book_add(client, user_book_add) -> Client:
    client.force_login(user_book_add)
    return client


@pytest.fixture
def user_book_change(cv_book):
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_book_change", password="password")
    user_viewset_permission(user, cv_book, "change")
    return user


@pytest.fixture
def client_user_book_change(client, user_book_change) -> Client:
    client.force_login(user_book_change)
    return client


@pytest.fixture
def user_book_delete(cv_book):
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_book_delete", password="password")
    user_viewset_permission(user, cv_book, "delete")
    return user


@pytest.fixture
def client_user_book_delete(client, user_book_delete) -> Client:
    client.force_login(user_book_delete)
    return client


# --- Vehicle (polymorphic) fixtures ---


@pytest.fixture
def cv_vehicle():
    from tests.test1.app.views import cv_vehicle as ret

    return ret


@pytest.fixture
def car_sedan():
    from tests.test1.app.models import Car

    return Car.objects.create(name="Sedan", doors=4)


@pytest.fixture
def truck_semi():
    from tests.test1.app.models import Truck

    return Truck.objects.create(name="Semi", payload_tons=20)


@pytest.fixture
def user_vehicle_view(cv_vehicle):
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_vehicle_view", password="password")
    user_viewset_permission(user, cv_vehicle, "view")
    return user


@pytest.fixture
def client_user_vehicle_view(client, user_vehicle_view) -> Client:
    client.force_login(user_vehicle_view)
    return client


@pytest.fixture
def user_vehicle_add(cv_vehicle):
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_vehicle_add", password="password")
    user_viewset_permission(user, cv_vehicle, "add")
    return user


@pytest.fixture
def client_user_vehicle_add(client, user_vehicle_add) -> Client:
    client.force_login(user_vehicle_add)
    return client


@pytest.fixture
def user_vehicle_change(cv_vehicle):
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_vehicle_change", password="password")
    user_viewset_permission(user, cv_vehicle, "change")
    return user


@pytest.fixture
def client_user_vehicle_change(client, user_vehicle_change) -> Client:
    client.force_login(user_vehicle_change)
    return client


@pytest.fixture
def user_vehicle_delete(cv_vehicle):
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_vehicle_delete", password="password")
    user_viewset_permission(user, cv_vehicle, "delete")
    return user


@pytest.fixture
def client_user_vehicle_delete(client, user_vehicle_delete) -> Client:
    client.force_login(user_vehicle_delete)
    return client


# --- Campaign (workflow) fixtures ---


@pytest.fixture
def cv_campaign():
    from tests.test1.app.views import cv_campaign as ret

    return ret


@pytest.fixture
def campaign_new():
    from tests.test1.app.models import Campaign

    return Campaign.objects.create(name="Test Campaign")


@pytest.fixture
def campaign_active():
    from tests.test1.app.models import Campaign

    campaign = Campaign.objects.create(name="Active Campaign")
    campaign.wf_activate(by=None)
    campaign.save()
    return campaign


@pytest.fixture
def campaign_success():
    from tests.test1.app.models import Campaign

    campaign = Campaign.objects.create(name="Success Campaign")
    campaign.wf_activate(by=None)
    campaign.save()
    campaign.wf_done(by=None)
    campaign.save()
    return campaign


@pytest.fixture
def campaign_canceled():
    from tests.test1.app.models import Campaign

    campaign = Campaign.objects.create(name="Canceled Campaign")
    campaign.wf_cancel_new(by=None, comment="Canceled in test")
    campaign.save()
    return campaign


@pytest.fixture
def user_campaign_change(cv_campaign):
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_campaign_change", password="password")
    user_viewset_permission(user, cv_campaign, "change")
    return user


@pytest.fixture
def client_user_campaign_change(client, user_campaign_change) -> Client:
    client.force_login(user_campaign_change)
    return client


@pytest.fixture
def user_campaign_view(cv_campaign):
    from django.contrib.auth.models import User

    user = User.objects.create_user(username="user_campaign_view", password="password")
    user_viewset_permission(user, cv_campaign, "view")
    return user


@pytest.fixture
def client_user_campaign_view(client, user_campaign_view) -> Client:
    client.force_login(user_campaign_view)
    return client
