from flask import Blueprint, render_template, redirect, url_for, flash, request, current_app
from flask_login import login_user, login_required, logout_user, current_user
from urllib.parse import urlparse
from app.models import User, Car, Tour, Booking, VehicleCategory, TourDay
from .forms import LoginForm, CarForm, TourForm, BlogForm
from app import db, is_maintenance_mode
from werkzeug.utils import secure_filename
from flask_wtf import FlaskForm
from app.models import Blog
from app.models import TourParentCategory, TourSubCategory
from .forms import TourParentCategoryForm, TourSubCategoryForm
from slugify import slugify 
import os
from . import admin_blueprint
import logging

logger = logging.getLogger(__name__)

@admin_blueprint.route('/')
@login_required
def index():
    return render_template('admin_dashboard.html')

@admin_blueprint.route('/login', methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return redirect(url_for('admin_blueprint.index'))
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user is None or not user.check_password(form.password.data):
            flash('Invalid username or password', 'danger')
            return redirect(url_for('admin_blueprint.login'))
        login_user(user)
        next_page = request.args.get('next')
        if not next_page or urlparse(next_page).netloc != '':
            next_page = url_for('admin_blueprint.index')
        return redirect(next_page)
    return render_template('login.html', title='Sign In', form=form)

@admin_blueprint.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('main.home'))

@admin_blueprint.route('/cars', methods=['GET', 'POST'])
@login_required
def manage_cars():
    form = CarForm()
    if form.validate_on_submit():
        filename = None
        if form.image.data:
            filename = secure_filename(form.image.data.filename)
            form.image.data.save(os.path.join(current_app.config['UPLOAD_FOLDER'], filename))
        
        category = VehicleCategory[form.category.data]
        
        car = Car(
            name=form.name.data,
            capacity=form.capacity.data,
            price_per_day=form.price_per_day.data,
            image=filename,
            category=category,
            has_ac=form.has_ac.data,
            has_usb=form.has_usb.data,
            has_player=form.has_player.data,
            has_bluetooth=form.has_bluetooth.data,
            luggage_space=form.luggage_space.data
        )
        try:
            db.session.add(car)
            db.session.commit()
            flash('Car added successfully', 'success')
            return redirect(url_for('admin_blueprint.manage_cars'))
        except Exception as e:
            db.session.rollback()
            flash(f'Error adding car: {str(e)}', 'error')
            current_app.logger.error(f"Error adding car: {str(e)}")
    
    cars = Car.query.all()
    return render_template('manage_cars.html', form=form, cars=cars)

# @admin_blueprint.route('/cars/edit/<int:id>', methods=['GET', 'POST'])
# @login_required
# def edit_car(id):
#     car = Car.query.get_or_404(id)
#     form = CarForm(obj=car)
#     if form.validate_on_submit():
#         if form.image.data:
#             filename = secure_filename(form.image.data.filename)
#             form.image.data.save(os.path.join(current_app.config['UPLOAD_FOLDER'], filename))
#             car.image = filename
#         form.populate_obj(car)
#         try:
#             db.session.commit()
#             flash('Car updated successfully', 'success')
#             return redirect(url_for('admin_blueprint.manage_cars'))
#         except Exception as e:
#             db.session.rollback()
#             flash(f'Error updating car: {str(e)}', 'error')
#             current_app.logger.error(f"Error updating car: {str(e)}")
#     return render_template('edit_car.html', form=form, car=car)


@admin_blueprint.route('/cars/edit/<int:id>', methods=['GET', 'POST'])
@login_required
def edit_car(id):
    car = Car.query.get_or_404(id)
    form = CarForm(obj=car)
    
    if form.validate_on_submit():
        try:
            # Update basic fields first
            car.name = form.name.data
            car.capacity = form.capacity.data
            car.price_per_day = form.price_per_day.data
            car.category = VehicleCategory[form.category.data]
            car.has_ac = form.has_ac.data
            car.has_usb = form.has_usb.data
            car.has_player = form.has_player.data
            car.has_bluetooth = form.has_bluetooth.data
            car.luggage_space = form.luggage_space.data
            
            # Handle image upload separately
            if form.image.data:
                filename = secure_filename(form.image.data.filename)
                image_path = os.path.join(current_app.config['UPLOAD_FOLDER'], filename)
                form.image.data.save(image_path)
                
                # Delete old image if it exists
                if car.image:
                    old_image_path = os.path.join(current_app.config['UPLOAD_FOLDER'], car.image)
                    if os.path.exists(old_image_path):
                        os.remove(old_image_path)
                
                car.image = filename
            
            db.session.commit()
            flash('Car updated successfully', 'success')
            return redirect(url_for('admin_blueprint.manage_cars'))
            
        except Exception as e:
            db.session.rollback()
            flash(f'Error updating car: {str(e)}', 'error')
            current_app.logger.error(f"Error updating car: {str(e)}")
    
    return render_template('edit_car.html', form=form, car=car)

