"""
Ticket Data Models
==================
Data models for the modular ticket system.
"""
from dataclasses import dataclass, field
from datetime import datetime
from typing import Optional, List, Dict, Any
from enum import Enum


class TicketStatus(Enum):
    """Ticket status enumeration"""
    OPEN = "open"
    CLAIMED = "claimed"
    CLOSED = "closed"
    ARCHIVED = "archived"


class Priority(Enum):
    """Ticket priority levels"""
    LOW = "low"
    NORMAL = "normal"
    HIGH = "high"
    URGENT = "urgent"


class TicketCategory:
    """
    Represents a ticket category with customizable settings.
    
    Attributes:
        id: Unique identifier for the category
        name: Display name
        description: Description shown in panel
        emoji: Emoji icon for the category
        color: Embed color (hex)
        staff_roles: List of role IDs who can access this category
        welcome_message: Custom welcome message for this category
        require_reason: Whether to require a reason when creating
        max_tickets_per_user: Maximum tickets per user in this category
        auto_close_days: Days before auto-closing inactive tickets
        priority_enabled: Whether priority selection is enabled
        allow_claims: Whether staff can claim tickets
        survey_enabled: Whether satisfaction survey is enabled
    """
    
    def __init__(
        self,
        id: str,
        name: str,
        description: str = "",
        emoji: str = "🎫",
        color: str = "#3498db",
        staff_roles: List[str] = None,
        welcome_message: str = None,
        require_reason: bool = False,
        max_tickets_per_user: int = 5,
        auto_close_days: int = 7,
        priority_enabled: bool = True,
        allow_claims: bool = True,
        survey_enabled: bool = True,
        discord_category_id: Optional[int] = None,
        is_recruitment: bool = False,
        questions: List[str] = None,
        responses_channel_id: Optional[int] = None
    ):
        self.id = id
        self.name = name
        self.description = description
        self.emoji = emoji
        self.color = color
        self.staff_roles = list(staff_roles) if staff_roles is not None else []
        self.welcome_message = welcome_message or "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu."
        self.require_reason = require_reason
        self.max_tickets_per_user = max_tickets_per_user
        self.auto_close_days = auto_close_days
        self.priority_enabled = priority_enabled
        self.allow_claims = allow_claims
        self.survey_enabled = survey_enabled
        self.discord_category_id = discord_category_id
        self.is_recruitment = is_recruitment
        self.questions = questions or []
        self.responses_channel_id = responses_channel_id

    def to_dict(self) -> Dict[str, Any]:
        """Convert category to dictionary for storage"""
        return {
            "id": self.id,
            "name": self.name,
            "description": self.description,
            "emoji": self.emoji,
            "color": self.color,
            "staff_roles": self.staff_roles,
            "welcome_message": self.welcome_message,
            "require_reason": self.require_reason,
            "max_tickets_per_user": self.max_tickets_per_user,
            "auto_close_days": self.auto_close_days,
            "priority_enabled": self.priority_enabled,
            "allow_claims": self.allow_claims,
            "survey_enabled": self.survey_enabled,
            "discord_category_id": self.discord_category_id,
            "is_recruitment": self.is_recruitment,
            "questions": self.questions,
            "responses_channel_id": self.responses_channel_id
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'TicketCategory':
        """Create category from dictionary"""
        return cls(
            id=data.get("id", ""),
            name=data.get("name", ""),
            description=data.get("description", ""),
            emoji=data.get("emoji", "🎫"),
            color=data.get("color", "#3498db"),
            staff_roles=data.get("staff_roles", []),
            welcome_message=data.get("welcome_message"),
            require_reason=data.get("require_reason", False),
            max_tickets_per_user=data.get("max_tickets_per_user", 5),
            auto_close_days=data.get("auto_close_days", 7),
            priority_enabled=data.get("priority_enabled", True),
            allow_claims=data.get("allow_claims", True),
            survey_enabled=data.get("survey_enabled", True),
            discord_category_id=data.get("discord_category_id"),
            is_recruitment=data.get("is_recruitment", False),
            questions=data.get("questions", []),
            responses_channel_id=data.get("responses_channel_id")
        )


@dataclass
class TicketMessage:
    """Represents a message in a ticket"""
    id: str
    author_id: int
    author_name: str
    content: str
    timestamp: datetime
    attachments: List[str] = field(default_factory=list)
    is_staff: bool = False
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            "id": self.id,
            "author_id": self.author_id,
            "author_name": self.author_name,
            "content": self.content,
            "timestamp": self.timestamp.isoformat(),
            "attachments": self.attachments,
            "is_staff": self.is_staff
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'TicketMessage':
        return cls(
            id=data.get("id", ""),
            author_id=data.get("author_id", 0),
            author_name=data.get("author_name", ""),
            content=data.get("content", ""),
            timestamp=datetime.fromisoformat(data.get("timestamp", datetime.now().isoformat())),
            attachments=data.get("attachments", []),
            is_staff=data.get("is_staff", False)
        )


@dataclass
class TicketData:
    """
    Main ticket data structure.
    
    Attributes:
        channel_id: Discord channel ID
        guild_id: Discord guild ID
        user_id: User who created the ticket
        category_id: Ticket category
        status: Current ticket status
        priority: Ticket priority level
        created_at: Creation timestamp
        closed_at: Closing timestamp
        claimed_by: Staff member who claimed the ticket
        messages: List of messages in the ticket
        reason: Reason for creating the ticket
        transcript_path: Path to generated transcript
        rating: Satisfaction rating (1-5)
        feedback: User feedback text
    """
    
    channel_id: int
    guild_id: int
    user_id: int
    category_id: str
    status: TicketStatus = TicketStatus.OPEN
    priority: Priority = Priority.NORMAL
    created_at: datetime = field(default_factory=datetime.now)
    closed_at: Optional[datetime] = None
    claimed_by: Optional[int] = None
    messages: List[TicketMessage] = field(default_factory=list)
    reason: str = ""
    transcript_path: Optional[str] = None
    rating: Optional[int] = None
    feedback: Optional[str] = None
    recruitment_responses: Dict[str, str] = field(default_factory=dict)

    @property
    def is_open(self) -> bool:
        return self.status in [TicketStatus.OPEN, TicketStatus.CLAIMED]
    
    @property
    def duration_minutes(self) -> Optional[float]:
        """Get ticket duration in minutes"""
        end = self.closed_at or datetime.now()
        return (end - self.created_at).total_seconds() / 60
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            "channel_id": self.channel_id,
            "guild_id": self.guild_id,
            "user_id": self.user_id,
            "category_id": self.category_id,
            "status": self.status.value,
            "priority": self.priority.value,
            "created_at": self.created_at.isoformat(),
            "closed_at": self.closed_at.isoformat() if self.closed_at else None,
            "claimed_by": self.claimed_by,
            "messages": [m.to_dict() for m in self.messages],
            "reason": self.reason,
            "transcript_path": self.transcript_path,
            "rating": self.rating,
            "feedback": self.feedback,
            "recruitment_responses": self.recruitment_responses
        }

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'TicketData':
        messages = [TicketMessage.from_dict(m) for m in data.get("messages", [])]
        return cls(
            channel_id=data.get("channel_id", 0),
            guild_id=data.get("guild_id", 0),
            user_id=data.get("user_id", 0),
            category_id=data.get("category_id", ""),
            status=TicketStatus(data.get("status", "open")),
            priority=Priority(data.get("priority", "normal")),
            created_at=datetime.fromisoformat(data.get("created_at", datetime.now().isoformat())),
            closed_at=datetime.fromisoformat(data["closed_at"]) if data.get("closed_at") else None,
            claimed_by=data.get("claimed_by"),
            messages=messages,
            reason=data.get("reason", ""),
            transcript_path=data.get("transcript_path"),
            rating=data.get("rating"),
            feedback=data.get("feedback"),
            recruitment_responses=data.get("recruitment_responses", {})
        )


