"""Routes pour la gestion des histoires."""

from flask import Blueprint, request, jsonify
from flask_jwt_extended import jwt_required, get_jwt_identity
from pydantic import ValidationError

from services.story_service import StoryService
from schemas.story import StoryCreateSchema, StoryUpdateSchema, StoryPublishSchema

bp = Blueprint('stories', __name__)


@bp.route('', methods=['POST'])
@jwt_required()
def create_story() -> tuple:
    """Crée une nouvelle histoire.
    
    Headers:
        Authorization: Bearer <access_token>
    
    Body (JSON):
        title: Titre de l'histoire.
        genre: Genre littéraire (optionnel).
        epoch: Époque (optionnel).
        reality_level: Niveau de réalité 0-100 (optionnel).
        narrative_perspective: 'second' ou 'third' (défaut: 'second').
        protagonist_name: Nom du protagoniste si 3ème personne (optionnel).
        protagonist_gender: 'he' ou 'she' si 3ème personne (optionnel).
        game_mode: 'choices' ou 'free' (défaut: 'choices').
    
    Returns:
        Tuple (response, status_code).
    """
    try:
        user_id = get_jwt_identity()
        
        # Valider les données
        data = StoryCreateSchema(**request.get_json())
        
        # Créer l'histoire
        story = StoryService.create_story(user_id, data)
        
        return jsonify({
            'message': 'Histoire créée avec succès',
            'story': story.to_dict()
        }), 201
        
    except ValidationError as e:
        return jsonify({
            'error': 'validation_error',
            'message': 'Données invalides',
            'details': e.errors()
        }), 400
        
    except Exception as e:
        return jsonify({
            'error': 'server_error',
            'message': 'Une erreur est survenue lors de la création'
        }), 500


@bp.route('', methods=['GET'])
@jwt_required()
def get_user_stories() -> tuple:
    """Récupère toutes les histoires de l'utilisateur connecté.
    
    Headers:
        Authorization: Bearer <access_token>
    
    Returns:
        Tuple (response, status_code).
    """
    try:
        user_id = get_jwt_identity()
        
        stories = StoryService.get_user_stories(user_id)
        
        return jsonify({
            'stories': [story.to_dict() for story in stories],
            'count': len(stories)
        }), 200
        
    except Exception as e:
        return jsonify({
            'error': 'server_error',
            'message': 'Une erreur est survenue'
        }), 500


@bp.route('/<story_id>', methods=['GET'])
@jwt_required()
def get_story(story_id: str) -> tuple:
    """Récupère une histoire par son ID.
    
    Headers:
        Authorization: Bearer <access_token>
    
    Args:
        story_id: ID de l'histoire.
    
    Returns:
        Tuple (response, status_code).
    """
    try:
        user_id = get_jwt_identity()
        
        story = StoryService.get_story_by_id(story_id)
        
        if not story:
            return jsonify({
                'error': 'story_not_found',
                'message': 'Histoire non trouvée'
            }), 404
        
        # Vérifier que l'utilisateur est le propriétaire
        if story.user_id != user_id:
            return jsonify({
                'error': 'forbidden',
                'message': 'Vous n\'avez pas accès à cette histoire'
            }), 403
        
        return jsonify({
            'story': story.to_dict(include_turns=False)
        }), 200
        
    except Exception as e:
        return jsonify({
            'error': 'server_error',
            'message': 'Une erreur est survenue'
        }), 500


@bp.route('/<story_id>', methods=['PATCH'])
@jwt_required()
def update_story(story_id: str) -> tuple:
    """Met à jour une histoire.
    
    Headers:
        Authorization: Bearer <access_token>
    
    Args:
        story_id: ID de l'histoire.
    
    Body (JSON):
        title: Nouveau titre (optionnel).
        status: Nouveau statut (optionnel).
        game_mode: Nouveau mode de jeu (optionnel).
        publication_description: Description pour galerie (optionnel).
    
    Returns:
        Tuple (response, status_code).
    """
    try:
        user_id = get_jwt_identity()
        
        story = StoryService.get_story_by_id(story_id)
        
        if not story:
            return jsonify({
                'error': 'story_not_found',
                'message': 'Histoire non trouvée'
            }), 404
        
        # Vérifier que l'utilisateur est le propriétaire
        if story.user_id != user_id:
            return jsonify({
                'error': 'forbidden',
                'message': 'Vous n\'avez pas accès à cette histoire'
            }), 403
        
        # Valider les données
        data = StoryUpdateSchema(**request.get_json())
        
        # Mettre à jour
        story = StoryService.update_story(story, data)
        
        return jsonify({
            'message': 'Histoire mise à jour',
            'story': story.to_dict()
        }), 200
        
    except ValidationError as e:
        return jsonify({
            'error': 'validation_error',
            'message': 'Données invalides',
            'details': e.errors()
        }), 400
        
    except Exception as e:
        return jsonify({
            'error': 'server_error',
            'message': 'Une erreur est survenue'
        }), 500


@bp.route('/<story_id>', methods=['DELETE'])
@jwt_required()
def delete_story(story_id: str) -> tuple:
    """Supprime une histoire.
    
    Headers:
        Authorization: Bearer <access_token>
    
    Args:
        story_id: ID de l'histoire.
    
    Returns:
        Tuple (response, status_code).
    """
    try:
        user_id = get_jwt_identity()
        
        story = StoryService.get_story_by_id(story_id)
        
        if not story:
            return jsonify({
                'error': 'story_not_found',
                'message': 'Histoire non trouvée'
            }), 404
        
        # Vérifier que l'utilisateur est le propriétaire
        if story.user_id != user_id:
            return jsonify({
                'error': 'forbidden',
                'message': 'Vous n\'avez pas accès à cette histoire'
            }), 403
        
        # Supprimer
        StoryService.delete_story(story)
        
        return jsonify({
            'message': 'Histoire supprimée'
        }), 200
        
    except Exception as e:
        return jsonify({
            'error': 'server_error',
            'message': 'Une erreur est survenue'
        }), 500


@bp.route('/<story_id>/publish', methods=['POST'])
@jwt_required()
def publish_story(story_id: str) -> tuple:
    """Publie une histoire (ou continue la publication).
    
    Headers:
        Authorization: Bearer <access_token>
    
    Args:
        story_id: ID de l'histoire.
    
    Body (JSON):
        publication_status: 'ongoing' ou 'finished' (défaut: 'ongoing').
        publication_description: Description pour galerie (optionnel).
    
    Returns:
        Tuple (response, status_code).
    """
    try:
        user_id = get_jwt_identity()
        
        story = StoryService.get_story_by_id(story_id)
        
        if not story:
            return jsonify({
                'error': 'story_not_found',
                'message': 'Histoire non trouvée'
            }), 404
        
        # Vérifier que l'utilisateur est le propriétaire
        if story.user_id != user_id:
            return jsonify({
                'error': 'forbidden',
                'message': 'Vous n\'avez pas accès à cette histoire'
            }), 403
        
        # Valider les données
        data = StoryPublishSchema(**request.get_json())
        
        # Mettre à jour la description si fournie
        if data.publication_description:
            story.publication_description = data.publication_description
        
        # Publier
        story = StoryService.publish_story(story, data.publication_status)
        
        return jsonify({
            'message': 'Histoire publiée',
            'story': story.to_dict()
        }), 200
        
    except ValidationError as e:
        return jsonify({
            'error': 'validation_error',
            'message': 'Données invalides',
            'details': e.errors()
        }), 400
        
    except Exception as e:
        return jsonify({
            'error': 'server_error',
            'message': 'Une erreur est survenue'
        }), 500

