from flask import Blueprint, render_template, redirect, url_for, flash, request, current_app
from flask_login import login_user, logout_user, login_required, current_user
from werkzeug.security import generate_password_hash
from datetime import datetime
from app import db
from models import User, Product, Service, Category, Contact, FAQ, SiteSetting, Page, Section
from forms import LoginForm, UserForm, ProductForm, ServiceForm, CategoryForm, SettingsForm, PageForm, SectionForm
from utils import save_image, get_nested_categories

# Create blueprint
admin_bp = Blueprint('admin', __name__)

# Add context processor for admin templates
@admin_bp.context_processor
def inject_now():
    """Add current datetime to all admin templates"""
    return {'now': datetime.now()}

# Middleware to check if user is admin
@admin_bp.before_request
def check_admin():
    """Ensure user is admin for all admin routes except login/logout"""
    if request.endpoint and 'admin' in request.endpoint and not request.endpoint.endswith('login') and not request.endpoint.endswith('logout'):
        if not current_user.is_authenticated or not current_user.is_admin():
            flash('Accès refusé. Vous devez être administrateur.', 'danger')
            return redirect(url_for('admin.login'))

@admin_bp.route('/login', methods=['GET', 'POST'])
def login():
    """Admin login page"""
    if current_user.is_authenticated:
        return redirect(url_for('admin.dashboard'))
    
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user and user.check_password(form.password.data) and user.is_admin():
            login_user(user, remember=form.remember_me.data)
            next_page = request.args.get('next')
            flash('Connexion réussie.', 'success')
            return redirect(next_page or url_for('admin.dashboard'))
        else:
            flash('Nom d\'utilisateur ou mot de passe incorrect.', 'danger')
    
    return render_template('admin/login.html', form=form, title="Administration - Connexion")

@admin_bp.route('/logout')
@login_required
def logout():
    """Admin logout"""
    logout_user()
    flash('Vous avez été déconnecté.', 'info')
    return redirect(url_for('admin.login'))

@admin_bp.route('/')
@login_required
def dashboard():
    """Admin dashboard"""
    # Collect statistics for dashboard
    product_count = Product.query.count()
    service_count = Service.query.count()
    category_count = Category.query.count()
    unread_message_count = Contact.query.filter_by(is_read=False).count()
    
    # Get recent contacts
    recent_contacts = Contact.query.order_by(Contact.created_at.desc()).limit(5).all()
    
    return render_template('admin/dashboard.html', 
                          product_count=product_count,
                          service_count=service_count,
                          category_count=category_count,
                          unread_message_count=unread_message_count,
                          recent_contacts=recent_contacts,
                          title="Administration - Tableau de bord")

# Category Management
@admin_bp.route('/categories')
@login_required
def categories():
    """List all categories"""
    categories = Category.query.all()
    return render_template('admin/categories.html', categories=categories, title="Administration - Catégories")

@admin_bp.route('/categories/add', methods=['GET', 'POST'])
@login_required
def add_category():
    """Add a new category"""
    form = CategoryForm()
    
    # Get all categories for parent dropdown
    all_categories = Category.query.all()
    nested_categories = [(0, 'Aucun (catégorie principale)')]
    nested_categories.extend(get_nested_categories(all_categories))
    form.parent_id.choices = nested_categories
    
    if form.validate_on_submit():
        parent_id = form.parent_id.data if form.parent_id.data != 0 else None
        category = Category(
            name=form.name.data,
            description=form.description.data,
            parent_id=parent_id
        )
        db.session.add(category)
        db.session.commit()
        
        flash('Catégorie ajoutée avec succès.', 'success')
        return redirect(url_for('admin.categories'))
    
    return render_template('admin/edit_category.html', form=form, title="Administration - Ajouter une catégorie")

@admin_bp.route('/categories/edit/<int:id>', methods=['GET', 'POST'])
@login_required
def edit_category(id):
    """Edit a category"""
    category = Category.query.get_or_404(id)
    form = CategoryForm(obj=category)
    
    # Get all categories for parent dropdown (excluding self and children)
    all_categories = Category.query.filter(Category.id != id).all()
    nested_categories = [(0, 'Aucun (catégorie principale)')]
    nested_categories.extend(get_nested_categories(all_categories))
    form.parent_id.choices = nested_categories
    
    if form.validate_on_submit():
        category.name = form.name.data
        category.description = form.description.data
        category.parent_id = form.parent_id.data if form.parent_id.data != 0 else None
        
        db.session.commit()
        flash('Catégorie mise à jour avec succès.', 'success')
        return redirect(url_for('admin.categories'))
    
    # Set form default values
    if category.parent_id:
        form.parent_id.default = category.parent_id
    else:
        form.parent_id.default = 0
    form.process()
    
    return render_template('admin/edit_category.html', form=form, category=category, title="Administration - Modifier une catégorie")