@admin_blueprint.route('/cars/delete/<int:id>', methods=['POST'])
@login_required
def delete_car(id):
    form = FlaskForm()
    if form.validate_on_submit():
        car = Car.query.get_or_404(id)
        try:
            db.session.delete(car)
            db.session.commit()
            flash('Car deleted successfully', 'success')
        except Exception as e:
            db.session.rollback()
            flash(f'Error deleting car: {str(e)}', 'error')
            current_app.logger.error(f"Error deleting car: {str(e)}")
    return redirect(url_for('admin_blueprint.manage_cars'))

@admin_blueprint.route('/tours')
@login_required
def manage_tours():
    multi_day_tours = Tour.query.all()
    form = FlaskForm()
    return render_template('manage_tours.html', multi_day_tours=multi_day_tours, form=form)

@admin_blueprint.route('/tours/add', methods=['GET', 'POST'])
@login_required
def add_tour():
    form = TourForm()
    if form.validate_on_submit():
        try:
            filename = None
            if form.image.data:
                filename = secure_filename(form.image.data.filename)
                form.image.data.save(os.path.join(current_app.config['UPLOAD_FOLDER'], filename))
            
            subcategory = TourSubCategory.query.get(form.subcategory.data)
            parent_category = subcategory.parent_category if subcategory else None
            
            title = f"{form.title.data} - {parent_category.name}" if parent_category else form.title.data
            
            tour = Tour(
                title=title,
                subtitle=form.subtitle.data,
                description=form.description.data,
                itinerary=form.itinerary.data,
                inclusions=form.inclusions.data,
                exclusions=form.exclusions.data,
                additional_info=form.additional_info.data,
                image=filename,
                subcategory_id=form.subcategory.data,
                duration=form.duration.data,
            )
            
            for index, day_form in enumerate(form.tour_days):
                tour_day = TourDay(
                    title=day_form.form.title.data,
                    description=day_form.form.description.data,
                    day_number=index + 1
                )
                tour.tour_days.append(tour_day)
            
            db.session.add(tour)
            db.session.commit()
            flash('Tour added successfully', 'success')
            return redirect(url_for('admin_blueprint.manage_tours'))
        except Exception as e:
            db.session.rollback()
            flash(f'Error adding tour: {str(e)}', 'error')
            current_app.logger.error(f"Error adding tour: {str(e)}")
    
    if form.errors:
        for field, errors in form.errors.items():
            for error in errors:
                field_label = getattr(form, field).label.text if hasattr(getattr(form, field), 'label') else field
                flash(f"{field_label}: {error}", 'error')
    
    return render_template('add_tour.html', form=form)

# @admin_blueprint.route('/tours/edit/<int:id>', methods=['GET', 'POST'])
# @login_required
# def edit_tour(id):
#     tour = Tour.query.get_or_404(id)
#     form = TourForm(obj=tour)
    
#     if form.validate_on_submit():
#         try:
#             form.populate_obj(tour)
            
#             # Handle file upload
#             if form.image.data:
#                 filename = secure_filename(form.image.data.filename)
#                 file_path = os.path.join(current_app.config['UPLOAD_FOLDER'], filename)
#                 form.image.data.save(file_path)
#                 tour.image = filename
            
#             db.session.commit()
#             flash('Tour updated successfully', 'success')
#             return redirect(url_for('admin_blueprint.manage_tours'))
#         except Exception as e:
#             db.session.rollback()
#             logger.exception(f"Error updating tour: {str(e)}")
#             flash(f'Error updating tour: {str(e)}', 'error')
    
#     return render_template('edit_tour.html', form=form, tour=tour)



