from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey, JSON, Enum, Boolean, Numeric
from sqlalchemy.orm import relationship
from datetime import datetime
import enum
from ...shared.config.database import Base

class CampaignStatus(str, enum.Enum):
    draft = 'draft'
    scheduled = 'scheduled'
    sending = 'sending'
    sent = 'sent'
    paused = 'paused'
    cancelled = 'cancelled'

class CampaignType(str, enum.Enum):
    newsletter = 'newsletter'
    promotional = 'promotional'
    transactional = 'transactional'
    abandoned_booking = 'abandoned_booking'
    welcome = 'welcome'
    drip = 'drip'
    custom = 'custom'

class EmailStatus(str, enum.Enum):
    pending = 'pending'
    sent = 'sent'
    delivered = 'delivered'
    opened = 'opened'
    clicked = 'clicked'
    bounced = 'bounced'
    failed = 'failed'
    unsubscribed = 'unsubscribed'

class Campaign(Base):
    __tablename__ = 'email_campaigns'
    
    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    name = Column(String(200), nullable=False, index=True)
    subject = Column(String(500), nullable=False)
    campaign_type = Column(Enum(CampaignType), nullable=False, default=CampaignType.newsletter)
    status = Column(Enum(CampaignStatus), nullable=False, default=CampaignStatus.draft, index=True)
    
    # Content
    html_content = Column(Text, nullable=True)
    text_content = Column(Text, nullable=True)
    template_id = Column(Integer, ForeignKey('email_templates.id'), nullable=True)
    
    # Scheduling
    scheduled_at = Column(DateTime, nullable=True, index=True)
    sent_at = Column(DateTime, nullable=True)
    
    # Segmentation
    segment_id = Column(Integer, ForeignKey('campaign_segments.id'), nullable=True)
    segment_criteria = Column(JSON, nullable=True)  # Store segment criteria as JSON
    recipient_type = Column(String(50), nullable=True, default='users')  # 'users', 'subscribers', 'both'
    
    # A/B Testing
    is_ab_test = Column(Boolean, nullable=False, default=False)
    ab_test_variant_a_id = Column(Integer, ForeignKey('email_campaigns.id'), nullable=True)
    ab_test_variant_b_id = Column(Integer, ForeignKey('email_campaigns.id'), nullable=True)
    ab_test_split_percentage = Column(Integer, nullable=True, default=50)  # Percentage for variant A
    ab_test_winner = Column(String(1), nullable=True)  # 'A' or 'B'
    
    # Drip Campaign
    is_drip = Column(Boolean, nullable=False, default=False)
    drip_sequence_id = Column(Integer, ForeignKey('drip_sequences.id'), nullable=True)
    drip_delay_days = Column(Integer, nullable=True)  # Days to wait before sending
    
    # Analytics
    total_recipients = Column(Integer, nullable=False, default=0)
    total_sent = Column(Integer, nullable=False, default=0)
    total_delivered = Column(Integer, nullable=False, default=0)
    total_opened = Column(Integer, nullable=False, default=0)
    total_clicked = Column(Integer, nullable=False, default=0)
    total_bounced = Column(Integer, nullable=False, default=0)
    total_unsubscribed = Column(Integer, nullable=False, default=0)
    
    # Metrics (calculated)
    open_rate = Column(Numeric(5, 2), nullable=True)  # Percentage
    click_rate = Column(Numeric(5, 2), nullable=True)  # Percentage
    bounce_rate = Column(Numeric(5, 2), nullable=True)  # Percentage
    
    # Settings
    from_name = Column(String(200), nullable=True)
    from_email = Column(String(255), nullable=True)
    reply_to_email = Column(String(255), nullable=True)
    track_opens = Column(Boolean, nullable=False, default=True)
    track_clicks = Column(Boolean, nullable=False, default=True)
    
    # Metadata
    created_by = Column(Integer, ForeignKey('users.id'), nullable=True)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
    
    # Relationships
    template = relationship('EmailTemplate', foreign_keys=[template_id])
    segment = relationship('CampaignSegment', foreign_keys=[segment_id])
    variant_a = relationship('Campaign', foreign_keys=[ab_test_variant_a_id], remote_side=[id])
    variant_b = relationship('Campaign', foreign_keys=[ab_test_variant_b_id], remote_side=[id])
    creator = relationship('User', foreign_keys=[created_by])
    emails = relationship('CampaignEmail', back_populates='campaign', cascade='all, delete-orphan')
    drip_sequence = relationship('DripSequence', foreign_keys=[drip_sequence_id])

