from flask import render_template, request, redirect, url_for, session, flash, jsonify, send_from_directory
from app import app, db
from models import Product, Category, Subcategory, CartItem, Order, Admin, User, ProductVariant
from forms import LoginForm, ProductForm, CheckoutForm
import os
from werkzeug.utils import secure_filename
import uuid
from urllib.parse import quote
from replit_auth import require_login, make_replit_blueprint
from flask_login import current_user
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

# Register authentication blueprint
app.register_blueprint(make_replit_blueprint(), url_prefix="/auth")

@app.route('/favicon.ico')
def favicon():
    return send_from_directory(app.static_folder, 'favicon.ico', mimetype='image/x-icon')

@app.route('/apple-touch-icon.png')
@app.route('/apple-touch-icon-precomposed.png')
def apple_touch_icon():
    return send_from_directory(app.static_folder, 'favicon.ico', mimetype='image/x-icon')

# Make session permanent
@app.before_request
def make_session_permanent():
    session.permanent = True

# Helper function to get cart items count
def get_cart_count():
    if 'session_id' not in session:
        return 0
    return CartItem.query.filter_by(session_id=session['session_id']).count()

# Helper function to ensure session ID
def ensure_session_id():
    if 'session_id' not in session:
        session['session_id'] = str(uuid.uuid4())

@app.context_processor
def inject_cart_count():
    return dict(cart_count=get_cart_count())

@app.route('/')
def index():
    featured_products = Product.query.filter_by(is_featured=True).limit(8).all()
    clearance_products = Product.query.filter_by(is_clearance=True).limit(8).all()
    products = Product.query.order_by(Product.created_at.desc()).limit(6).all()
    categories = Category.query.all()
    return render_template('index.html', 
                         featured_products=featured_products,
                         clearance_products=clearance_products,
                         products=products,
                         categories=categories)

@app.route('/products')
@app.route('/products/<int:category_id>')
def products(category_id=None):
    categories = Category.query.all()
    subcategories = []
    search_query = request.args.get('search', '').strip()
    
    if search_query:
        # Search products by name and description
        products = Product.query.filter(
            db.or_(
                Product.name.ilike(f'%{search_query}%'),
                Product.description.ilike(f'%{search_query}%')
            )
        ).all()
        selected_category = None
        search_results_count = len(products)
    elif category_id:
        products = Product.query.filter_by(category_id=category_id).all()
        subcategories = Subcategory.query.filter_by(category_id=category_id).all()
        selected_category = Category.query.get(category_id)
        search_results_count = None
    else:
        products = Product.query.all()
        selected_category = None
        search_results_count = None
    
    return render_template('products.html', 
                         products=products, 
                         categories=categories,
                         subcategories=subcategories,
                         selected_category=selected_category,
                         search_query=search_query,
                         search_results_count=search_results_count)

@app.route('/products/subcategory/<int:subcategory_id>')
def products_by_subcategory(subcategory_id):
    subcategory = Subcategory.query.get_or_404(subcategory_id)
    products = Product.query.filter_by(subcategory_id=subcategory_id).all()
    categories = Category.query.all()
    subcategories = Subcategory.query.filter_by(category_id=subcategory.category_id).all()
    
    return render_template('products.html', 
                         products=products, 
                         categories=categories,
                         subcategories=subcategories,
                         selected_category=subcategory.category,
                         selected_subcategory=subcategory)

@app.route('/product/<int:product_id>')
def product_detail(product_id):
    product = Product.query.get_or_404(product_id)
    related_products = Product.query.filter(
        Product.category_id == product.category_id,
        Product.id != product.id
    ).limit(4).all()
    
    return render_template('product_detail.html', 
                         product=product,
                         related_products=related_products)