@dataclass
class TicketStats:
    """Statistics for a ticket system"""
    total_tickets: int = 0
    open_tickets: int = 0
    closed_tickets: int = 0
    claimed_tickets: int = 0
    average_duration_minutes: float = 0
    average_rating: float = 0
    tickets_by_category: Dict[str, int] = field(default_factory=dict)
    tickets_by_priority: Dict[str, int] = field(default_factory=dict)
    tickets_by_day: Dict[str, int] = field(default_factory=dict)
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            "total_tickets": self.total_tickets,
            "open_tickets": self.open_tickets,
            "closed_tickets": self.closed_tickets,
            "claimed_tickets": self.claimed_tickets,
            "average_duration_minutes": self.average_duration_minutes,
            "average_rating": self.average_rating,
            "tickets_by_category": self.tickets_by_category,
            "tickets_by_priority": self.tickets_by_priority,
            "tickets_by_day": self.tickets_by_day
        }


@dataclass
class GuildTicketConfig:
    """
    Guild-wide ticket configuration.
    
    Attributes:
        guild_id: Discord guild ID
        enabled: Whether the ticket system is enabled
        categories: List of ticket categories
        default_category: Default category ID
        log_channel_id: Channel for ticket logs
        archive_channel_id: Channel for archived transcripts
        staff_roles: Global staff roles (can manage tickets, access analytics, etc.)
        config_roles: Roles that can access the configuration panel (/ticketconfig)
        max_tickets_per_user: Global max tickets per user
        auto_close_enabled: Whether auto-close is enabled
        auto_close_days: Days before auto-close
        transcript_enabled: Whether transcripts are generated
        claim_enabled: Whether claiming is enabled by default
        survey_enabled: Whether surveys are enabled by default
        panel_channel_id: Channel for the ticket panel
        panel_message_id: Message ID of the ticket panel (for auto-refresh)
        welcome_enabled: Whether welcome messages are shown
        priority_enabled: Whether priority selection is enabled
    """
    
    guild_id: int
    enabled: bool = True
    categories: List[TicketCategory] = field(default_factory=list)
    default_category: Optional[str] = None
    log_channel_id: Optional[int] = None
    archive_channel_id: Optional[int] = None
    staff_roles: List[str] = field(default_factory=list)
    staff_users: List[int] = field(default_factory=list)
    config_roles: List[str] = field(default_factory=list)
    config_users: List[int] = field(default_factory=list)
    max_tickets_per_user: int = 5
    auto_close_enabled: bool = False
    auto_close_days: int = 7
    transcript_enabled: bool = True
    claim_enabled: bool = True
    survey_enabled: bool = True
    panel_channel_id: Optional[int] = None
    panel_message_id: Optional[int] = None
    welcome_enabled: bool = True
    priority_enabled: bool = True
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            "guild_id": self.guild_id,
            "enabled": self.enabled,
            "categories": [c.to_dict() for c in self.categories],
            "default_category": self.default_category,
            "log_channel_id": self.log_channel_id,
            "archive_channel_id": self.archive_channel_id,
            "log_channel_id": self.log_channel_id,
            "archive_channel_id": self.archive_channel_id,
            "staff_roles": self.staff_roles,
            "staff_users": self.staff_users,
            "config_roles": self.config_roles,
            "config_users": self.config_users,
            "max_tickets_per_user": self.max_tickets_per_user,
            "auto_close_enabled": self.auto_close_enabled,
            "auto_close_days": self.auto_close_days,
            "transcript_enabled": self.transcript_enabled,
            "claim_enabled": self.claim_enabled,
            "survey_enabled": self.survey_enabled,
            "panel_channel_id": self.panel_channel_id,
            "panel_message_id": self.panel_message_id,
            "welcome_enabled": self.welcome_enabled,
            "priority_enabled": self.priority_enabled
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'GuildTicketConfig':
        categories = [TicketCategory.from_dict(c) for c in data.get("categories", [])]
        return cls(
            guild_id=data.get("guild_id", 0),
            enabled=data.get("enabled", True),
            categories=categories,
            default_category=data.get("default_category"),
            log_channel_id=data.get("log_channel_id"),
            archive_channel_id=data.get("archive_channel_id"),

            staff_roles=data.get("staff_roles", []),
            staff_users=data.get("staff_users", []),
            config_roles=data.get("config_roles", []),
            config_users=data.get("config_users", []),
            max_tickets_per_user=data.get("max_tickets_per_user", 5),
            auto_close_enabled=data.get("auto_close_enabled", False),
            auto_close_days=data.get("auto_close_days", 7),
            transcript_enabled=data.get("transcript_enabled", True),
            claim_enabled=data.get("claim_enabled", True),
            survey_enabled=data.get("survey_enabled", True),
            panel_channel_id=data.get("panel_channel_id"),
            panel_message_id=data.get("panel_message_id"),
            welcome_enabled=data.get("welcome_enabled", True),
            priority_enabled=data.get("priority_enabled", True)
        )
    
    def get_category(self, category_id: str) -> Optional[TicketCategory]:
        """Get a category by ID"""
        for cat in self.categories:
            if cat.id == category_id:
                return cat
        return None

