class Campaign(Base, TimestampMixin):
    __tablename__ = "campaigns"
    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True)
    name = Column(String(250), nullable=False)
    status = Column(String(30), default="draft")  # draft|queued|running|paused|completed|cancelled|failed
    # selections
    recipient_list_id = Column(Integer, ForeignKey("recipient_lists.id", ondelete="SET NULL"))
    subject_set_ids = Column(JSON, default=list)   # list of subject line ids
    template_ids = Column(JSON, default=list)      # ordered template ids for sequencing
    message_type = Column(String(40), default="html")
    # attachment behaviour
    attach_pdf = Column(Boolean, default=False)
    attach_pdf_template_id = Column(Integer, ForeignKey("html_templates.id", ondelete="SET NULL"))
    attachment_id = Column(Integer, ForeignKey("attachments.id", ondelete="SET NULL"))
    attach_mode = Column(String(40), default="none")  # none|pdf|file|image
    # dynamic variables config
    variable_config = Column(JSON, default=dict)   # invoice date, due date, ranges etc.
    # rotation / limits
    account_ids = Column(JSON, default=list)
    rotation_strategy = Column(String(30), default="sequential")  # sequential|weighted
    rotation_weights = Column(JSON, default=dict)  # account_id -> weight
    subject_rotation = Column(String(30), default="round_robin")  # round_robin|random|fixed_first
    template_sequence_mode = Column(String(30), default="repeat")  # repeat|stop|random
    phone_selection = Column(String(30), default="round_robin")   # round_robin|random|fixed
    max_per_account = Column(Integer, default=200)
    send_interval_seconds = Column(Float, default=1.0)
    rate_per_minute = Column(Integer, default=60)
    max_retries = Column(Integer, default=3)
    retry_delay_seconds = Column(Integer, default=60)
    # counters
    total_recipients = Column(Integer, default=0)
    sent_count = Column(Integer, default=0)
class CampaignRecipient(Base, TimestampMixin):
    """Materialized campaign×recipient rows with generated values & audit info."""
    __tablename__ = "campaign_recipients"
    id = Column(Integer, primary_key=True)
    campaign_id = Column(Integer, ForeignKey("campaigns.id", ondelete="CASCADE"), nullable=False, index=True)
    recipient_id = Column(Integer, ForeignKey("recipients.id", ondelete="CASCADE"), nullable=False)
    email = Column(String(320), nullable=False, index=True)
    status = Column(String(30), default="pending")  # pending|queued|processing|sent|temp_failed|perm_failed|suppressed|skipped
    generated_invoice_number = Column(String(100), default="")
    generated_amount = Column(Float)
    generated_shipping = Column(Float)
    generated_subject_id = Column(Integer, ForeignKey("subject_lines.id", ondelete="SET NULL"))
    generated_template_id = Column(Integer, ForeignKey("html_templates.id", ondelete="SET NULL"))
    generated_phone = Column(String(60), default="")
    assigned_account_id = Column(Integer, ForeignKey("gmail_accounts.id", ondelete="SET NULL"))
    attempt_count = Column(Integer, default=0)
    last_error = Column(Text, default="")
    msg_id = Column(String(200), default="")       # Gmail message id
    thread_id = Column(String(200), default="")    # Gmail thread id
    sent_at = Column(DateTime(timezone=True))
    seq = Column(Integer, default=0)               # ordering within campaign

    campaign = relationship("Campaign")
    recipient = relationship("Recipient")
    subject = relationship("SubjectLine")
    template = relationship("EmailTemplate")
    account = relationship("GmailAccount")

    __table_args__ = (UniqueConstraint("campaign_id", "recipient_id", name="uq_campaign_recipient"),
                      Index("ix_campaign_recipient_status", "campaign_id", "status"),)


class Attachment(Base, TimestampMixin):
    __tablename__ = "attachments"
    id = Column(Integer, primary_key=True)
class SendJob(Base, TimestampMixin):
    __tablename__ = "send_jobs"
    id = Column(Integer, primary_key=True)
    campaign_id = Column(Integer, ForeignKey("campaigns.id", ondelete="CASCADE"), nullable=False, index=True)
    campaign_recipient_id = Column(Integer, ForeignKey("campaign_recipients.id", ondelete="CASCADE"), nullable=False, index=True)
    status = Column(String(30), default="queued")  # queued|processing|sent|failed|retrying|cancelled|dead
    attempts = Column(Integer, default=0)
    max_attempts = Column(Integer, default=3)
    retry_after = Column(DateTime(timezone=True))
    last_error = Column(Text, default="")
    locked_at = Column(DateTime(timezone=True))
    priority = Column(Integer, default=0)
    scheduled_at = Column(DateTime(timezone=True), default=utcnow, index=True)

    campaign = relationship("Campaign", back_populates="send_jobs")
    campaign_recipient = relationship("CampaignRecipient")


class SendAttempt(Base, TimestampMixin):
    __tablename__ = "send_attempts"
    id = Column(Integer, primary_key=True)
    send_job_id = Column(Integer, ForeignKey("send_jobs.id", ondelete="CASCADE"), nullable=False, index=True)
    campaign_id = Column(Integer, ForeignKey("campaigns.id", ondelete="CASCADE"), nullable=False, index=True)
    gmail_account_id = Column(Integer, ForeignKey("gmail_accounts.id", ondelete="SET NULL"))
    recipient_email = Column(String(320), nullable=False)
    subject = Column(String(500), default="")
    template_name = Column(String(250), default="")
    attachment_names = Column(JSON, default=list)
    method = Column(String(20), default="api")  # api|smtp
    outcome = Column(String(30), nullable=False)  # submitted|accepted|temp_failed|perm_failed|skipped
    provider_response = Column(Text, default="")   # sanitized provider response
    message_id = Column(String(200), default="")
    thread_id = Column(String(200), default="")
    retry_no = Column(Integer, default=0)
    failure_reason = Column(Text, default="")
    error_class = Column(String(60), default="")  # temporary|permanent|auth|quota|unknown

    send_job = relationship("SendJob")


class EmailEvent(Base, TimestampMixin):
    __tablename__ = "email_events"
    id = Column(Integer, primary_key=True)
    campaign_id = Column(Integer, ForeignKey("campaigns.id", ondelete="CASCADE"), index=True)
    campaign_recipient_id = Column(Integer, ForeignKey("campaign_recipients.id", ondelete="CASCADE"), index=True)
    gmail_account_id = Column(Integer, ForeignKey("gmail_accounts.id", ondelete="SET NULL"))
    event_type = Column(String(40), nullable=False)  # sent|failed|bounced|suppressed|unsubscribed|complained
    detail = Column(Text, default="")
    message_id = Column(String(200), default="")

    __table_args__ = (Index("ix_email_events_campaign", "campaign_id", "event_type"),)


class AuditLog(Base, TimestampMixin):
    __tablename__ = "audit_logs"
    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"), index=True)
    action = Column(String(120), nullable=False, index=True)
    entity = Column(String(60), default="")
    entity_id = Column(Integer)
    detail = Column(JSON, default=dict)
    ip_address = Column(String(64), default="")

    user = relationship("User")


class ApplicationSettings(Base, TimestampMixin):
    __tablename__ = "application_settings"
    id = Column(Integer, primary_key=True)
    key = Column(String(150), unique=True, nullable=False, index=True)
    value = Column(JSON, nullable=False)
    description = Column(String(300), default="")
    category = Column(String(60), default="general")
