from datetime import datetime
from typing import List, Optional
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy import (
    Integer,
    String,
    Text,
    Boolean,
    DateTime,
    ForeignKey,
    Column,
    func,
)
from shared.db.base import Base  # whatever your Base is
# from .author import Author  # make sure imports resolve
# from ..app.blog.calendars.model import Calendar

class Tag(Base):
    __tablename__ = "tags"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    ghost_id: Mapped[str] = mapped_column(String(64), index=True, unique=True, nullable=False)

    slug: Mapped[str] = mapped_column(String(191), index=True, nullable=False)
    name: Mapped[str] = mapped_column(String(255), nullable=False)

    description: Mapped[Optional[str]] = mapped_column(Text())
    visibility: Mapped[str] = mapped_column(String(32), default="public", nullable=False)
    feature_image: Mapped[Optional[str]] = mapped_column(Text())

    meta_title: Mapped[Optional[str]] = mapped_column(String(300))
    meta_description: Mapped[Optional[str]] = mapped_column(Text())

    created_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
    updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
    deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))

    # NEW: posts relationship is now direct Post objects via PostTag
    posts: Mapped[List["Post"]] = relationship(
        "Post",
        secondary="post_tags",
        primaryjoin="Tag.id==post_tags.c.tag_id",
        secondaryjoin="Post.id==post_tags.c.post_id",
        back_populates="tags",
        order_by="PostTag.sort_order",
    )


class Post(Base):
    __tablename__ = "posts"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    ghost_id: Mapped[str] = mapped_column(String(64), index=True, unique=True, nullable=False)
    uuid: Mapped[str] = mapped_column(String(64), unique=True, nullable=False)
    slug: Mapped[str] = mapped_column(String(191), index=True, nullable=False)

    title: Mapped[str] = mapped_column(String(500), nullable=False)

    html: Mapped[Optional[str]] = mapped_column(Text())
    plaintext: Mapped[Optional[str]] = mapped_column(Text())
    mobiledoc: Mapped[Optional[str]] = mapped_column(Text())
    lexical: Mapped[Optional[str]] = mapped_column(Text())

    feature_image: Mapped[Optional[str]] = mapped_column(Text())
    feature_image_alt: Mapped[Optional[str]] = mapped_column(Text())
    feature_image_caption: Mapped[Optional[str]] = mapped_column(Text())

    excerpt: Mapped[Optional[str]] = mapped_column(Text())
    custom_excerpt: Mapped[Optional[str]] = mapped_column(Text())

    visibility: Mapped[str] = mapped_column(String(32), default="public", nullable=False)
    status: Mapped[str] = mapped_column(String(32), default="draft", nullable=False)
    featured: Mapped[bool] = mapped_column(Boolean(), default=False, nullable=False)
    is_page: Mapped[bool] = mapped_column(Boolean(), default=False, nullable=False)
    email_only: Mapped[bool] = mapped_column(Boolean(), default=False, nullable=False)

    canonical_url: Mapped[Optional[str]] = mapped_column(Text())
    meta_title: Mapped[Optional[str]] = mapped_column(String(500))
    meta_description: Mapped[Optional[str]] = mapped_column(Text())
    og_image: Mapped[Optional[str]] = mapped_column(Text())
    og_title: Mapped[Optional[str]] = mapped_column(String(500))
    og_description: Mapped[Optional[str]] = mapped_column(Text())
    twitter_image: Mapped[Optional[str]] = mapped_column(Text())
    twitter_title: Mapped[Optional[str]] = mapped_column(String(500))
    twitter_description: Mapped[Optional[str]] = mapped_column(Text())
    custom_template: Mapped[Optional[str]] = mapped_column(String(191))

    reading_time: Mapped[Optional[int]] = mapped_column(Integer())
    comment_id: Mapped[Optional[str]] = mapped_column(String(191))

    published_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
    updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
    created_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
    deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))

    user_id: Mapped[Optional[int]] = mapped_column(
        Integer, ForeignKey("users.id", ondelete="SET NULL"), index=True
    )
    publish_requested: Mapped[bool] = mapped_column(Boolean(), default=False, server_default="false", nullable=False)

    primary_author_id: Mapped[Optional[int]] = mapped_column(
        Integer, ForeignKey("authors.id", ondelete="SET NULL")
    )
    primary_tag_id: Mapped[Optional[int]] = mapped_column(
        Integer, ForeignKey("tags.id", ondelete="SET NULL")
    )

    primary_author: Mapped[Optional["Author"]] = relationship(
        "Author", foreign_keys=[primary_author_id]
    )
    primary_tag: Mapped[Optional[Tag]] = relationship(
        "Tag", foreign_keys=[primary_tag_id]
    )
    user: Mapped[Optional["User"]] = relationship(
        "User", foreign_keys=[user_id]
    )

    # AUTHORS RELATIONSHIP (many-to-many via post_authors)
    authors: Mapped[List["Author"]] = relationship(
        "Author",
        secondary="post_authors",
        primaryjoin="Post.id==post_authors.c.post_id",
        secondaryjoin="Author.id==post_authors.c.author_id",
        back_populates="posts",
        order_by="PostAuthor.sort_order",
    )

    # TAGS RELATIONSHIP (many-to-many via post_tags)
    tags: Mapped[List[Tag]] = relationship(
        "Tag",
        secondary="post_tags",
        primaryjoin="Post.id==post_tags.c.post_id",
        secondaryjoin="Tag.id==post_tags.c.tag_id",
        back_populates="posts",
        order_by="PostTag.sort_order",
    )
    likes: Mapped[List["PostLike"]] = relationship(
        "PostLike",
        back_populates="post",
        cascade="all, delete-orphan",
        passive_deletes=True,
    )