class CampaignSegment(Base):
    __tablename__ = 'campaign_segments'
    
    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    name = Column(String(200), nullable=False, index=True)
    description = Column(Text, nullable=True)
    
    # Segment criteria (stored as JSON for flexibility)
    criteria = Column(JSON, nullable=False)  # e.g., {"role": "customer", "last_booking_days": 30}
    
    # Estimated count
    estimated_count = Column(Integer, nullable=True)
    last_calculated_at = Column(DateTime, nullable=True)
    
    is_active = Column(Boolean, nullable=False, default=True)
    created_by = Column(Integer, ForeignKey('users.id'), nullable=True)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
    
    # Relationships
    creator = relationship('User', foreign_keys=[created_by])

class EmailTemplate(Base):
    __tablename__ = 'email_templates'
    
    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    name = Column(String(200), nullable=False, index=True)
    subject = Column(String(500), nullable=False)
    html_content = Column(Text, nullable=False)
    text_content = Column(Text, nullable=True)
    
    # Template variables (e.g., {{name}}, {{booking_number}})
    variables = Column(JSON, nullable=True)  # List of available variables
    
    # Category
    category = Column(String(100), nullable=True, index=True)  # 'newsletter', 'transactional', etc.
    
    is_active = Column(Boolean, nullable=False, default=True)
    is_system = Column(Boolean, nullable=False, default=False)  # System templates can't be deleted
    
    created_by = Column(Integer, ForeignKey('users.id'), nullable=True)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
    
    # Relationships
    creator = relationship('User', foreign_keys=[created_by])

class CampaignEmail(Base):
    __tablename__ = 'campaign_emails'
    
    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    campaign_id = Column(Integer, ForeignKey('email_campaigns.id'), nullable=False, index=True)
    user_id = Column(Integer, ForeignKey('users.id'), nullable=True, index=True)
    email = Column(String(255), nullable=False, index=True)
    
    # Status tracking
    status = Column(Enum(EmailStatus), nullable=False, default=EmailStatus.pending, index=True)
    sent_at = Column(DateTime, nullable=True)
    delivered_at = Column(DateTime, nullable=True)
    opened_at = Column(DateTime, nullable=True)
    clicked_at = Column(DateTime, nullable=True)
    bounced_at = Column(DateTime, nullable=True)
    unsubscribed_at = Column(DateTime, nullable=True)
    
    # Tracking
    open_count = Column(Integer, nullable=False, default=0)
    click_count = Column(Integer, nullable=False, default=0)
    last_opened_at = Column(DateTime, nullable=True)
    last_clicked_at = Column(DateTime, nullable=True)
    
    # A/B Test tracking
    ab_test_variant = Column(String(1), nullable=True)  # 'A' or 'B'
    
    # Error tracking
    error_message = Column(Text, nullable=True)
    
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
    
    # Relationships
    campaign = relationship('Campaign', back_populates='emails')
    user = relationship('User')

class EmailClick(Base):
    __tablename__ = 'email_clicks'
    
    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    campaign_email_id = Column(Integer, ForeignKey('campaign_emails.id'), nullable=False, index=True)
    url = Column(String(1000), nullable=False)
    clicked_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
    ip_address = Column(String(45), nullable=True)
    user_agent = Column(String(500), nullable=True)
    
    # Relationships
    campaign_email = relationship('CampaignEmail')