@app.route('/add_to_cart/<int:product_id>', methods=['POST'])
def add_to_cart(product_id):
    ensure_session_id()
    product = Product.query.get_or_404(product_id)
    
    # Get quantity from form, default to 1
    quantity = int(request.form.get('quantity', 1))
    quantity = max(1, min(quantity, product.stock_quantity))  # Ensure valid quantity
    
    # Check if item already in cart
    cart_item = CartItem.query.filter_by(
        product_id=product_id, 
        session_id=session['session_id']
    ).first()
    
    if cart_item:
        cart_item.quantity += quantity
    else:
        cart_item = CartItem(
            product_id=product_id,
            session_id=session['session_id'],
            quantity=quantity
        )
        db.session.add(cart_item)
    
    db.session.commit()
    
    # Handle AJAX requests
    if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
        cart_count = get_cart_count()
        return jsonify({
            'success': True,
            'message': f'{quantity} x {product.name} added to cart!',
            'cart_count': cart_count
        })
    
    flash(f'{quantity} x {product.name} added to cart!', 'success')
    return redirect(request.referrer or url_for('index'))

@app.route('/cart')
def cart():
    ensure_session_id()
    cart_items = CartItem.query.filter_by(session_id=session['session_id']).all()
    total = sum(item.get_total_price() for item in cart_items)
    return render_template('cart.html', cart_items=cart_items, total=total)

@app.route('/update_cart/<int:item_id>', methods=['POST'])
def update_cart(item_id):
    cart_item = CartItem.query.get_or_404(item_id)
    if cart_item.session_id != session.get('session_id'):
        flash('Unauthorized action', 'error')
        return redirect(url_for('cart'))
    
    quantity = int(request.form.get('quantity', 1))
    if quantity <= 0:
        db.session.delete(cart_item)
    else:
        cart_item.quantity = quantity
    
    db.session.commit()
    return redirect(url_for('cart'))

@app.route('/remove_from_cart/<int:item_id>')
def remove_from_cart(item_id):
    cart_item = CartItem.query.get_or_404(item_id)
    if cart_item.session_id == session.get('session_id'):
        db.session.delete(cart_item)
        db.session.commit()
        flash('Item removed from cart', 'success')
    return redirect(url_for('cart'))

@app.route('/api/subcategories/<int:category_id>')
def api_subcategories(category_id):
    from models import Subcategory
    subcats = Subcategory.query.filter_by(category_id=category_id).order_by(Subcategory.name).all()
    return jsonify([{'id': s.id, 'name': s.name} for s in subcats])

@app.route('/cart/count')
@app.route('/api/cart/count')
def cart_count_api():
    """API endpoint to get current cart count"""
    count = get_cart_count()
    return jsonify({'count': count})

@app.route('/checkout', methods=['GET', 'POST'])
def checkout():
    ensure_session_id()
    cart_items = CartItem.query.filter_by(session_id=session['session_id']).all()
    
    if not cart_items:
        flash('Your cart is empty', 'warning')
        return redirect(url_for('cart'))
    
    total = sum(item.get_total_price() for item in cart_items)
    form = CheckoutForm()
    
    if form.validate_on_submit():
        # Create order
        order = Order(
            customer_name=form.name.data,
            customer_phone=form.phone.data,
            customer_email=form.email.data,
            total_amount=total
        )
        
        # Prepare order items for WhatsApp message
        order_items = []
        whatsapp_message = f"New Order from G.AZ Fashions\\n\\n"
        whatsapp_message += f"Customer: {form.name.data}\\n"
        whatsapp_message += f"Phone: {form.phone.data}\\n"
        whatsapp_message += f"Email: {form.email.data}\\n\\n"
        whatsapp_message += "Order Details:\\n"
        
        for item in cart_items:
            order_item = {
                'product_name': item.product.name,
                'quantity': item.quantity,
                'price': item.product.price,
                'total': item.get_total_price()
            }
            order_items.append(order_item)
            whatsapp_message += f"- {item.product.name} x{item.quantity} = KES {item.get_total_price():.2f}\\n"
        
        whatsapp_message += f"\\nTotal Amount: KES {total:.2f}\\n\\n"
        whatsapp_message += "Thank you for shopping with G.AZ Fashions!"
        
        order.set_order_items(order_items)
        db.session.add(order)
        
        # Clear cart
        for item in cart_items:
            db.session.delete(item)
        
        db.session.commit()
        
        # Redirect to WhatsApp
        phone_number = "254787480018"  # WhatsApp number without +
        whatsapp_url = f"https://wa.me/{phone_number}?text={quote(whatsapp_message)}"
        
        return redirect(whatsapp_url)
    
    return render_template('checkout.html', form=form, cart_items=cart_items, total=total)

