from sqlalchemy import (
    Column,
    BigInteger,
    DateTime,
    Integer,
    String,
    func,
    Boolean,
    ForeignKey,
    Text,
    SmallInteger,
)
from sqlalchemy.orm import relationship, backref

from app import db
from app.persistence.model import UserModel
from app.persistence.model.post_category_model import PostCategoryModel
from core.domains.community.entity.community_entity import (
    PostEntity,
    FeedEntity,
    FeedUserEntity,
    FeedCommentEntity,
    FeedCommentUserEntity,
    NoticeEntity,
    AdminFeedEntity,
    AdminFeedCommentEntity,
)


class PostModel(db.Model):
    __tablename__ = "posts"

    id = Column(
        BigInteger().with_variant(Integer, "sqlite"),
        primary_key=True,
        nullable=False,
        autoincrement=True,
    )
    user_id = Column(
        BigInteger().with_variant(Integer, "sqlite"),
        ForeignKey(UserModel.id),
        nullable=False,
        index=True,
    )
    title = Column(String(100), nullable=True)
    body = Column(Text, nullable=False)
    is_deleted = Column(Boolean, nullable=False, default=False)
    like_count = Column(Integer, nullable=False, default=0)
    post_category_id = Column(
        SmallInteger, ForeignKey(PostCategoryModel.id), nullable=False, index=True,
    )
    last_user_action = Column(String(20), nullable=False)
    last_user_action_at = Column(DateTime(), server_default=func.now(), nullable=False)
    last_admin_action = Column(String(20), nullable=True)
    last_admin_action_at = Column(DateTime(), nullable=True)
    created_at = Column(DateTime(), server_default=func.now(), nullable=False)
    updated_at = Column(
        DateTime(), server_default=func.now(), onupdate=func.now(), nullable=False
    )

    comments = relationship("CommentModel", backref=backref("posts"), uselist=True)
    post_like_statuses = relationship(
        "PostLikeStatusModel", backref=backref("posts"), uselist=True
    )
    post_attachments = relationship(
        "PostAttachmentModel", backref=backref("posts"), uselist=True
    )
    post_category = relationship(
        "PostCategoryModel", backref=backref("posts"), uselist=False
    )

    # user relationship
    user = relationship("UserModel", backref=backref("posts"), uselist=False)

    def to_entity(self) -> PostEntity:
        post_attachment_list = list()
        if self.post_attachments:
            for post_attachment in self.post_attachments:
                if not post_attachment.is_available:
                    continue

                post_attachment_list.append(post_attachment.to_entity())
        else:
            post_attachment_list = None

        return PostEntity(
            id=self.id,
            user_id=self.user_id,
            title=self.title,
            body=self.body,
            is_deleted=self.is_deleted,
            like_count=self.like_count,
            post_category_id=self.post_category_id,
            last_user_action=self.last_user_action,
            last_user_action_at=self.last_user_action_at,
            last_admin_action=self.last_admin_action,
            last_admin_action_at=self.last_admin_action_at,
            created_at=self.created_at,
            updated_at=self.updated_at,
            comments=[comment.to_entity() for comment in self.comments]
            if self.comments
            else None,
            post_like_statuses=[
                post_like_status.to_entity()
                for post_like_status in self.post_like_statuses
            ]
            if self.post_like_statuses
            else None,
            post_attachments=post_attachment_list,
            post_category=self.post_category.to_entity(),
        )

    def to_feed_entity(self, reader_id: int) -> FeedEntity:
        created_date = self.created_at.strftime("%y.%m.%d")
        feed_comment_entities = list()

        for comment in self.comments:
            feed_comment_entities.append(
                FeedCommentEntity(
                    id=comment.id,
                    body=comment.body,
                    is_liked=True if comment.comment_like_statuses else False,
                    is_owner=True if comment.user_id == self.user_id else False,
                    is_writer=True if comment.user_id == reader_id else False,
                    like_count=comment.like_count,
                    plant_nickname=comment.user.plant_profile.name,
                    user=FeedCommentUserEntity(
                        id=comment.user.id,
                        nickname=comment.user.nickname,
                        profile_img=comment.user.user_profile.path
                        if comment.user.user_profile
                        else None,
                    ),
                )
            )

        return FeedEntity(
            id=self.id,
            plant_nickname=self.user.plant_profile.name,
            created_date=created_date,
            category=self.post_category.name,
            title=self.title,
            body=self.body,
            is_liked=True if self.post_like_statuses else False,
            like_count=self.like_count,
            is_owner=True if self.user_id == reader_id else False,
            comment_count=len(self.comments) if self.comments else 0,
            created_at=self.created_at,
            updated_at=self.updated_at,
            post_attachments=[
                post_attachment.to_entity() for post_attachment in self.post_attachments
            ]
            if self.post_attachments
            else None,
            user=FeedUserEntity(
                id=self.user.id,
                nickname=self.user.nickname,
                profile_img=self.user.user_profile.path
                if self.user.user_profile
                else None,
            ),
            comments=feed_comment_entities if feed_comment_entities else None,
        )

    def to_notice_entity(self) -> NoticeEntity:
        created_date = self.created_at.strftime("%y.%m.%d")
        post_attachment_list = list()
        if self.post_attachments:
            for post_attachment in self.post_attachments:
                if not post_attachment.is_available:
                    continue

                post_attachment_list.append(post_attachment.to_entity())
        else:
            post_attachment_list = None

        return NoticeEntity(
            id=self.id,
            title=self.title,
            created_date=created_date,
            body=self.body,
            created_at=self.created_at,
            updated_at=self.updated_at,
            post_attachments=post_attachment_list,
        )

    def to_admin_feed_entity(self) -> AdminFeedEntity:
        created_date = self.created_at.strftime("%y.%m.%d")
        feed_comment_entities = list()

        comment_count = 0
        for comment in self.comments:
            if comment.is_deleted:
                continue

            comment_count += 1
            feed_comment_entities.append(
                AdminFeedCommentEntity(
                    id=comment.id,
                    body=comment.body,
                    like_count=comment.like_count,
                    plant_nickname=comment.user.plant_profile.name,
                    user=FeedCommentUserEntity(
                        id=comment.user.id,
                        nickname=comment.user.nickname,
                        profile_img=comment.user.user_profile.path
                        if comment.user.user_profile
                        else None,
                    ),
                )
            )

        post_attachments = list()
        if self.post_attachments:
            for post_attachment in self.post_attachments:
                if not post_attachment.is_available:
                    continue

                post_attachments.append(post_attachment.to_entity())

        return AdminFeedEntity(
            id=self.id,
            plant_nickname=self.user.plant_profile.name,
            created_date=created_date,
            category=self.post_category.name,
            title=self.title,
            body=self.body,
            like_count=self.like_count,
            comment_count=comment_count,
            create_diff_day=None,
            created_at=self.created_at,
            updated_at=self.updated_at,
            post_attachments=post_attachments if post_attachments else None,
            user=FeedUserEntity(
                id=self.user.id,
                nickname=self.user.nickname,
                profile_img=self.user.user_profile.path
                if self.user.user_profile
                else None,
            ),
            comments=feed_comment_entities if feed_comment_entities else None,
        )
