from datetime import datetime
from sqlalchemy import (
    BigInteger, String, Integer, Boolean,
    DateTime, ForeignKey, Text, Enum as SAEnum,
    UniqueConstraint
)
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
import enum


class Base(DeclarativeBase):
    pass

class BotType(str, enum.Enum):
    communication = "communication"
    download      = "download"
    decor         = "decor"
    buttons       = "buttons"
    factory       = "factory"
    transcoding   = "transcoding"
    translation   = "translation"
    ai            = "ai"


class TransferStatus(str, enum.Enum):
    pending         = "pending"
    waiting_confirm = "waiting_confirm"
    completed       = "completed"
    rejected        = "rejected"
    cancelled       = "cancelled"


class ChannelDisplayType(str, enum.Enum):
    buttons = "buttons"
    text    = "text"

class User(Base):
    __tablename__ = "users"

    id             : Mapped[int]      = mapped_column(BigInteger, primary_key=True)
    username       : Mapped[str|None] = mapped_column(String(64),  nullable=True)
    first_name     : Mapped[str]      = mapped_column(String(128))
    is_banned      : Mapped[bool]     = mapped_column(Boolean, default=False)
    is_blocked_bot : Mapped[bool]     = mapped_column(Boolean, default=False)
    is_dev         : Mapped[bool]     = mapped_column(Boolean, default=False)
    is_admin       : Mapped[bool]     = mapped_column(Boolean, default=False)
    last_active    : Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
    joined_at      : Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)

    bots               : Mapped[list["Bot"]]         = relationship("Bot", back_populates="owner", foreign_keys="Bot.owner_id")
    sent_transfers     : Mapped[list["BotTransfer"]] = relationship("BotTransfer", back_populates="sender",   foreign_keys="BotTransfer.sender_id")
    received_transfers : Mapped[list["BotTransfer"]] = relationship("BotTransfer", back_populates="receiver", foreign_keys="BotTransfer.receiver_id")

class Bot(Base):
    __tablename__ = "bots"

    id          : Mapped[int]      = mapped_column(Integer, primary_key=True, autoincrement=True)
    token       : Mapped[str]      = mapped_column(String(128), unique=True, nullable=False)
    username    : Mapped[str]      = mapped_column(String(64),  nullable=False)
    bot_name    : Mapped[str]      = mapped_column(String(128), nullable=False)
    bot_type    : Mapped[BotType]  = mapped_column(SAEnum(BotType), nullable=False)
    owner_id    : Mapped[int]      = mapped_column(BigInteger, ForeignKey("users.id"), nullable=False)
    is_active   : Mapped[bool]     = mapped_column(Boolean, default=True)
    is_stopped  : Mapped[bool]     = mapped_column(Boolean, default=False)
    webhook_set : Mapped[bool]     = mapped_column(Boolean, default=False)
    created_at  : Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)

    created_by_bot_id : Mapped[int|None] = mapped_column(Integer, nullable=True)
    is_paid     : Mapped[bool]     = mapped_column(Boolean, default=False)

    owner        : Mapped["User"]              = relationship("User", back_populates="bots", foreign_keys=[owner_id])
    transfers    : Mapped[list["BotTransfer"]] = relationship("BotTransfer", back_populates="bot")
    subscription : Mapped["BotSubscription|None"] = relationship("BotSubscription", back_populates="bot", uselist=False)

class BotTransfer(Base):
    __tablename__ = "bot_transfers"

    id          : Mapped[int]            = mapped_column(Integer, primary_key=True, autoincrement=True)
    bot_id      : Mapped[int]            = mapped_column(Integer, ForeignKey("bots.id"), nullable=False)
    sender_id   : Mapped[int]            = mapped_column(BigInteger, ForeignKey("users.id"), nullable=False)
    receiver_id : Mapped[int]            = mapped_column(BigInteger, ForeignKey("users.id"), nullable=False)
    status      : Mapped[TransferStatus] = mapped_column(SAEnum(TransferStatus), default=TransferStatus.pending)
    created_at  : Mapped[datetime]       = mapped_column(DateTime, default=datetime.utcnow)
    updated_at  : Mapped[datetime]       = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    bot      : Mapped["Bot"]  = relationship("Bot",  back_populates="transfers")
    sender   : Mapped["User"] = relationship("User", back_populates="sent_transfers",     foreign_keys=[sender_id])
    receiver : Mapped["User"] = relationship("User", back_populates="received_transfers", foreign_keys=[receiver_id])

