"""
Parts Routes - GMAO Collège
Gestion des pièces détachées
"""
from flask import Blueprint, render_template, request, flash, redirect, url_for
from flask_login import login_required, current_user
from app_new.extensions import db
from ..core.models.company import Part, PartStockMovement


def _record_movement(part, new_quantity, movement_type, reason):
    before = int(part.quantity or 0)
    after = int(new_quantity)
    if after < 0:
        raise ValueError('Le stock ne peut pas devenir négatif.')
    if after == before:
        return None
    movement = PartStockMovement(
        part=part, user_id=current_user.id, movement_type=movement_type,
        quantity_delta=after - before, quantity_before=before,
        quantity_after=after, reason=(reason or '').strip() or 'Ajustement manuel',
    )
    part.quantity = after
    db.session.add(movement)
    return movement

parts_bp = Blueprint('parts', __name__)

@parts_bp.route('/')
@login_required
def index():
    """Liste des pièces."""
    page = request.args.get('page', 1, type=int)
    parts = Part.query.order_by(Part.name).paginate(page=page, per_page=20)
    return render_template('parts/index.html', parts=parts)

@parts_bp.route('/<int:id>')
@login_required
def detail(id):
    """Détail d'une pièce."""
    part = Part.query.get_or_404(id)
    movements = part.stock_movements.order_by(PartStockMovement.created_at.desc()).limit(100).all()
    return render_template('parts/detail.html', part=part, movements=movements)


@parts_bp.route('/<int:id>/edit', methods=['GET', 'POST'])
@login_required
def edit(id):
    """Modifier une pièce."""
    part = Part.query.get_or_404(id)
    if request.method == 'POST':
        part.name = request.form.get('name')
        part.reference = request.form.get('reference')
        try:
            _record_movement(part, request.form.get('quantity', type=int, default=0),
                             'correction', request.form.get('stock_reason'))
        except ValueError as exc:
            flash(str(exc), 'danger')
            return render_template('parts/form.html', part=part), 400
        part.unit = request.form.get('unit')
        part.unit_price = request.form.get('unit_price', type=float)
        part.supplier = request.form.get('supplier')
        db.session.commit()
        flash('Pièce modifiée avec succès.', 'success')
        return redirect(url_for('parts.detail', id=part.id))
    return render_template('parts/form.html', part=part)


@parts_bp.route('/new', methods=['GET', 'POST'])
@login_required
def create():
    """Créer une pièce."""
    if request.method == 'POST':
        quantity = max(0, request.form.get('quantity', type=int, default=0))
        part = Part(
            name=request.form.get('name'),
            reference=request.form.get('reference'),
            quantity=0,
            unit=request.form.get('unit')
        )
        part.unit_price = request.form.get('unit_price', type=float)
        part.supplier = request.form.get('supplier')
        db.session.add(part)
        db.session.flush()
        if quantity:
            _record_movement(part, quantity, 'entree', 'Stock initial')
        db.session.commit()
        flash('Pièce créée avec succès.', 'success')
        return redirect(url_for('parts.index'))
    
    return render_template('parts/new.html')


@parts_bp.route('/<int:id>/movement', methods=['POST'])
@login_required
def movement(id):
    """Enregistre une entrée, une sortie ou un inventaire sans écraser l'historique."""
    part = Part.query.get_or_404(id)
    movement_type = request.form.get('movement_type')
    amount = request.form.get('quantity', type=int)
    reason = (request.form.get('reason') or '').strip()
    if movement_type not in {'entree', 'sortie', 'inventaire'} or amount is None or amount < 0 or not reason:
        flash('Type, quantité positive et motif sont obligatoires.', 'danger')
        return redirect(url_for('parts.detail', id=id))
    new_quantity = amount if movement_type == 'inventaire' else int(part.quantity or 0) + (amount if movement_type == 'entree' else -amount)
    try:
        _record_movement(part, new_quantity, movement_type, reason)
        db.session.commit()
        flash('Mouvement de stock enregistré.', 'success')
    except ValueError as exc:
        db.session.rollback()
        flash(str(exc), 'danger')
    return redirect(url_for('parts.detail', id=id))
