"""Modèle Story pour les histoires interactives."""

import uuid
from datetime import datetime
from typing import Optional

from sqlalchemy import String, Integer, Boolean, DateTime, Text, ForeignKey, JSON
from sqlalchemy.orm import Mapped, mapped_column, relationship
from models.user import db


class Story(db.Model):
    """Modèle représentant une histoire interactive.
    
    Attributes:
        id: Identifiant unique (UUID).
        user_id: ID de l'utilisateur créateur.
        title: Titre de l'histoire.
        genre: Genre littéraire.
        epoch: Époque de l'histoire.
        reality_level: Niveau de réalité (0-100).
        narrative_perspective: Perspective narrative ('second' ou 'third').
        protagonist_name: Nom du protagoniste (si 3ème personne).
        protagonist_gender: Genre du protagoniste ('he' ou 'she').
        context_answers: Réponses aux questions de contextualisation (JSON).
        narrative_skeleton: Squelette narratif généré par l'IA (JSON).
        cover_image_url: URL de l'image de couverture.
        game_mode: Mode de jeu ('choices' ou 'free').
        status: Statut ('in_progress', 'completed', 'abandoned').
        is_published: Histoire publiée ou non.
        publication_status: Statut de publication ('ongoing' ou 'finished').
        publication_description: Description pour la galerie publique.
        published_turn_count: Nombre de passages publiés et figés.
        turn_count: Nombre total de tours.
        views_count: Nombre de vues.
        likes_count: Nombre de likes.
        created_at: Date de création.
        updated_at: Date de dernière mise à jour.
        last_played_at: Date de dernière partie.
        published_at: Date de première publication.
        last_chapter_published_at: Date du dernier chapitre publié.
    """
    
    __tablename__ = 'stories'
    
    # Primary Key
    id: Mapped[str] = mapped_column(
        String(36),
        primary_key=True,
        default=lambda: str(uuid.uuid4())
    )
    
    # Foreign Key
    user_id: Mapped[str] = mapped_column(
        String(36),
        ForeignKey('users.id', ondelete='CASCADE'),
        nullable=False,
        index=True
    )
    
    # Basic Info
    title: Mapped[str] = mapped_column(
        String(255),
        nullable=False
    )
    
    # Configuration initiale
    genre: Mapped[Optional[str]] = mapped_column(
        String(100),
        nullable=True,
        index=True
    )
    epoch: Mapped[Optional[str]] = mapped_column(
        String(100),
        nullable=True
    )
    reality_level: Mapped[int] = mapped_column(
        Integer,
        default=0,
        nullable=False
    )
    
    # Perspective narrative
    narrative_perspective: Mapped[str] = mapped_column(
        String(10),
        default='second',
        nullable=False
    )
    protagonist_name: Mapped[Optional[str]] = mapped_column(
        String(100),
        nullable=True
    )
    protagonist_gender: Mapped[Optional[str]] = mapped_column(
        String(10),
        nullable=True
    )
    
    # Contexte et structure
    pitch: Mapped[Optional[str]] = mapped_column(
        Text,
        nullable=True
    )
    context_answers: Mapped[Optional[dict]] = mapped_column(
        JSON,
        nullable=True
    )
    narrative_skeleton: Mapped[Optional[dict]] = mapped_column(
        JSON,
        nullable=True
    )
    
    # Couverture
    cover_image_url: Mapped[Optional[str]] = mapped_column(
        Text,
        nullable=True
    )
    
    # Mode de jeu
    game_mode: Mapped[str] = mapped_column(
        String(20),
        default='choices',
        nullable=False
    )
    
    # Statut
    status: Mapped[str] = mapped_column(
        String(20),
        default='in_progress',
        nullable=False,
        index=True
    )
    is_published: Mapped[bool] = mapped_column(
        Boolean,
        default=False,
        nullable=False,
        index=True
    )
    publication_status: Mapped[str] = mapped_column(
        String(20),
        default='ongoing',
        nullable=False,
        index=True
    )
    publication_description: Mapped[Optional[str]] = mapped_column(
        Text,
        nullable=True
    )
    published_turn_count: Mapped[int] = mapped_column(
        Integer,
        default=0,
        nullable=False
    )
    
    # Statistiques
    turn_count: Mapped[int] = mapped_column(
        Integer,
        default=0,
        nullable=False
    )
    views_count: Mapped[int] = mapped_column(
        Integer,
        default=0,
        nullable=False
    )
    likes_count: Mapped[int] = mapped_column(
        Integer,
        default=0,
        nullable=False
    )
    
    # Timestamps
    created_at: Mapped[datetime] = mapped_column(
        DateTime,
        default=datetime.utcnow,
        nullable=False
    )
    updated_at: Mapped[datetime] = mapped_column(
        DateTime,
        default=datetime.utcnow,
        onupdate=datetime.utcnow,
        nullable=False
    )
    last_played_at: Mapped[datetime] = mapped_column(
        DateTime,
        default=datetime.utcnow,
        nullable=False
    )
    published_at: Mapped[Optional[datetime]] = mapped_column(
        DateTime,
        nullable=True
    )
    last_chapter_published_at: Mapped[Optional[datetime]] = mapped_column(
        DateTime,
        nullable=True
    )
    
    # Relationships
    user: Mapped["User"] = relationship(
        "User",
        back_populates="stories"
    )
    turns: Mapped[list["StoryTurn"]] = relationship(
        "StoryTurn",
        back_populates="story",
        cascade="all, delete-orphan",
        order_by="StoryTurn.turn_number"
    )
    lorebook: Mapped[Optional["LoreBook"]] = relationship(
        "LoreBook",
        back_populates="story",
        uselist=False,
        cascade="all, delete-orphan"
    )
    likes: Mapped[list["StoryLike"]] = relationship(
        "StoryLike",
        back_populates="story",
        cascade="all, delete-orphan"
    )
    favorites: Mapped[list["StoryFavorite"]] = relationship(
        "StoryFavorite",
        back_populates="story",
        cascade="all, delete-orphan"
    )
    
    def __repr__(self) -> str:
        """Représentation string du Story."""
        return f"<Story '{self.title}' by user {self.user_id}>"
    
    def to_dict(self, include_turns: bool = False) -> dict:
        """Convertit le Story en dictionnaire.
        
        Args:
            include_turns: Inclure les tours de jeu ou non.
        
        Returns:
            Dictionnaire avec les informations de l'histoire.
        """
        data = {
            'id': self.id,
            'user_id': self.user_id,
            'title': self.title,
            'genre': self.genre,
            'epoch': self.epoch,
            'reality_level': self.reality_level,
            'narrative_perspective': self.narrative_perspective,
            'protagonist_name': self.protagonist_name,
            'protagonist_gender': self.protagonist_gender,
            'context_answers': self.context_answers,
            'narrative_skeleton': self.narrative_skeleton,
            'cover_image_url': self.cover_image_url,
            'game_mode': self.game_mode,
            'status': self.status,
            'is_published': self.is_published,
            'publication_status': self.publication_status,
            'publication_description': self.publication_description,
            'published_turn_count': self.published_turn_count,
            'turn_count': self.turn_count,
            'views_count': self.views_count,
            'likes_count': self.likes_count,
            'created_at': self.created_at.isoformat(),
            'updated_at': self.updated_at.isoformat(),
            'last_played_at': self.last_played_at.isoformat(),
            'published_at': self.published_at.isoformat() if self.published_at else None,
            'last_chapter_published_at': self.last_chapter_published_at.isoformat() if self.last_chapter_published_at else None
        }
        
        if include_turns and self.turns:
            data['turns'] = [turn.to_dict() for turn in self.turns]
        
        return data

