from django.core.exceptions import ValidationError
from django.db.utils import IntegrityError
from django.test import TestCase

from apps.billboard.models import Line, Post
from apps.lyric.models import User


class LineModelTest(TestCase):
    def setUp(self):
        self.user = User.objects.create(email="a@b.cde")

    def test_line_is_related_to_post(self):
        mypost = Post.objects.create()
        line = Line(post=mypost, author=self.user, text="x")
        line.save()
        self.assertIn(line, mypost.lines.all())

    def test_cannot_save_null_post_lines(self):
        mypost = Post.objects.create()
        line = Line(post=mypost, author=self.user, text=None)
        with self.assertRaises(IntegrityError):
            line.save()

    def test_cannot_save_empty_post_lines(self):
        mypost = Post.objects.create()
        line = Line(post=mypost, author=self.user, text="")
        with self.assertRaises(ValidationError):
            line.full_clean()

    def test_duplicate_lines_are_invalid(self):
        mypost = Post.objects.create()
        Line.objects.create(post=mypost, author=self.user, text="jklol")
        with self.assertRaises(ValidationError):
            line = Line(post=mypost, author=self.user, text="jklol")
            line.full_clean()

    def test_still_can_save_same_line_to_different_posts(self):
        post1 = Post.objects.create()
        post2 = Post.objects.create()
        Line.objects.create(post=post1, author=self.user, text="nojk")
        line = Line(post=post2, author=self.user, text="nojk")
        line.full_clean()  # should not raise

class PostModelTest(TestCase):
        def setUp(self):
            self.user = User.objects.create(email="a@b.cde")

        def test_get_absolute_url(self):
            mypost = Post.objects.create()
            self.assertEqual(mypost.get_absolute_url(), f"/billboard/post/{mypost.id}/")

        def test_post_lines_order(self):
            post1 = Post.objects.create()
            line1 = Line.objects.create(post=post1, author=self.user, text="i1")
            line2 = Line.objects.create(post=post1, author=self.user, text="line 2")
            line3 = Line.objects.create(post=post1, author=self.user, text="3")
            self.assertEqual(
                list(post1.lines.all()),
                [line1, line2, line3],
            )

        def test_posts_can_have_owners(self):
            mypost = Post.objects.create(owner=self.user)
            self.assertIn(mypost, self.user.posts.all())

        def test_post_owner_is_optional(self):
            Post.objects.create()

        def test_post_title_is_explicit_field(self):
            post = Post.objects.create(title="first line")
            self.assertEqual(post.title, "first line")
