from datetime import UTC, datetime
from sqlalchemy import BigInteger, Boolean, Column, DateTime, Float, ForeignKey, Integer, String, Text, JSON
from sqlalchemy.orm import declarative_base, relationship

Base = declarative_base()


def utc_now() -> datetime:
    return datetime.now(UTC).replace(tzinfo=None)


class Domain(Base):
    __tablename__ = "domains"
    id = Column(Integer, primary_key=True)
    name = Column(String(255), unique=True, nullable=False)
    is_active = Column(Boolean, default=True, nullable=False)
    max_users = Column(Integer, default=0)
    dkim_selector = Column(String(64), default="default")
    dkim_public_key = Column(Text)
    dkim_private_path = Column(String(512))
    dmarc_policy = Column(String(32), default="reject")
    dns_provider = Column(String(32))
    dns_account_id = Column(String(128))
    dns_zone_id = Column(String(128))
    dns_api_token = Column(Text)
    dns_sync_enabled = Column(Boolean, default=False, nullable=False)
    dns_last_sync_at = Column(DateTime)
    dns_last_sync_status = Column(String(512))
    created_at = Column(DateTime, default=utc_now)

    accounts = relationship("Account", back_populates="domain", cascade="all,delete")
    aliases = relationship("Alias", back_populates="domain", cascade="all,delete")
    redirects = relationship("Redirect", back_populates="domain", cascade="all,delete")

    @property
    def dns_has_api_token(self) -> bool:
        return bool(self.dns_api_token)

class Account(Base):
    __tablename__ = "accounts"
    id = Column(Integer, primary_key=True)
    domain_id = Column(Integer, ForeignKey("domains.id", ondelete="CASCADE"), nullable=False)
    local_part = Column(String(255), nullable=False)
    username = Column(String(320), unique=True, nullable=False)
    password_hash = Column(String(255), nullable=False)
    quota_mb = Column(Integer, nullable=False, default=2048)
    quota_bytes = Column(BigInteger, nullable=False, default=0)
    quota_messages = Column(BigInteger, nullable=False, default=0)
    is_active = Column(Boolean, default=True, nullable=False)
    created_at = Column(DateTime, default=utc_now)

    domain = relationship("Domain", back_populates="accounts")

class Alias(Base):
    __tablename__ = "aliases"
    id = Column(Integer, primary_key=True)
    domain_id = Column(Integer, ForeignKey("domains.id", ondelete="CASCADE"), nullable=False)
    source_local = Column(String(255), nullable=False)
    destination = Column(String(255), nullable=False)
    is_active = Column(Boolean, default=True, nullable=False)
    created_at = Column(DateTime, default=utc_now)

    domain = relationship("Domain", back_populates="aliases")

class Redirect(Base):
    __tablename__ = "redirects"
    id = Column(Integer, primary_key=True)
    domain_id = Column(Integer, ForeignKey("domains.id", ondelete="CASCADE"), nullable=False)
    source_local = Column(String(255), nullable=False)
    target_email = Column(String(255), nullable=False)
    is_active = Column(Boolean, default=True, nullable=False)
    created_at = Column(DateTime, default=utc_now)

    domain = relationship("Domain", back_populates="redirects")

class Reputation(Base):
    __tablename__ = "reputations"
    id = Column(Integer, primary_key=True)
    entity_type = Column(String(16), nullable=False)
    entity_value = Column(String(255), nullable=False)
    score = Column(Float, default=0)
    last_event = Column(JSON, nullable=True)
    updated_at = Column(DateTime, default=utc_now, onupdate=utc_now)

class Greylist(Base):
    __tablename__ = "greylist"
    id = Column(Integer, primary_key=True)
    ip = Column(String(64), nullable=False)
    sender = Column(String(255), nullable=False)
    rcpt = Column(String(255), nullable=False)
    passed = Column(Boolean, default=False)
    first_seen = Column(DateTime, default=utc_now)
    last_seen = Column(DateTime, default=utc_now)

class SpamTrap(Base):
    __tablename__ = "spam_traps"
    id = Column(Integer, primary_key=True)
    email = Column(String(255), nullable=False)
    note = Column(String(255), nullable=True)
    created_at = Column(DateTime, default=utc_now)

class TrustedReply(Base):
    __tablename__ = "trusted_replies"
    id = Column(Integer, primary_key=True)
    message_id = Column(String(255), nullable=False)
    from_email = Column(String(255), nullable=False)
    trust_score = Column(Float, default=0)
    seen_at = Column(DateTime, default=utc_now)

class BlocklistCache(Base):
    __tablename__ = "blocklists_cache"
    id = Column(Integer, primary_key=True)
    entity_type = Column(String(16), nullable=False)
    entity_value = Column(String(255), nullable=False)
    status = Column(String(16), nullable=False)
    source = Column(String(255), nullable=False)
    checked_at = Column(DateTime, default=utc_now)
