from django.db.models import Q

import graphene
from graphql import GraphQLError
from graphene_django import DjangoObjectType

from website.users.schema import UserType

from .models import Link, Vote


class LinkType(DjangoObjectType):
    class Meta:
        model = Link


class VoteType(DjangoObjectType):
    class Meta:
        model = Vote


class Query(graphene.ObjectType):
    links = graphene.List(LinkType, search=graphene.String(), first=graphene.Int(), skip=graphene.Int())
    votes = graphene.List(VoteType)

    def resolve_links(self, info, search=None, first=None, skip=None, **kwargs):
        queryset = Link.objects.all()

        if search:
            queryset = Link.objects.filter(Q(url__icontains=search) | Q(description__icontains=search))
        if skip:
            queryset = queryset[skip:]
        if first:
            queryset = queryset[:first]

        return queryset

    def resolve_votes(self, info, **kwargs):
        return Vote.objects.all()


class CreateLink(graphene.Mutation):
    id  = graphene.Int()
    url = graphene.String()
    description = graphene.String()
    posted_by   = graphene.Field(UserType)

    class Arguments:
        """Data that can be sent to the server."""
        url = graphene.String()
        description = graphene.String()

    def mutate(self, info, url, description):
        user = info.context.user
        link = Link.objects.create(url=url, description=description, posted_by=user)

        return CreateLink(
            id=link.id,
            url=link.url,
            description=link.description,
            posted_by=link.posted_by
        )


class CreateVote(graphene.Mutation):
    user = graphene.Field(UserType)
    link = graphene.Field(LinkType)

    class Arguments:
        link_id = graphene.Int()

    def mutate(self, info, link_id):
        user = info.context.user
        if user.is_anonymous:
            raise GraphQLError('You must be logged to vote!')

        link = Link.objects.filter(id=link_id).first()
        if not link:
            raise Exception('Invalid Link!')

        Vote.objects.create(user=user, link=link)
        return CreateVote(user=user, link=link)


class Mutation(graphene.ObjectType):
    create_link = CreateLink.Field()
    create_vote = CreateVote.Field()