class FactorySettings(Base):
    __tablename__ = "factory_settings"

    id                    : Mapped[int]      = mapped_column(Integer, primary_key=True, autoincrement=True)

    is_open               : Mapped[bool]     = mapped_column(Boolean, default=True)
    closed_message        : Mapped[str|None] = mapped_column(Text, nullable=True)
    open_message          : Mapped[str|None] = mapped_column(Text, nullable=True)

    max_bots_per_user     : Mapped[int]      = mapped_column(Integer, default=3)
    notify_new_users      : Mapped[bool]     = mapped_column(Boolean, default=True)
    notify_blocked        : Mapped[bool]     = mapped_column(Boolean, default=True)
    notify_funded_sub     : Mapped[bool]     = mapped_column(Boolean, default=True)

    bots_channel_url      : Mapped[str]      = mapped_column(String(256), default="https://t.me/placeholder_bots_channel")
    source_channel_url    : Mapped[str]      = mapped_column(String(256), default="https://t.me/placeholder_source_channel")
    developer_url         : Mapped[str]      = mapped_column(String(256), default="https://t.me/placeholder_developer")

    start_template        : Mapped[str|None] = mapped_column(Text, nullable=True)
    start_template_entities : Mapped[str|None] = mapped_column(Text, nullable=True)
    token_template        : Mapped[str|None] = mapped_column(Text, nullable=True)
    token_template_entities : Mapped[str|None] = mapped_column(Text, nullable=True)

    cobots_sub_enabled    : Mapped[bool]     = mapped_column(Boolean, default=True)
    cobots_funded_enabled : Mapped[bool]     = mapped_column(Boolean, default=True)
    cobots_fund_notify    : Mapped[bool]     = mapped_column(Boolean, default=True)
    cobots_maker_rights   : Mapped[bool]     = mapped_column(Boolean, default=True)

    updated_at            : Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    help_text             : Mapped[str|None] = mapped_column(Text, nullable=True)

class ButtonSetting(Base):
    __tablename__ = "button_settings"

    id         : Mapped[int]      = mapped_column(Integer, primary_key=True, autoincrement=True)
    button_key : Mapped[str]      = mapped_column(String(64),  unique=True, nullable=False)
    label      : Mapped[str]      = mapped_column(String(128), nullable=False)
    emoji      : Mapped[str|None] = mapped_column(String(32),  nullable=True)
    color      : Mapped[str]      = mapped_column(String(16),  default="default")
    is_visible : Mapped[bool]     = mapped_column(Boolean, default=True)
    url        : Mapped[str|None] = mapped_column(String(256), nullable=True)
    updated_at : Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    custom_emoji_id : Mapped[str|None] = mapped_column(String(64), nullable=True)

class MandatoryChannel(Base):
    __tablename__ = "mandatory_channels"

    id               : Mapped[int]                = mapped_column(Integer, primary_key=True, autoincrement=True)
    channel_id       : Mapped[int]                = mapped_column(BigInteger, nullable=False, unique=True)
    channel_username : Mapped[str|None]           = mapped_column(String(128), nullable=True)
    channel_title    : Mapped[str]                = mapped_column(String(256), nullable=False)
    invite_link      : Mapped[str|None]           = mapped_column(String(256), nullable=True)
    display_type     : Mapped[ChannelDisplayType] = mapped_column(SAEnum(ChannelDisplayType), default=ChannelDisplayType.buttons)
    is_active        : Mapped[bool]               = mapped_column(Boolean, default=True)
    added_at         : Mapped[datetime]           = mapped_column(DateTime, default=datetime.utcnow)

class FundedChannel(Base):
    __tablename__ = "funded_channels"

    id               : Mapped[int]                = mapped_column(Integer, primary_key=True, autoincrement=True)
    channel_id       : Mapped[int]                = mapped_column(BigInteger, nullable=False, unique=True)
    channel_username : Mapped[str|None]           = mapped_column(String(128), nullable=True)
    channel_title    : Mapped[str]                = mapped_column(String(256), nullable=False)
    invite_link      : Mapped[str|None]           = mapped_column(String(256), nullable=True)
    display_type     : Mapped[ChannelDisplayType] = mapped_column(SAEnum(ChannelDisplayType), default=ChannelDisplayType.buttons)
    target_count     : Mapped[int]                = mapped_column(Integer, nullable=False)
    current_count    : Mapped[int]                = mapped_column(Integer, default=0)
    is_active        : Mapped[bool]               = mapped_column(Boolean, default=True)
    added_at         : Mapped[datetime]           = mapped_column(DateTime, default=datetime.utcnow)
    completed_at     : Mapped[datetime|None]      = mapped_column(DateTime, nullable=True)

class FundedSubscription(Base):
    __tablename__ = "funded_subscriptions"

    id                : Mapped[int]      = mapped_column(Integer, primary_key=True, autoincrement=True)
    funded_channel_id : Mapped[int]      = mapped_column(Integer, ForeignKey("funded_channels.id"), nullable=False)
    user_id           : Mapped[int]      = mapped_column(BigInteger, ForeignKey("users.id"), nullable=False)
    subscribed_at     : Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)

    __table_args__ = (UniqueConstraint("funded_channel_id", "user_id"),)


