"""Sequence data models - outreach sequence and steps."""

from __future__ import annotations
from dataclasses import dataclass, field
from datetime import datetime
from typing import Optional
import uuid


@dataclass
class SequenceStep:
    """
    Represents a single step in an outreach sequence.
    """
    id: str = field(default_factory=lambda: str(uuid.uuid4()))
    sequence_id: str = ""
    step_number: int = 1
    channel: str = "email"  # email | linkedin | call | task
    delay_days: int = 0  # Days after previous step (0 for first step)
    delay_hours: int = 0  # Additional hours delay

    # Email content
    subject: str = ""
    body: str = ""

    # Variants for A/B testing
    subject_variants: list[str] = field(default_factory=list)
    body_variants: list[str] = field(default_factory=list)

    # Template reference (if using templates)
    template_id: Optional[str] = None

    # Step settings
    skip_if_replied: bool = True
    skip_weekends: bool = True

    # Stats
    sent_count: int = 0
    open_count: int = 0
    reply_count: int = 0

    created_at: datetime = field(default_factory=datetime.now)

    def to_dict(self) -> dict:
        return {
            "id": self.id,
            "sequence_id": self.sequence_id,
            "step_number": self.step_number,
            "channel": self.channel,
            "delay_days": self.delay_days,
            "delay_hours": self.delay_hours,
            "subject": self.subject,
            "body": self.body,
            "subject_variants": self.subject_variants,
            "body_variants": self.body_variants,
            "template_id": self.template_id,
            "skip_if_replied": self.skip_if_replied,
            "skip_weekends": self.skip_weekends,
            "sent_count": self.sent_count,
            "open_count": self.open_count,
            "reply_count": self.reply_count,
            "created_at": self.created_at.isoformat(),
        }

    @classmethod
    def from_dict(cls, data: dict) -> SequenceStep:
        data = data.copy()
        if "created_at" in data and isinstance(data["created_at"], str):
            data["created_at"] = datetime.fromisoformat(data["created_at"])
        return cls(**data)


@dataclass
class Sequence:
    """
    Represents an outreach sequence with multiple steps.
    """
    id: str = field(default_factory=lambda: str(uuid.uuid4()))
    name: str = ""
    description: Optional[str] = None
    status: str = "draft"  # draft | active | paused | completed | archived

    # Steps
    steps: list[SequenceStep] = field(default_factory=list)

    # Targeting
    segment_ids: list[str] = field(default_factory=list)

    # Sending settings
    sending_window_start: str = "08:00"
    sending_window_end: str = "18:00"
    timezone: str = "America/New_York"
    send_on_weekends: bool = False
    daily_limit: int = 100

    # Sender settings
    sender_email: Optional[str] = None
    sender_name: Optional[str] = None
    reply_to: Optional[str] = None

    # Stats
    total_enrolled: int = 0
    active_enrolled: int = 0
    completed_count: int = 0
    reply_count: int = 0
    meeting_count: int = 0

    # Timestamps
    created_at: datetime = field(default_factory=datetime.now)
    updated_at: datetime = field(default_factory=datetime.now)
    started_at: Optional[datetime] = None
    paused_at: Optional[datetime] = None

    def to_dict(self) -> dict:
        return {
            "id": self.id,
            "name": self.name,
            "description": self.description,
            "status": self.status,
            "steps": [s.to_dict() for s in self.steps],
            "segment_ids": self.segment_ids,
            "sending_window_start": self.sending_window_start,
            "sending_window_end": self.sending_window_end,
            "timezone": self.timezone,
            "send_on_weekends": self.send_on_weekends,
            "daily_limit": self.daily_limit,
            "sender_email": self.sender_email,
            "sender_name": self.sender_name,
            "reply_to": self.reply_to,
            "total_enrolled": self.total_enrolled,
            "active_enrolled": self.active_enrolled,
            "completed_count": self.completed_count,
            "reply_count": self.reply_count,
            "meeting_count": self.meeting_count,
            "created_at": self.created_at.isoformat(),
            "updated_at": self.updated_at.isoformat(),
            "started_at": self.started_at.isoformat() if self.started_at else None,
            "paused_at": self.paused_at.isoformat() if self.paused_at else None,
        }

    @classmethod
    def from_dict(cls, data: dict) -> Sequence:
        data = data.copy()
        # Parse steps
        if "steps" in data:
            data["steps"] = [SequenceStep.from_dict(s) for s in data["steps"]]
        # Parse timestamps
        for field_name in ["created_at", "updated_at", "started_at", "paused_at"]:
            if field_name in data and isinstance(data[field_name], str):
                data[field_name] = datetime.fromisoformat(data[field_name])
        return cls(**data)

    def add_step(self, step: SequenceStep) -> None:
        """Add a step to the sequence."""
        step.sequence_id = self.id
        step.step_number = len(self.steps) + 1
        self.steps.append(step)
        self.updated_at = datetime.now()

    def activate(self) -> None:
        """Activate the sequence."""
        self.status = "active"
        self.started_at = datetime.now()
        self.updated_at = datetime.now()

    def pause(self) -> None:
        """Pause the sequence."""
        self.status = "paused"
        self.paused_at = datetime.now()
        self.updated_at = datetime.now()

    def get_step(self, step_number: int) -> Optional[SequenceStep]:
        """Get a step by number."""
        for step in self.steps:
            if step.step_number == step_number:
                return step
        return None