@admin_blueprint.route('/tours/edit/<int:id>', methods=['GET', 'POST'])
@login_required
def edit_tour(id):
    tour = Tour.query.get_or_404(id)
    form = TourForm(obj=tour)
    
    if form.validate_on_submit():
        try:
            # Handle file upload first
            if form.image.data and hasattr(form.image.data, 'filename'):
                filename = secure_filename(form.image.data.filename)
                file_path = os.path.join(current_app.config['UPLOAD_FOLDER'], filename)
                form.image.data.save(file_path)
                
                # Delete old image if it exists
                if tour.image:
                    old_image_path = os.path.join(current_app.config['UPLOAD_FOLDER'], tour.image)
                    if os.path.exists(old_image_path):
                        try:
                            os.remove(old_image_path)
                        except Exception as e:
                            logger.warning(f"Could not delete old image: {str(e)}")
                
                tour.image = filename

            # Update other fields
            tour.title = form.title.data
            tour.subtitle = form.subtitle.data
            tour.description = form.description.data
            tour.itinerary = form.itinerary.data
            tour.inclusions = form.inclusions.data
            tour.exclusions = form.exclusions.data
            tour.additional_info = form.additional_info.data
            tour.subcategory_id = form.subcategory.data
            tour.duration = form.duration.data

            # Handle tour days
            # First, remove existing tour days
            for day in tour.tour_days:
                db.session.delete(day)
            
            # Add new tour days
            for index, day_form in enumerate(form.tour_days):
                tour_day = TourDay(
                    title=day_form.form.title.data or "Untitled",
                    description=day_form.form.description.data or "No description provided",
                    day_number=index + 1
                )
                tour.tour_days.append(tour_day)

            db.session.commit()
            flash('Tour updated successfully', 'success')
            return redirect(url_for('admin_blueprint.manage_tours'))
            
        except Exception as e:
            db.session.rollback()
            logger.exception(f"Error updating tour: {str(e)}")
            flash(f'Error updating tour: {str(e)}', 'error')
    
    if form.errors:
        for field, errors in form.errors.items():
            for error in errors:
                flash(f"{getattr(form, field).label.text}: {error}", 'error')
    
    return render_template('edit_tour.html', form=form, tour=tour)






@admin_blueprint.route('/tours/delete/<int:id>', methods=['POST'])
@login_required
def delete_tour(id):
    form = FlaskForm()
    if form.validate_on_submit():
        tour = Tour.query.get_or_404(id)
        try:
            db.session.delete(tour)
            db.session.commit()
            flash('Tour deleted successfully', 'success')
        except Exception as e:
            db.session.rollback()
            flash(f'Error deleting tour: {str(e)}', 'error')
            current_app.logger.error(f"Error deleting tour: {str(e)}")
    return redirect(url_for('admin_blueprint.manage_tours'))

@admin_blueprint.route('/bookings')
@login_required
def manage_bookings():
    bookings = Booking.query.all()
    return render_template('manage_bookings.html', bookings=bookings)

@admin_blueprint.route('/bookings/view/<int:id>')
@login_required
def view_booking(id):
    booking = Booking.query.get_or_404(id)
    return render_template('view_booking.html', booking=booking)

@admin_blueprint.route('/bookings/delete/<int:id>', methods=['POST'])
@login_required
def delete_booking(id):
    form = FlaskForm()
    if form.validate_on_submit():
        booking = Booking.query.get_or_404(id)
        try:
            db.session.delete(booking)
            db.session.commit()
            flash('Booking deleted successfully', 'success')
        except Exception as e:
            db.session.rollback()
            flash(f'Error deleting booking: {str(e)}', 'error')
            current_app.logger.error(f"Error deleting booking: {str(e)}")
    return redirect(url_for('admin_blueprint.manage_bookings'))

@admin_blueprint.route('/quote-requests')
@login_required
def quote_requests():
    requests = Booking.query.order_by(Booking.created_at.desc()).all()
    return render_template('quote_requests.html', requests=requests)

@admin_blueprint.route('/toggle_maintenance')
@login_required
def toggle_maintenance():
    current_app.config['MAINTENANCE_MODE'] = not current_app.config.get('MAINTENANCE_MODE', False)
    status = "enabled" if current_app.config['MAINTENANCE_MODE'] else "disabled"
    flash(f'Maintenance mode {status}', 'success')
    return redirect(url_for('admin_blueprint.index'))

@admin_blueprint.errorhandler(404)
def not_found_error(error):
    return render_template('404.html'), 404

@admin_blueprint.errorhandler(500)
def internal_error(error):
    db.session.rollback()
    return render_template('500.html'), 500

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in current_app.config['ALLOWED_EXTENSIONS']

@admin_blueprint.route('/upload', methods=['POST'])
@login_required
def upload_file():
    if 'file' not in request.files:
        flash('No file part', 'error')
        return redirect(request.url)
    file = request.files['file']
    if file.filename == '':
        flash('No selected file', 'error')
        return redirect(request.url)
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        file.save(os.path.join(current_app.config['UPLOAD_FOLDER'], filename))
        flash('File successfully uploaded', 'success')
        return redirect(url_for('admin_blueprint.index'))
    else:
        flash('Allowed file types are txt, pdf, png, jpg, jpeg, gif', 'error')
        return redirect(request.url)    