class Author(Base):
    __tablename__ = "authors"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    ghost_id: Mapped[str] = mapped_column(String(64), index=True, unique=True, nullable=False)

    slug: Mapped[str] = mapped_column(String(191), index=True, nullable=False)
    name: Mapped[str] = mapped_column(String(255), nullable=False)
    email: Mapped[Optional[str]] = mapped_column(String(255))

    profile_image: Mapped[Optional[str]] = mapped_column(Text())
    cover_image: Mapped[Optional[str]] = mapped_column(Text())
    bio: Mapped[Optional[str]] = mapped_column(Text())
    website: Mapped[Optional[str]] = mapped_column(Text())
    location: Mapped[Optional[str]] = mapped_column(Text())
    facebook: Mapped[Optional[str]] = mapped_column(Text())
    twitter: Mapped[Optional[str]] = mapped_column(Text())

    created_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
    updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
    deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))

    # backref to posts via post_authors
    posts: Mapped[List[Post]] = relationship(
        "Post",
        secondary="post_authors",
        primaryjoin="Author.id==post_authors.c.author_id",
        secondaryjoin="Post.id==post_authors.c.post_id",
        back_populates="authors",
        order_by="PostAuthor.sort_order",
    )

class PostAuthor(Base):
    __tablename__ = "post_authors"

    post_id: Mapped[int] = mapped_column(
        ForeignKey("posts.id", ondelete="CASCADE"),
        primary_key=True,
    )
    author_id: Mapped[int] = mapped_column(
        ForeignKey("authors.id", ondelete="CASCADE"),
        primary_key=True,
    )
    sort_order: Mapped[int] = mapped_column(Integer, default=0, nullable=False)


class PostTag(Base):
    __tablename__ = "post_tags"

    post_id: Mapped[int] = mapped_column(
        ForeignKey("posts.id", ondelete="CASCADE"),
        primary_key=True,
    )
    tag_id: Mapped[int] = mapped_column(
        ForeignKey("tags.id", ondelete="CASCADE"),
        primary_key=True,
    )
    sort_order: Mapped[int] = mapped_column(Integer, default=0, nullable=False)


class PostLike(Base):
    __tablename__ = "post_likes"

    id = Column(Integer, primary_key=True, autoincrement=True)
    user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
    post_id: Mapped[int] = mapped_column(ForeignKey("posts.id", ondelete="CASCADE"), nullable=False)

    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=func.now())
    updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=func.now())
    deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))

    post: Mapped["Post"] = relationship("Post", back_populates="likes", foreign_keys=[post_id])
    user = relationship("User", back_populates="liked_posts")