@admin_bp.route('/categories/delete/<int:id>', methods=['POST'])
@login_required
def delete_category(id):
    """Delete a category"""
    category = Category.query.get_or_404(id)
    
    # Check if category has products
    if category.products:
        flash('Impossible de supprimer cette catégorie car elle contient des produits.', 'danger')
        return redirect(url_for('admin.categories'))
    
    # Check if category has subcategories
    if category.subcategories:
        flash('Impossible de supprimer cette catégorie car elle contient des sous-catégories.', 'danger')
        return redirect(url_for('admin.categories'))
    
    db.session.delete(category)
    db.session.commit()
    
    flash('Catégorie supprimée avec succès.', 'success')
    return redirect(url_for('admin.categories'))

# Product Management
@admin_bp.route('/products')
@login_required
def products():
    """List all products"""
    products = Product.query.all()
    return render_template('admin/products.html', products=products, title="Administration - Produits")

@admin_bp.route('/products/add', methods=['GET', 'POST'])
@login_required
def add_product():
    """Add a new product"""
    form = ProductForm()
    
    # Get all categories for dropdown
    all_categories = Category.query.all()
    # Add default option and nested categories
    form.category_id.choices = [(0, 'Sélectionner une catégorie')] + get_nested_categories(all_categories)
    
    if form.validate_on_submit():
        # Save uploaded image
        image_path = save_image(form.image.data, folder='uploads/products') if form.image.data else None
        
        product = Product(
            name=form.name.data,
            description=form.description.data,
            price=form.price.data,
            image_url=image_path,
            category_id=form.category_id.data,
            is_available=form.is_available.data,
            condition=form.condition.data
        )
        db.session.add(product)
        db.session.commit()
        
        flash('Produit ajouté avec succès.', 'success')
        return redirect(url_for('admin.products'))
    
    return render_template('admin/edit_product.html', form=form, title="Administration - Ajouter un produit")

@admin_bp.route('/products/edit/<int:id>', methods=['GET', 'POST'])
@login_required
def edit_product(id):
    """Edit a product"""
    product = Product.query.get_or_404(id)
    form = ProductForm(obj=product)
    
    # Get all categories for dropdown
    all_categories = Category.query.all()
    # Add default option and nested categories
    form.category_id.choices = [(0, 'Sélectionner une catégorie')] + get_nested_categories(all_categories)
    
    if form.validate_on_submit():
        product.name = form.name.data
        product.description = form.description.data
        product.price = form.price.data
        product.category_id = form.category_id.data
        product.is_available = form.is_available.data
        product.condition = form.condition.data
        
        # Update image if new one uploaded
        if form.image.data:
            image_path = save_image(form.image.data, folder='uploads/products')
            if image_path:
                product.image_url = image_path
        
        db.session.commit()
        flash('Produit mis à jour avec succès.', 'success')
        return redirect(url_for('admin.products'))
    
    return render_template('admin/edit_product.html', form=form, product=product, title="Administration - Modifier un produit")

@admin_bp.route('/products/delete/<int:id>', methods=['POST'])
@login_required
def delete_product(id):
    """Delete a product"""
    product = Product.query.get_or_404(id)
    db.session.delete(product)
    db.session.commit()
    
    flash('Produit supprimé avec succès.', 'success')
    return redirect(url_for('admin.products'))

# Service Management
@admin_bp.route('/services')
@login_required
def services():
    """List all services"""
    services = Service.query.all()
    return render_template('admin/services.html', services=services, title="Administration - Services")

@admin_bp.route('/services/add', methods=['GET', 'POST'])
@login_required
def add_service():
    """Add a new service"""
    form = ServiceForm()
    
    if form.validate_on_submit():
        # Save uploaded image
        image_path = save_image(form.image.data, folder='uploads/services') if form.image.data else None
        
        service = Service(
            name=form.name.data,
            description=form.description.data,
            image_url=image_path,
            is_active=form.is_active.data
        )
        db.session.add(service)
        db.session.commit()
        
        flash('Service ajouté avec succès.', 'success')
        return redirect(url_for('admin.services'))
    
    return render_template('admin/edit_service.html', form=form, title="Administration - Ajouter un service")

@admin_bp.route('/services/edit/<int:id>', methods=['GET', 'POST'])
@login_required
def edit_service(id):
    """Edit a service"""
    service = Service.query.get_or_404(id)
    form = ServiceForm(obj=service)
    
    if form.validate_on_submit():
        service.name = form.name.data
        service.description = form.description.data
        service.is_active = form.is_active.data
        
        # Update image if new one uploaded
        if form.image.data:
            image_path = save_image(form.image.data, folder='uploads/services')
            if image_path:
                service.image_url = image_path
        
        db.session.commit()
        flash('Service mis à jour avec succès.', 'success')
        return redirect(url_for('admin.services'))
    
    return render_template('admin/edit_service.html', form=form, service=service, title="Administration - Modifier un service")