@admin_blueprint.route('/blogs')
@login_required
def manage_blogs():
    logger.info("Entering manage_blogs function")
    blogs = Blog.query.order_by(Blog.created_at.desc()).all()
    logger.info(f"Retrieved {len(blogs)} blog posts")
    return render_template('manage_blogs.html', blogs=blogs)

@admin_blueprint.route('/blogs/add', methods=['GET', 'POST'])
@login_required
def add_blog():
    logger.info("Entering add_blog function")
    logger.info(f"Request method: {request.method}")
    logger.info(f"Form data: {request.form}")
    logger.info(f"Files: {request.files}")
    
    form = BlogForm()
    
    if request.method == 'POST':
        logger.info("Processing POST request")
        logger.info(f"CSRF Token: {form.csrf_token.current_token}")
        
        if form.validate_on_submit():
            logger.info("Form validated successfully")
            try:
                def safe_slugify(text):
                    return slugify(text) if 'slugify' in globals() else text.replace(" ", "-").lower()
                
                blog = Blog(
                    title=form.title.data,
                    content=form.content.data,
                    meta_description=form.meta_description.data,
                    meta_keywords=form.meta_keywords.data,
                    slug=safe_slugify(form.title.data)
                )
                
                if form.feature_image.data:
                    feature_image = save_image(form.feature_image.data)
                    blog.feature_image = feature_image
                    logger.info(f"Feature image saved: {feature_image}")
                
                for i in range(1, 4):
                    image_field = getattr(form, f'gallery_image_{i}')
                    if image_field.data:
                        image_filename = save_image(image_field.data)
                        setattr(blog, f'gallery_image_{i}', image_filename)
                        logger.info(f"Gallery image {i} saved: {image_filename}")
                
                db.session.add(blog)
                db.session.commit()
                logger.info('Blog post added successfully')
                flash('Blog post added successfully', 'success')
                return redirect(url_for('admin_blueprint.manage_blogs'))
            except Exception as e:
                logger.exception(f"Error adding blog post: {str(e)}")
                db.session.rollback()
                flash(f'Error adding blog post: {str(e)}', 'error')
        else:
            logger.warning(f"Form validation failed. Errors: {form.errors}")
            for field, errors in form.errors.items():
                for error in errors:
                    flash(f"{getattr(form, field).label.text}: {error}", 'error')
    
    logger.info("Rendering add_blog template")
    return render_template('add_blog.html', form=form)

@admin_blueprint.route('/blogs/edit/<int:id>', methods=['GET', 'POST'])
@login_required
def edit_blog(id):
    logger.info(f"Entering edit_blog function for blog id: {id}")
    logger.info(f"Request method: {request.method}")
    logger.info(f"Form data: {request.form}")
    logger.info(f"Files: {request.files}")
    
    blog = Blog.query.get_or_404(id)
    form = BlogForm(obj=blog)
    
    if request.method == 'POST':
        logger.info("Processing POST request")
        logger.info(f"CSRF Token: {form.csrf_token.current_token}")
        
        if form.validate_on_submit():
            logger.info("Form validated successfully")
            try:
                form.populate_obj(blog)
                blog.slug = slugify(blog.title)
                
                if form.feature_image.data:
                    feature_image = save_image(form.feature_image.data)
                    blog.feature_image = feature_image
                    logger.info(f"Feature image updated: {feature_image}")
                
                for i in range(1, 4):
                    image_field = getattr(form, f'gallery_image_{i}')
                    if image_field.data:
                        image_filename = save_image(image_field.data)
                        setattr(blog, f'gallery_image_{i}', image_filename)
                        logger.info(f"Gallery image {i} updated: {image_filename}")
                
                db.session.commit()
                logger.info('Blog post updated successfully')
                flash('Blog post updated successfully', 'success')
                return redirect(url_for('admin_blueprint.manage_blogs'))
            except Exception as e:
                logger.exception(f"Error updating blog post: {str(e)}")
                db.session.rollback()
                flash(f'Error updating blog post: {str(e)}', 'error')
        else:
            logger.warning(f"Form validation failed. Errors: {form.errors}")
            for field, errors in form.errors.items():
                for error in errors:
                    flash(f"{getattr(form, field).label.text}: {error}", 'error')
    
    logger.info("Rendering edit_blog template")
    return render_template('edit_blog.html', form=form, blog=blog)