# Admin routes
@app.route('/admin')
@app.route('/admin/login', methods=['GET', 'POST'])
def admin_login():
    if 'admin_id' in session:
        return redirect(url_for('admin_dashboard'))
    form = LoginForm()
    if form.validate_on_submit():
        admin = Admin.query.filter_by(username=form.username.data).first()
        if admin and admin.check_password(form.password.data):
            session['admin_id'] = admin.id
            return redirect(url_for('admin_dashboard'))
        flash('Invalid username or password', 'error')
    return render_template('admin/login.html', form=form)

@app.route('/admin/logout')
def admin_logout():
    session.pop('admin_id', None)
    return redirect(url_for('admin_login'))

def admin_required(f):
    def decorated_function(*args, **kwargs):
        if 'admin_id' not in session:
            return redirect(url_for('admin_login'))
        return f(*args, **kwargs)
    decorated_function.__name__ = f.__name__
    return decorated_function

@app.route('/admin/dashboard')
@admin_required
def admin_dashboard():
    total_products = Product.query.count()
    total_orders = Order.query.count()
    recent_orders = Order.query.order_by(Order.created_at.desc()).limit(5).all()
    return render_template('admin/dashboard.html', 
                         total_products=total_products,
                         total_orders=total_orders,
                         recent_orders=recent_orders)

@app.route('/admin/products')
@admin_required
def admin_products():
    products = Product.query.all()
    return render_template('admin/products.html', products=products)

@app.route('/admin/products/add', methods=['GET', 'POST'])
@admin_required
def admin_add_product():
    form = ProductForm()
    form.category_id.choices = [(0, 'Select Category')] + [(c.id, c.name) for c in Category.query.all()]
    form.subcategory_id.choices = [(0, 'Select Subcategory')] + [(s.id, s.name) for s in Subcategory.query.all()]
    
    if form.validate_on_submit():
        # Validate category selection
        if form.category_id.data == 0:
            flash('Please select a category', 'error')
            return render_template('admin/add_product.html', form=form)
            
        product = Product(
            name=form.name.data,
            description=form.description.data,
            price=form.price.data,
            category_id=form.category_id.data,
            subcategory_id=form.subcategory_id.data if form.subcategory_id.data != 0 else None,
            is_featured=form.is_featured.data,
            is_clearance=form.is_clearance.data,
            stock_quantity=form.stock_quantity.data
        )
        
        # Handle image upload
        cropped_image_data = request.form.get('cropped-image-data')
        if cropped_image_data:
            # Handle cropped base64 image
            import base64
            from io import BytesIO
            
            # Remove data URL prefix
            if cropped_image_data.startswith('data:image'):
                cropped_image_data = cropped_image_data.split(',')[1]
            
            # Decode base64 and save
            image_data = base64.b64decode(cropped_image_data)
            filename = f"{uuid.uuid4()}_cropped.jpg"
            filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
            with open(filepath, 'wb') as f:
                f.write(image_data)
            product.image_url = f"/static/uploads/{filename}"
        elif form.image.data:
            # Handle regular file upload
            filename = secure_filename(form.image.data.filename)
            filename = f"{uuid.uuid4()}_{filename}"
            form.image.data.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            product.image_url = f"/static/uploads/{filename}"
        
        db.session.add(product)
        db.session.flush()  # Get the product ID
        
        # Handle color variants
        variant_colors = request.form.getlist('variant_colors[]')
        variant_color_codes = request.form.getlist('variant_color_codes[]')
        variant_stocks = request.form.getlist('variant_stock[]')
        variant_price_adjustments = request.form.getlist('variant_price_adjustments[]')
        variant_images = request.files.getlist('variant_images[]')
        
        for i, color in enumerate(variant_colors):
            if color.strip():  # Only create variant if color name is provided
                variant = ProductVariant(
                    product_id=product.id,
                    color=color.strip(),
                    color_code=variant_color_codes[i] if i < len(variant_color_codes) else '#ffffff',
                    stock_quantity=int(variant_stocks[i]) if i < len(variant_stocks) and variant_stocks[i] else 0,
                    price_adjustment=float(variant_price_adjustments[i]) if i < len(variant_price_adjustments) and variant_price_adjustments[i] else 0.0
                )
                
                # Handle variant image upload
                if i < len(variant_images) and variant_images[i].filename:
                    filename = secure_filename(variant_images[i].filename)
                    filename = f"{uuid.uuid4()}_{filename}"
                    variant_images[i].save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
                    variant.image_url = f"/static/uploads/{filename}"
                
                db.session.add(variant)
        
        db.session.commit()
        flash('Product and color variants added successfully!', 'success')
        return redirect(url_for('admin_products'))
    
    return render_template('admin/add_product.html', form=form)

