from snek.system.service import BaseService


class ChannelMemberService(BaseService):

    mapper_name = "channel_member"

    async def mark_as_read(self, channel_uid, user_uid):
        channel_member = await self.get(channel_uid=channel_uid, user_uid=user_uid)
        channel_member["new_count"] = 0
        return await self.save(channel_member)

    async def get_user_uids(self, channel_uid):
        async for model in self.mapper.query(
            "SELECT user_uid FROM channel_member WHERE channel_uid=:channel_uid",
            {"channel_uid": channel_uid},
        ):
            yield model["user_uid"]

    async def create(
        self,
        channel_uid,
        user_uid,
        is_moderator=False,
        is_read_only=False,
        is_muted=False,
        is_banned=False,
    ):
        model = await self.get(channel_uid=channel_uid, user_uid=user_uid)
        if model:
            if model["is_banned"]:
                return False
            return model
        model = await self.new()
        channel = await self.services.channel.get(uid=channel_uid)
        model["label"] = channel["label"]
        model["channel_uid"] = channel_uid
        model["user_uid"] = user_uid
        model["is_moderator"] = is_moderator
        model["is_read_only"] = is_read_only
        model["is_muted"] = is_muted
        model["is_banned"] = is_banned
        if await self.save(model):
            return model
        raise Exception(f"Failed to create channel member: {model.errors}.")

    async def get_dm(self, from_user, to_user):
        async for model in self.query(
            "SELECT channel_member.* FROM channel_member INNER JOIN channel ON (channel.uid = channel_member.channel_uid and channel.tag = 'dm') INNER JOIN channel_member AS channel_member2 ON(channel_member2.channel_uid = channel.uid AND channel_member2.user_uid = :to_user)   WHERE channel_member.user_uid=:from_user ",
            {"from_user": from_user, "to_user": to_user},
        ):
            return model
        if not from_user == to_user:
            return None
        async for model in self.query(
            "SELECT channel_member.* FROM channel_member INNER JOIN channel ON (channel.uid = channel_member.channel_uid and channel.tag = 'dm') LEFT JOIN channel_member AS channel_member2 ON(channel_member2.channel_uid = NULL AND channel_member2.user_uid = NULL)   WHERE channel_member.user_uid=:from_user ",
            {"from_user": from_user, "to_user": to_user},
        ):

            return model

    async def get_other_dm_user(self, channel_uid, user_uid):
        channel_member = await self.get(channel_uid=channel_uid, user_uid=user_uid)
        channel = await self.services.channel.get(uid=channel_member["channel_uid"])
        if channel["tag"] != "dm":
            return None
        async for model in self.services.channel_member.find(channel_uid=channel_uid):
            if model["uid"] != channel_member["uid"]:
                return await self.services.user.get(uid=model["user_uid"])

    async def create_dm(self, channel_uid, from_user_uid, to_user_uid):
        result = await self.create(channel_uid, from_user_uid)
        await self.create(channel_uid, to_user_uid)
        return result