@admin_blueprint.route('/blogs/delete/<int:id>', methods=['POST'])
@login_required
def delete_blog(id):
    logger.info(f"Entering delete_blog function for blog id: {id}")
    blog = Blog.query.get_or_404(id)
    try:
        db.session.delete(blog)
        db.session.commit()
        logger.info(f"Blog post with id {id} deleted successfully")
        flash('Blog post deleted successfully', 'success')
    except Exception as e:
        logger.exception(f"Error deleting blog post: {str(e)}")
        db.session.rollback()
        flash(f'Error deleting blog post: {str(e)}', 'error')
    return redirect(url_for('admin_blueprint.manage_blogs'))

def save_image(image):
    filename = secure_filename(image.filename)
    image_path = os.path.join(current_app.config['UPLOAD_FOLDER'], filename)
    logger.info(f"Saving image to: {image_path}")
    image.save(image_path)
    return filename

@admin_blueprint.route('/tour-categories', methods=['GET', 'POST'])
@login_required
def manage_tour_categories():
    parent_form = TourParentCategoryForm(prefix="parent")
    sub_form = TourSubCategoryForm(prefix="sub")

    if request.method == 'POST':
        if parent_form.submit.data and parent_form.validate():
            category = TourParentCategory(name=parent_form.name.data)
            db.session.add(category)
            db.session.commit()
            flash('Parent category added successfully', 'success')
            return redirect(url_for('admin_blueprint.manage_tour_categories'))

        elif sub_form.submit.data and sub_form.validate():
            subcategory = TourSubCategory(
                name=sub_form.name.data,
                parent_category_id=sub_form.parent_category.data
            )
            if sub_form.image.data:
                image_filename = save_image(sub_form.image.data)
                subcategory.image = image_filename
            db.session.add(subcategory)
            db.session.commit()
            flash('Subcategory added successfully', 'success')
            return redirect(url_for('admin_blueprint.manage_tour_categories'))

    parent_categories = TourParentCategory.query.options(db.joinedload(TourParentCategory.subcategories)).order_by(TourParentCategory.name).all()

    return render_template('manage_tour_categories.html', 
                           parent_form=parent_form, 
                           sub_form=sub_form, 
                           parent_categories=parent_categories)

@admin_blueprint.route('/tour-categories/edit-parent/<int:id>', methods=['GET', 'POST'])
@login_required
def edit_parent_category(id):
    category = TourParentCategory.query.get_or_404(id)
    form = TourParentCategoryForm(obj=category)

    if form.validate_on_submit():
        category.name = form.name.data
        category.slug = slugify(form.name.data)
        try:
            db.session.commit()
            flash('Parent category updated successfully', 'success')
            return redirect(url_for('admin_blueprint.manage_tour_categories'))
        except Exception as e:
            db.session.rollback()
            flash(f'Error updating parent category: {str(e)}', 'error')

    return render_template('edit_parent_category.html', form=form, category=category)

@admin_blueprint.route('/tour-categories/delete-parent/<int:id>', methods=['POST'])
@login_required
def delete_parent_category(id):
    category = TourParentCategory.query.get_or_404(id)
    try:
        db.session.delete(category)
        db.session.commit()
        flash('Parent category deleted successfully', 'success')
    except Exception as e:
        db.session.rollback()
        flash(f'Error deleting parent category: {str(e)}', 'error')
    return redirect(url_for('admin_blueprint.manage_tour_categories'))

@admin_blueprint.route('/tour-categories/edit-sub/<int:id>', methods=['GET', 'POST'])
@login_required
def edit_subcategory(id):
    subcategory = TourSubCategory.query.get_or_404(id)
    form = TourSubCategoryForm(obj=subcategory)

    if form.validate_on_submit():
        subcategory.name = form.name.data
        subcategory.slug = slugify(form.name.data)
        subcategory.parent_category_id = form.parent_category.data
        if form.image.data:
            image_filename = save_image(form.image.data)
            subcategory.image = image_filename
        try:
            db.session.commit()
            flash('Subcategory updated successfully', 'success')
            return redirect(url_for('admin_blueprint.manage_tour_categories'))
        except Exception as e:
            db.session.rollback()
            flash(f'Error updating subcategory: {str(e)}', 'error')

    return render_template('edit_subcategory.html', form=form, subcategory=subcategory)

@admin_blueprint.route('/tour-categories/delete-sub/<int:id>', methods=['POST'])
@login_required
def delete_subcategory(id):
    subcategory = TourSubCategory.query.get_or_404(id)
    try:
        db.session.delete(subcategory)
        db.session.commit()
        flash('Subcategory deleted successfully', 'success')
    except Exception as e:
        db.session.rollback()
        flash(f'Error deleting subcategory: {str(e)}', 'error')
    return redirect(url_for('admin_blueprint.manage_tour_categories'))