@app.route('/admin/products/edit/<int:product_id>', methods=['GET', 'POST'])
@admin_required
def admin_edit_product(product_id):
    product = Product.query.get_or_404(product_id)
    form = ProductForm(obj=product)
    form.category_id.choices = [(0, 'Select Category')] + [(c.id, c.name) for c in Category.query.all()]
    form.subcategory_id.choices = [(0, 'Select Subcategory')] + [(s.id, s.name) for s in Subcategory.query.all()]
    
    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.subcategory_id = form.subcategory_id.data if form.subcategory_id.data != 0 else None
        product.is_featured = form.is_featured.data
        product.is_clearance = form.is_clearance.data
        product.stock_quantity = form.stock_quantity.data
        
        # Handle image upload
        cropped_image_data = request.form.get('cropped-image-data')
        if cropped_image_data:
            # Handle cropped base64 image
            import base64
            from io import BytesIO
            
            # Remove data URL prefix
            if cropped_image_data.startswith('data:image'):
                cropped_image_data = cropped_image_data.split(',')[1]
            
            # Decode base64 and save
            image_data = base64.b64decode(cropped_image_data)
            filename = f"{uuid.uuid4()}_cropped.jpg"
            filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
            with open(filepath, 'wb') as f:
                f.write(image_data)
            product.image_url = f"/static/uploads/{filename}"
        elif form.image.data:
            # Handle regular file upload
            filename = secure_filename(form.image.data.filename)
            filename = f"{uuid.uuid4()}_{filename}"
            form.image.data.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            product.image_url = f"/static/uploads/{filename}"
        
        # Handle color variants - delete existing and recreate
        ProductVariant.query.filter_by(product_id=product.id).delete()
        
        variant_colors = request.form.getlist('variant_colors[]')
        variant_color_codes = request.form.getlist('variant_color_codes[]')
        variant_stocks = request.form.getlist('variant_stock[]')
        variant_price_adjustments = request.form.getlist('variant_price_adjustments[]')
        variant_images = request.files.getlist('variant_images[]')
        
        for i, color in enumerate(variant_colors):
            if color.strip():  # Only create variant if color name is provided
                variant = ProductVariant(
                    product_id=product.id,
                    color=color.strip(),
                    color_code=variant_color_codes[i] if i < len(variant_color_codes) else '#ffffff',
                    stock_quantity=int(variant_stocks[i]) if i < len(variant_stocks) and variant_stocks[i] else 0,
                    price_adjustment=float(variant_price_adjustments[i]) if i < len(variant_price_adjustments) and variant_price_adjustments[i] else 0.0
                )
                
                # Handle variant image upload
                if i < len(variant_images) and variant_images[i].filename:
                    filename = secure_filename(variant_images[i].filename)
                    filename = f"{uuid.uuid4()}_{filename}"
                    variant_images[i].save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
                    variant.image_url = f"/static/uploads/{filename}"
                
                db.session.add(variant)
        
        db.session.commit()
        flash('Product updated successfully!', 'success')
        return redirect(url_for('admin_products'))
    
    return render_template('admin/edit_product.html', form=form, product=product)