class DripSequence(Base):
    __tablename__ = 'drip_sequences'
    
    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    name = Column(String(200), nullable=False, index=True)
    description = Column(Text, nullable=True)
    trigger_event = Column(String(100), nullable=True)  # 'booking_created', 'checkout_abandoned', etc.
    
    is_active = Column(Boolean, nullable=False, default=True)
    created_by = Column(Integer, ForeignKey('users.id'), nullable=True)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
    
    # Relationships
    creator = relationship('User', foreign_keys=[created_by])
    steps = relationship('DripSequenceStep', back_populates='sequence', cascade='all, delete-orphan', order_by='DripSequenceStep.step_order')
    campaigns = relationship('Campaign', foreign_keys=[Campaign.drip_sequence_id], overlaps="drip_sequence")

class DripSequenceStep(Base):
    __tablename__ = 'drip_sequence_steps'
    
    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    sequence_id = Column(Integer, ForeignKey('drip_sequences.id'), nullable=False, index=True)
    step_order = Column(Integer, nullable=False)  # Order in the sequence
    
    # Email content
    subject = Column(String(500), nullable=False)
    html_content = Column(Text, nullable=False)
    text_content = Column(Text, nullable=True)
    template_id = Column(Integer, ForeignKey('email_templates.id'), nullable=True)
    
    # Timing
    delay_days = Column(Integer, nullable=False, default=0)  # Days to wait after previous step
    delay_hours = Column(Integer, nullable=False, default=0)  # Additional hours
    
    # Conditions (optional - skip this step if conditions not met)
    conditions = Column(JSON, nullable=True)
    
    is_active = Column(Boolean, nullable=False, default=True)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
    
    # Relationships
    sequence = relationship('DripSequence', back_populates='steps')
    template = relationship('EmailTemplate', foreign_keys=[template_id])

class DripSequenceEnrollment(Base):
    __tablename__ = 'drip_sequence_enrollments'
    
    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    sequence_id = Column(Integer, ForeignKey('drip_sequences.id'), nullable=False, index=True)
    user_id = Column(Integer, ForeignKey('users.id'), nullable=False, index=True)
    
    # Progress tracking
    current_step = Column(Integer, nullable=False, default=0)
    next_send_at = Column(DateTime, nullable=True, index=True)
    completed = Column(Boolean, nullable=False, default=False)
    completed_at = Column(DateTime, nullable=True)
    
    # Trigger context
    trigger_data = Column(JSON, nullable=True)  # Store context about what triggered enrollment
    
    enrolled_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
    
    # Relationships
    sequence = relationship('DripSequence')
    user = relationship('User')

class Unsubscribe(Base):
    __tablename__ = 'email_unsubscribes'
    
    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    email = Column(String(255), nullable=False, index=True)
    user_id = Column(Integer, ForeignKey('users.id'), nullable=True, index=True)
    campaign_id = Column(Integer, ForeignKey('email_campaigns.id'), nullable=True)
    
    # Unsubscribe type
    unsubscribe_all = Column(Boolean, nullable=False, default=False)  # True = all emails, False = specific campaign
    unsubscribe_type = Column(String(50), nullable=True)  # 'newsletter', 'promotional', etc.
    
    reason = Column(Text, nullable=True)
    unsubscribed_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
    
    # Relationships
    user = relationship('User')
    campaign = relationship('Campaign')

class NewsletterSubscriber(Base):
    __tablename__ = 'newsletter_subscribers'
    
    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    email = Column(String(255), nullable=False, unique=True, index=True)
    user_id = Column(Integer, ForeignKey('users.id'), nullable=True, index=True)
    name = Column(String(255), nullable=True)
    
    subscribed_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
    is_active = Column(Boolean, nullable=False, default=True, index=True)
    
    # Relationships
    user = relationship('User')