@admin_bp.route('/services/delete/<int:id>', methods=['POST'])
@login_required
def delete_service(id):
    """Delete a service"""
    service = Service.query.get_or_404(id)
    db.session.delete(service)
    db.session.commit()
    
    flash('Service supprimé avec succès.', 'success')
    return redirect(url_for('admin.services'))

# Contact Management
@admin_bp.route('/contacts')
@login_required
def contacts():
    """List all contact messages"""
    contacts = Contact.query.order_by(Contact.created_at.desc()).all()
    return render_template('admin/contacts.html', contacts=contacts, title="Administration - Messages")

@admin_bp.route('/contacts/view/<int:id>')
@login_required
def view_contact(id):
    """View a contact message and mark as read"""
    contact = Contact.query.get_or_404(id)
    contact.is_read = True
    db.session.commit()
    
    return render_template('admin/view_contact.html', contact=contact, title="Administration - Voir le message")

@admin_bp.route('/contacts/delete/<int:id>', methods=['POST'])
@login_required
def delete_contact(id):
    """Delete a contact message"""
    contact = Contact.query.get_or_404(id)
    db.session.delete(contact)
    db.session.commit()
    
    flash('Message supprimé avec succès.', 'success')
    return redirect(url_for('admin.contacts'))

# User Management
@admin_bp.route('/users')
@login_required
def users():
    """List all users"""
    all_users = User.query.all()
    return render_template('admin/users.html', users=all_users, title="Administration - Utilisateurs")

@admin_bp.route('/users/add', methods=['GET', 'POST'])
@login_required
def add_user():
    """Add a new user"""
    form = UserForm()
    
    if form.validate_on_submit():
        user = User(
            username=form.username.data,
            email=form.email.data,
            role=form.role.data
        )
        user.set_password(form.password.data)
        
        db.session.add(user)
        db.session.commit()
        
        flash('Utilisateur ajouté avec succès.', 'success')
        return redirect(url_for('admin.users'))
    
    return render_template('admin/edit_user.html', form=form, title="Administration - Ajouter un utilisateur")

@admin_bp.route('/users/edit/<int:id>', methods=['GET', 'POST'])
@login_required
def edit_user(id):
    """Edit a user"""
    user = User.query.get_or_404(id)
    
    # To avoid ValidationError for existing email/username
    form = UserForm(obj=user)
    form.user_id = user.id
    
    if form.validate_on_submit():
        user.username = form.username.data
        user.email = form.email.data
        user.role = form.role.data
        
        # Update password if provided
        if form.password.data:
            user.set_password(form.password.data)
        
        db.session.commit()
        flash('Utilisateur mis à jour avec succès.', 'success')
        return redirect(url_for('admin.users'))
    
    # Remove password data for security
    form.password.data = ''
    form.confirm_password.data = ''
    
    return render_template('admin/edit_user.html', form=form, user=user, title="Administration - Modifier un utilisateur")

@admin_bp.route('/users/delete/<int:id>', methods=['POST'])
@login_required
def delete_user(id):
    """Delete a user"""
    user = User.query.get_or_404(id)
    
    # Prevent deleting yourself
    if user.id == current_user.id:
        flash('Vous ne pouvez pas supprimer votre propre compte.', 'danger')
        return redirect(url_for('admin.users'))
    
    db.session.delete(user)
    db.session.commit()
    
    flash('Utilisateur supprimé avec succès.', 'success')
    return redirect(url_for('admin.users'))

# Site Settings
@admin_bp.route('/settings', methods=['GET', 'POST'])
@login_required
def settings():
    """Edit site settings"""
    form = SettingsForm()
    
    # Get current settings
    if request.method == 'GET':
        form.company_name.data = SiteSetting.get('company_name', '')
        form.company_description.data = SiteSetting.get('company_description', '')
        form.company_address.data = SiteSetting.get('company_address', '')
        form.company_email.data = SiteSetting.get('company_email', '')
        form.company_phone.data = SiteSetting.get('company_phone', '')
    
    if form.validate_on_submit():
        # Update settings
        SiteSetting.set('company_name', form.company_name.data, 'Company name')
        SiteSetting.set('company_description', form.company_description.data, 'Company description')
        SiteSetting.set('company_address', form.company_address.data, 'Company address')
        SiteSetting.set('company_email', form.company_email.data, 'Company email')
        SiteSetting.set('company_phone', form.company_phone.data, 'Company phone')
        
        flash('Paramètres mis à jour avec succès.', 'success')
        return redirect(url_for('admin.settings'))
    
    return render_template('admin/settings.html', form=form, title="Administration - Paramètres")