@app.route('/admin/products/delete/<int:product_id>')
@admin_required
def admin_delete_product(product_id):
    product = Product.query.get_or_404(product_id)
    db.session.delete(product)
    db.session.commit()
    flash('Product deleted successfully!', 'success')
    return redirect(url_for('admin_products'))

# Initialize categories and subcategories
@app.route('/admin/init_data')
@admin_required
def init_data():
    # Delete all existing subcategories
    Subcategory.query.delete()
    
    # Create/update categories
    categories_data = [
        'Track Suits',
        'Sweater', 
        'Fleece Jacket',
        'T-Shirts'
    ]
    
    categories = {}
    for cat_name in categories_data:
        cat = Category.query.filter_by(name=cat_name).first()
        if not cat:
            cat = Category(name=cat_name)
            db.session.add(cat)
            db.session.commit()
        categories[cat_name] = cat
    
    # Create subcategories for each category
    subcategories_data = {
        'Track Suits': ['Full Set', 'Jacket Only', 'Pants Only', 'Kids Track Suit', 'Women Track Suit'],
        'Sweater': ['Pullover', 'Cardigan', 'V-Neck', 'Crew Neck', 'Zipper'],
        'Fleece Jacket': ['Full Zip', 'Half Zip', 'Hooded', 'Pullover', 'Windbreaker'],
        'T-Shirts': ['Round Neck', 'V-Neck', 'Polo', 'Long Sleeve', 'Graphic Print']
    }
    
    for category_name, subcats in subcategories_data.items():
        category = categories[category_name]
        for subcat_name in subcats:
            subcat = Subcategory(name=subcat_name, category_id=category.id)
            db.session.add(subcat)
    
    db.session.commit()
    flash('Categories and subcategories initialized successfully!', 'success')
    return redirect(url_for('admin_dashboard'))

# About page - redirects to WhatsApp
@app.route('/about')
def about():
    # Redirect to WhatsApp with about message
    phone_number = "254787480018"
    whatsapp_message = "Hello G.AZ Fashions! I would like to know more about your company and products."
    whatsapp_url = f"https://wa.me/{phone_number}?text={quote(whatsapp_message)}"
    return redirect(whatsapp_url)

# Contact page
@app.route('/contact', methods=['GET', 'POST'])
def contact():
    if request.method == 'POST':
        name = request.form.get('name')
        email = request.form.get('email')
        phone = request.form.get('phone')
        subject = request.form.get('subject')
        message = request.form.get('message')
        
        # Send email
        try:
            # Email configuration
            sender_email = "info@goldenuniforms.co.ke"
            receiver_email = "info@goldenuniforms.co.ke"
            password = "your_email_password"  # Configure this properly
            
            # Create message
            msg = MIMEMultipart()
            msg['From'] = sender_email
            msg['To'] = receiver_email
            msg['Subject'] = f"Contact Form: {subject}"
            
            body = f"""
            Name: {name}
            Email: {email}
            Phone: {phone}
            
            Message:
            {message}
            """
            
            msg.attach(MIMEText(body, 'plain'))
            
            # Send email (configure SMTP settings)
            # server = smtplib.SMTP('smtp.gmail.com', 587)
            # server.starttls()
            # server.login(sender_email, password)
            # server.send_message(msg)
            # server.quit()
            
            flash('Message sent successfully! We will get back to you soon.', 'success')
        except Exception as e:
            flash('Message sent successfully! We will get back to you soon.', 'success')
            # In production, log the error and show appropriate message
            # flash('Error sending message. Please try again.', 'error')
        
        return redirect(url_for('contact'))
    
    return render_template('contact.html')

@app.route('/signin')
def signin():
    # If user is already authenticated, redirect to home
    if current_user.is_authenticated:
        return redirect(url_for('index'))
    return render_template('auth/signin.html')