class CobotMandatoryChannel(Base):
    __tablename__ = "cobot_mandatory_channels"

    id               : Mapped[int]                = mapped_column(Integer, primary_key=True, autoincrement=True)
    channel_id       : Mapped[int]                = mapped_column(BigInteger, nullable=False, unique=True)
    channel_username : Mapped[str|None]           = mapped_column(String(128), nullable=True)
    channel_title    : Mapped[str]                = mapped_column(String(256), nullable=False)
    invite_link      : Mapped[str|None]           = mapped_column(String(256), nullable=True)
    display_type     : Mapped[ChannelDisplayType] = mapped_column(SAEnum(ChannelDisplayType), default=ChannelDisplayType.buttons)
    is_active        : Mapped[bool]               = mapped_column(Boolean, default=True)
    added_at         : Mapped[datetime]           = mapped_column(DateTime, default=datetime.utcnow)

class CobotFundedChannel(Base):
    __tablename__ = "cobot_funded_channels"

    id               : Mapped[int]                = mapped_column(Integer, primary_key=True, autoincrement=True)
    channel_id       : Mapped[int]                = mapped_column(BigInteger, nullable=False, unique=True)
    channel_username : Mapped[str|None]           = mapped_column(String(128), nullable=True)
    channel_title    : Mapped[str]                = mapped_column(String(256), nullable=False)
    invite_link      : Mapped[str|None]           = mapped_column(String(256), nullable=True)
    display_type     : Mapped[ChannelDisplayType] = mapped_column(SAEnum(ChannelDisplayType), default=ChannelDisplayType.buttons)
    target_count     : Mapped[int]                = mapped_column(Integer, nullable=False)
    current_count    : Mapped[int]                = mapped_column(Integer, default=0)
    is_active        : Mapped[bool]               = mapped_column(Boolean, default=True)
    added_at         : Mapped[datetime]           = mapped_column(DateTime, default=datetime.utcnow)
    completed_at     : Mapped[datetime|None]      = mapped_column(DateTime, nullable=True)


class CobotFundedSubscription(Base):
    __tablename__ = "cobot_funded_subscriptions"

    id                      : Mapped[int]      = mapped_column(Integer, primary_key=True, autoincrement=True)
    cobot_funded_channel_id : Mapped[int]      = mapped_column(Integer, ForeignKey("cobot_funded_channels.id"), nullable=False)
    user_id                 : Mapped[int]      = mapped_column(BigInteger, nullable=False)
    bot_id                  : Mapped[int]      = mapped_column(Integer, ForeignKey("bots.id"), nullable=False)
    subscribed_at           : Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)

    __table_args__ = (UniqueConstraint("cobot_funded_channel_id", "user_id", "bot_id"),)


class CobotFundedPending(Base):
    """تتبّع المستخدمين الذين طُلب منهم الاشتراك في قناة ممولة (المصنع الأساسي)
    ولم يُحتسبوا بعد. وجود صف = طُلب منه ولم يشترك بعد."""
    __tablename__ = "cobot_funded_pending"

    id                      : Mapped[int]      = mapped_column(Integer, primary_key=True, autoincrement=True)
    cobot_funded_channel_id : Mapped[int]      = mapped_column(Integer, ForeignKey("cobot_funded_channels.id"), nullable=False)
    user_id                 : Mapped[int]      = mapped_column(BigInteger, nullable=False)
    bot_id                  : Mapped[int]      = mapped_column(Integer, ForeignKey("bots.id"), nullable=False)
    requested_at            : Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)

    __table_args__ = (UniqueConstraint("cobot_funded_channel_id", "user_id", "bot_id"),)

class BotGroup(Base):
    __tablename__ = "bot_groups"

    id          : Mapped[int]      = mapped_column(Integer, primary_key=True, autoincrement=True)
    chat_id     : Mapped[int]      = mapped_column(BigInteger, unique=True, nullable=False)
    chat_title  : Mapped[str]      = mapped_column(String(256), nullable=False)
    chat_type   : Mapped[str]      = mapped_column(String(32),  nullable=False)
    username    : Mapped[str|None] = mapped_column(String(128), nullable=True)
    invite_link : Mapped[str|None] = mapped_column(String(256), nullable=True)
    is_active   : Mapped[bool]     = mapped_column(Boolean, default=True)
    added_at    : Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)