# Page Management
@admin_bp.route('/pages')
@login_required
def pages():
    """List all pages"""
    pages = Page.query.all()
    return render_template('admin/pages.html', pages=pages, title="Administration - Pages")

@admin_bp.route('/pages/add', methods=['GET', 'POST'])
@login_required
def add_page():
    """Add a new page"""
    form = PageForm()
    
    if form.validate_on_submit():
        page = Page(
            title=form.title.data,
            slug=form.slug.data,
            description=form.description.data,
            is_active=form.is_active.data,
            meta_keywords=form.meta_keywords.data,
            meta_description=form.meta_description.data
        )
        db.session.add(page)
        db.session.commit()
        
        flash('Page ajoutée avec succès.', 'success')
        return redirect(url_for('admin.pages'))
    
    return render_template('admin/edit_page.html', form=form, title="Administration - Ajouter une page")

@admin_bp.route('/pages/edit/<int:id>', methods=['GET', 'POST'])
@login_required
def edit_page(id):
    """Edit a page"""
    page = Page.query.get_or_404(id)
    form = PageForm(obj=page)
    
    # Set page_id for validation
    form.page_id = page.id
    
    if form.validate_on_submit():
        page.title = form.title.data
        page.slug = form.slug.data
        page.description = form.description.data
        page.is_active = form.is_active.data
        page.meta_keywords = form.meta_keywords.data
        page.meta_description = form.meta_description.data
        
        db.session.commit()
        flash('Page mise à jour avec succès.', 'success')
        return redirect(url_for('admin.pages'))
    
    return render_template('admin/edit_page.html', form=form, page=page, title="Administration - Modifier une page")

@admin_bp.route('/pages/delete/<int:id>', methods=['POST'])
@login_required
def delete_page(id):
    """Delete a page"""
    page = Page.query.get_or_404(id)
    
    # Check if page has sections
    if page.sections:
        flash('Impossible de supprimer cette page car elle contient des sections.', 'danger')
        return redirect(url_for('admin.pages'))
    
    db.session.delete(page)
    db.session.commit()
    
    flash('Page supprimée avec succès.', 'success')
    return redirect(url_for('admin.pages'))

# Section Management
@admin_bp.route('/sections')
@login_required
def sections():
    """List all sections"""
    sections = Section.query.all()
    return render_template('admin/sections.html', sections=sections, title="Administration - Sections")

@admin_bp.route('/sections/add', methods=['GET', 'POST'])
@login_required
def add_section():
    """Add a new section"""
    form = SectionForm()
    
    # Get all pages for dropdown
    pages = Page.query.all()
    form.page_id.choices = [(page.id, page.title) for page in pages]
    
    if form.validate_on_submit():
        # Save uploaded image
        image_path = save_image(form.image.data, folder='uploads/sections') if form.image.data else None
        
        section = Section(
            page_id=form.page_id.data,
            title=form.title.data,
            content=form.content.data,
            section_type=form.section_type.data,
            order=form.order.data,
            is_active=form.is_active.data,
            background_color=form.background_color.data,
            css_class=form.css_class.data,
            image_url=image_path
        )
        db.session.add(section)
        db.session.commit()
        
        flash('Section ajoutée avec succès.', 'success')
        return redirect(url_for('admin.sections'))
    
    return render_template('admin/edit_section.html', form=form, title="Administration - Ajouter une section")

@admin_bp.route('/sections/edit/<int:id>', methods=['GET', 'POST'])
@login_required
def edit_section(id):
    """Edit a section"""
    section = Section.query.get_or_404(id)
    form = SectionForm(obj=section)
    
    # Get all pages for dropdown
    pages = Page.query.all()
    form.page_id.choices = [(page.id, page.title) for page in pages]
    
    if form.validate_on_submit():
        section.page_id = form.page_id.data
        section.title = form.title.data
        section.content = form.content.data
        section.section_type = form.section_type.data
        section.order = form.order.data
        section.is_active = form.is_active.data
        section.background_color = form.background_color.data
        section.css_class = form.css_class.data
        
        # Update image if new one uploaded
        if form.image.data:
            image_path = save_image(form.image.data)
            if image_path:
                section.image_url = image_path
        
        db.session.commit()
        flash('Section mise à jour avec succès.', 'success')
        return redirect(url_for('admin.sections'))
    
    return render_template('admin/edit_section.html', form=form, section=section, title="Administration - Modifier une section")

@admin_bp.route('/sections/delete/<int:id>', methods=['POST'])
@login_required
def delete_section(id):
    """Delete a section"""
    section = Section.query.get_or_404(id)
    db.session.delete(section)
    db.session.commit()
    
    flash('Section supprimée avec succès.', 'success')
    return redirect(url_for('admin.sections'))