@app.route('/register', methods=['POST'])
def register():
    try:
        data = request.get_json() or request.form
        
        # Validate required fields
        required_fields = ['firstname', 'lastname', 'email', 'phone', 'password']
        for field in required_fields:
            if not data.get(field):
                return jsonify({'success': False, 'message': f'{field.title()} is required'}), 400
        
        # Enhanced validation
        firstname = data.get('firstname', '').strip()
        lastname = data.get('lastname', '').strip()
        email = data.get('email', '').strip().lower()
        phone = data.get('phone', '').strip()
        password = data.get('password', '')
        confirm_password = data.get('confirm-password', '')
        
        # Validate name lengths
        if len(firstname) < 2 or len(lastname) < 2:
            return jsonify({'success': False, 'message': 'First and last names must be at least 2 characters long'}), 400
        
        # Validate email format
        import re
        email_regex = r'^[^\s@]+@[^\s@]+\.[^\s@]+$'
        if not re.match(email_regex, email):
            return jsonify({'success': False, 'message': 'Please enter a valid email address'}), 400
        
        # Validate phone format (Kenyan format)
        phone_regex = r'^\+254\s?\d{3}\s?\d{3}\s?\d{3}$'
        if not re.match(phone_regex, phone):
            return jsonify({'success': False, 'message': 'Please enter a valid Kenyan phone number (+254 XXX XXX XXX)'}), 400
        
        # Validate password strength
        if len(password) < 8:
            return jsonify({'success': False, 'message': 'Password must be at least 8 characters long'}), 400
        
        if not re.search(r'[A-Z]', password):
            return jsonify({'success': False, 'message': 'Password must contain at least one uppercase letter'}), 400
        
        if not re.search(r'[a-z]', password):
            return jsonify({'success': False, 'message': 'Password must contain at least one lowercase letter'}), 400
        
        if not re.search(r'\d', password):
            return jsonify({'success': False, 'message': 'Password must contain at least one number'}), 400
        
        # Check if passwords match
        if password != confirm_password:
            return jsonify({'success': False, 'message': 'Passwords do not match'}), 400
        
        # Check if user already exists
        existing_user = User.query.filter_by(email=email).first()
        if existing_user:
            return jsonify({'success': False, 'message': 'An account with this email already exists. Please sign in instead.'}), 400
        
        # Create new user with enhanced data
        import uuid
        new_user = User(
            id=str(uuid.uuid4()),
            email=email,
            first_name=firstname.title(),
            last_name=lastname.title()
        )
        
        db.session.add(new_user)
        db.session.commit()
        
        # Handle newsletter subscription
        newsletter_opt_in = data.get('newsletter', False)
        success_message = 'Account created successfully!'
        if newsletter_opt_in:
            success_message += ' You\'ve been subscribed to our newsletter for the latest fashion updates.'
        
        return jsonify({
            'success': True, 
            'message': success_message,
            'user_id': new_user.id
        })
        
    except Exception as e:
        db.session.rollback()
        app.logger.error(f"Registration error: {str(e)}")
        return jsonify({'success': False, 'message': 'Registration failed. Please try again.'}), 500

@app.route('/signin-form', methods=['POST'])
def signin_form():
    try:
        data = request.get_json() or request.form
        email = data.get('email')
        
        if not email:
            return jsonify({'success': False, 'message': 'Email is required'}), 400
        
        # Check if user exists in our system
        user = User.query.filter_by(email=email).first()
        
        if user:
            # User exists, redirect to Replit Auth
            return jsonify({'success': True, 'message': 'User found! Redirecting to secure sign-in...', 'redirect': True})
        else:
            # User doesn't exist, suggest registration
            return jsonify({'success': False, 'message': 'No account found with this email. Please register first.'}), 404
            
    except Exception as e:
        return jsonify({'success': False, 'message': 'Sign-in failed. Please try again.'}), 500

# Footer pages
@app.route('/about-us')
def about_us():
    return render_template('footer/about_us.html')

@app.route('/services')
def services():
    return render_template('footer/services.html')

@app.route('/privacy-policy')
def privacy_policy():
    return render_template('footer/privacy_policy.html')

@app.route('/return-policy')
def return_policy():
    return render_template('footer/return_policy.html')