class BroadcastSettings(Base):
    __tablename__ = "broadcast_settings"

    id            : Mapped[int]  = mapped_column(Integer, primary_key=True, autoincrement=True)
    pin_broadcast : Mapped[bool] = mapped_column(Boolean, default=False)
    to_groups     : Mapped[bool] = mapped_column(Boolean, default=True)
    to_channels   : Mapped[bool] = mapped_column(Boolean, default=True)
    to_users      : Mapped[bool] = mapped_column(Boolean, default=True)

class CobotUser(Base):
    __tablename__ = "cobot_users"

    id          : Mapped[int]      = mapped_column(Integer, primary_key=True, autoincrement=True)
    user_id     : Mapped[int]      = mapped_column(BigInteger, nullable=False)
    bot_id      : Mapped[int]      = mapped_column(Integer, ForeignKey("bots.id"), nullable=False)
    username    : Mapped[str|None] = mapped_column(String(64),  nullable=True)
    first_name  : Mapped[str|None] = mapped_column(String(128), nullable=True)
    is_blocked  : Mapped[bool]     = mapped_column(Boolean, default=False)
    last_active : Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
    joined_at   : Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)

    __table_args__ = (UniqueConstraint("user_id", "bot_id"),)


# ============================================================
# نظام المدفوعات
# ============================================================

class PaymentPackage(Base):
    """باقات الشحن — نجوم مقابل دولار"""
    __tablename__ = "payment_packages"

    id         : Mapped[int]      = mapped_column(Integer, primary_key=True, autoincrement=True)
    factory_bot_id : Mapped[int] = mapped_column(Integer, default=0, index=True)   # 0 = المصنع الأساسي
    stars      : Mapped[int]      = mapped_column(Integer, nullable=False)   # عدد النجوم
    usd        : Mapped[float]    = mapped_column(Integer, nullable=False)   # القيمة بالدولار (مضروب 100 لتجنب الكسور)
    is_active  : Mapped[bool]     = mapped_column(Boolean, default=True)
    created_at : Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)


class PaymentSettings(Base):
    """إعدادات المدفوعات — سعر البوت الواحد"""
    __tablename__ = "payment_settings"

    id            : Mapped[int]   = mapped_column(Integer, primary_key=True, autoincrement=True)
    factory_bot_id : Mapped[int]  = mapped_column(Integer, default=0, index=True)   # 0 = المصنع الأساسي
    bot_price_usd : Mapped[int]   = mapped_column(Integer, default=200)   # سعر البوت × 100 (200 = 2.00$)
    updated_at    : Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)


class UserBalance(Base):
    """رصيد المستخدم بالدولار (مضروب 100)"""
    __tablename__ = "user_balances"

    user_id    : Mapped[int]      = mapped_column(BigInteger, ForeignKey("users.id"), primary_key=True)
    factory_bot_id : Mapped[int]  = mapped_column(Integer, primary_key=True, default=0)   # 0 = المصنع الأساسي
    balance    : Mapped[int]      = mapped_column(Integer, default=0)   # مثلاً 200 = 2.00$
    updated_at : Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    user : Mapped["User"] = relationship("User")


class PaymentTransaction(Base):
    """سجل معاملات الدفع — لمنع معالجة نفس الدفعة مرتين"""
    __tablename__ = "payment_transactions"

    id             : Mapped[int]      = mapped_column(Integer, primary_key=True, autoincrement=True)
    user_id        : Mapped[int]      = mapped_column(BigInteger, ForeignKey("users.id"), nullable=False)
    factory_bot_id : Mapped[int]      = mapped_column(Integer, default=0, index=True)   # 0 = المصنع الأساسي
    telegram_charge_id : Mapped[str]  = mapped_column(String(256), unique=True, nullable=False)
    stars          : Mapped[int]      = mapped_column(Integer, nullable=False)
    usd_credited   : Mapped[int]      = mapped_column(Integer, nullable=False)   # المبلغ المضاف × 100
    created_at     : Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)

    user : Mapped["User"] = relationship("User")


class BotSubscription(Base):
    """اشتراك البوت المدفوع"""
    __tablename__ = "bot_subscriptions"

    id         : Mapped[int]      = mapped_column(Integer, primary_key=True, autoincrement=True)
    bot_id     : Mapped[int]      = mapped_column(Integer, ForeignKey("bots.id"), unique=True, nullable=False)
    factory_bot_id : Mapped[int]  = mapped_column(Integer, default=0, index=True)   # 0 = المصنع الأساسي
    user_id    : Mapped[int]      = mapped_column(BigInteger, ForeignKey("users.id"), nullable=False)
    started_at : Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
    expires_at : Mapped[datetime] = mapped_column(DateTime, nullable=False)
    is_active  : Mapped[bool]     = mapped_column(Boolean, default=True)

    bot  : Mapped["Bot"]  = relationship("Bot",  back_populates="subscription")
    user : Mapped["User"] = relationship("User")
