import os
import pandas as pd
import datetime
from flask import Blueprint, render_template, redirect, url_for, flash, request, current_app, jsonify
from flask_login import login_user, logout_user, login_required
from werkzeug.utils import secure_filename
from .forms import LoginForm, RegisterForm, UploadForm
from .models import User, db, Precio, Proyecto, Vendedor
from sqlalchemy.exc import SQLAlchemyError

bp = Blueprint('auth', __name__)

@bp.route('/login', methods=['GET', 'POST'])
def login():
    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):
            login_user(user)
            flash('Inicio de sesión exitoso', 'success')
            return redirect(url_for('auth.home'))
        flash('Nombre de usuario o contraseña inválidos', 'error')
    return render_template('login.html', form=form)

@bp.route('/register', methods=['GET', 'POST'])
def register():
    form = RegisterForm()
    if form.validate_on_submit():
        new_user = User(username=form.username.data)
        new_user.set_password(form.password.data)
        db.session.add(new_user)
        db.session.commit()
        flash('Registro exitoso. Ahora puedes iniciar sesión.', 'success')
        return redirect(url_for('auth.login'))
    return render_template('register.html', form=form)

@bp.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('auth.login'))

@bp.route('/upload_excel', methods=['POST'])
@login_required
def upload_excel():
    form = UploadForm()
    if form.validate_on_submit():
        file = form.excelFile.data
        if file.filename == '':
            return jsonify({"success": False, "message": "No selected file"})

        if file and file.filename.endswith(('.xls', '.xlsx')):
            timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
            filename = secure_filename(f"{timestamp}_{file.filename}")
            file_path = os.path.join(current_app.root_path, 'static/files', filename)
            file.save(file_path)

            try:
                process_excel(file_path)
                return jsonify({"success": True, "message": "Archivo cargado y procesado exitosamente"})
            except Exception as e:
                current_app.logger.error(f"Error al procesar el archivo: {e}")
                return jsonify({"success": False, "message": f"Error al procesar el archivo: {e}"})

        return jsonify({"success": False, "message": "Formato de archivo no permitido"})
    return jsonify({"success": False, "message": "Error en el formulario"})

@bp.route('/home')
@login_required
def home():
    form = UploadForm()
    return render_template('home.html', form=form)

def process_excel(file_path):
    try:
        current_app.logger.info(f"Procesando el archivo: {file_path}")
        xls = pd.ExcelFile(file_path)

        if 'Precios' in xls.sheet_names:
            df_precios = pd.read_excel(xls, sheet_name='Precios')
            df_precios = df_precios.where(pd.notnull(df_precios), None)
            for _, row in df_precios.iterrows():
                current_app.logger.info(f"Insertando registro en Precios: {row.to_dict()}")
                precio = Precio(
                    Proyecto=row['Proyecto'],
                    Modelos=row['Modelos'],
                    Programa=row['Programa'],
                    Superficie=row['Superficie'],
                    Patio=row['Patio'],
                    Terraza=row['Terraza'],
                    Desde=row['Desde'],
                    Hasta=row['Hasta'],
                    En_Stock=row['En_Stock']
                )
                db.session.add(precio)
                current_app.logger.info(f"Registro en Precios añadido: {precio}")

        if 'Proyectos' in xls.sheet_names:
            df_proyectos = pd.read_excel(xls, sheet_name='Proyectos')
            df_proyectos = df_proyectos.where(pd.notnull(df_proyectos), None)
            for _, row in df_proyectos.iterrows():
                current_app.logger.info(f"Insertando registro en Proyectos: {row.to_dict()}")
                proyecto = Proyecto(
                    Inmobiliaria=row['Inmobiliaria'],
                    Proyecto=row['Proyecto'],
                    Fecha_de_entrega=row['Fecha_de_entrega'],
                    Direccion=row['Direccion'],
                    Comuna=row['Comuna'],
                    Cantidad_de_Modelos=row['Cantidad_de_Modelos'],
                    Desde_del_proyecto=row['Desde_del_proyecto']
                )
                db.session.add(proyecto)
                current_app.logger.info(f"Registro en Proyectos añadido: {proyecto}")

        if 'Vendedores' in xls.sheet_names:
            df_vendedores = pd.read_excel(xls, sheet_name='Vendedores')
            df_vendedores = df_vendedores.where(pd.notnull(df_vendedores), None)
            for _, row in df_vendedores.iterrows():
                current_app.logger.info(f"Insertando registro en Vendedores: {row.to_dict()}")
                vendedor = Vendedor(
                    Inmobiliaria=row['Inmobiliaria'],
                    Proyecto=row['Proyecto'],
                    Vendedor=row['Vendedor'],
                    Telefono=row['Telefono'],
                    Email=row['Email'],
                    Direccion_Sala_de_ventas=row['Direccion_Sala_de_ventas']
                )
                db.session.add(vendedor)
                current_app.logger.info(f"Registro en Vendedores añadido: {vendedor}")

        current_app.logger.info("Confirmando los cambios en la base de datos...")
        db.session.commit()
        current_app.logger.info("Datos insertados exitosamente")

    except SQLAlchemyError as e:
        db.session.rollback()
        current_app.logger.error(f"Error de SQLAlchemy: {e}")
        raise e
    except Exception as e:
        current_app.logger.error(f"Error al procesar el archivo: {e}")
        raise e
        
        
@bp.route('/get_table_data', methods=['POST'])
@login_required
def get_table_data():
    table = request.json.get('table')
    if table == 'vendedores':
        data = Vendedor.query.all()
    elif table == 'proyectos':
        data = Proyecto.query.all()
    elif table == 'precios':
        data = Precio.query.all()
    else:
        return jsonify({"error": "Tabla no encontrada"}), 400

    # Renderiza los datos de la tabla en HTML
    rendered_data = render_template(f'tables/{table}_table.html', data=data)
    return jsonify(rendered_data)


@bp.route('/update_table_data', methods=['POST'])
@login_required
def update_table_data():
    data = request.json
    table = data.get('table')
    id = data.get('id')
    field = data.get('field')
    value = data.get('value')
    
    current_app.logger.info(f"Actualizando datos en la tabla: {table}, ID: {id}, campo: {field}, valor: {value}")
    
    if table == 'vendedores':
        record = Vendedor.query.get(id)
    elif table == 'proyectos':
        record = Proyecto.query.get(id)
    elif table == 'precios':
        record = Precio.query.get(id)
    else:
        return jsonify({"success": False, "message": "Tabla no encontrada"}), 400
    
    if not record:
        return jsonify({"success": False, "message": "Registro no encontrado"}), 404

    # Convertir el valor booleano a un valor Python
    if field == 'En_Stock':
        value = value.lower() in ['true', '1', 'yes']
    
    setattr(record, field, value)
    
    try:
        db.session.commit()
        current_app.logger.info(f"Datos actualizados en la tabla: {table}, ID: {id}")
        return jsonify({"success": True, "message": "Datos actualizados exitosamente"})
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Error al actualizar los datos: {e}")
        return jsonify({"success": False, "message": str(e)}), 500


# Endpoint para obtener proyectos en JSON
@bp.route('/api/proyectos', methods=['GET'])
def get_proyectos():
    proyectos = Proyecto.query.all()
    formatted_proyectos = []
    for proyecto in proyectos:
        formatted_proyectos.append({
            "Proyecto": proyecto.Proyecto,
            "Inmobiliaria": proyecto.Inmobiliaria,
            "Fecha_de_entrega": proyecto.Fecha_de_entrega.isoformat() if proyecto.Fecha_de_entrega else None,
            "Direccion": proyecto.Direccion,
            "Comuna": proyecto.Comuna,
            "Cantidad_de_Modelos": proyecto.Cantidad_de_Modelos,
            "Desde_del_proyecto": proyecto.Desde_del_proyecto
        })
    return jsonify({"response": formatted_proyectos})



# Endpoint para obtener vendedores en JSON
@bp.route('/api/vendedores', methods=['GET'])
def get_vendedores():
    vendedores = Vendedor.query.all()
    return jsonify([vendedor.to_dict() for vendedor in vendedores])

# Endpoint para obtener precios en JSON
@bp.route('/api/precios', methods=['GET'])
def get_precios():
    precios = Precio.query.all()
    return jsonify([precio.to_dict() for precio in precios])


# Endpoint para obtener detalles de un proyecto específico
@bp.route('/api/proyectos/<int:id>', methods=['GET'])
def get_proyecto(id):
    proyecto = Proyecto.query.get_or_404(id)
    return jsonify(proyecto.to_dict())

# Endpoint para obtener modelos disponibles de un proyecto específico
@bp.route('/api/proyectos/<int:id>/modelos', methods=['GET'])
def get_modelos_proyecto(id):
    precios = Precio.query.filter_by(Proyecto=id).all()
    return jsonify([precio.to_dict() for precio in precios])

# Endpoint para buscar proyectos por comuna
@bp.route('/api/proyectos/comuna/<string:comuna>', methods=['GET'])
def get_proyectos_por_comuna(comuna):
    proyectos = Proyecto.query.filter_by(Comuna=comuna).all()
    return jsonify([proyecto.to_dict() for proyecto in proyectos])

# Endpoint para obtener información de un vendedor específico
@bp.route('/api/vendedores/<int:id>', methods=['GET'])
def get_vendedor(id):
    vendedor = Vendedor.query.get_or_404(id)
    return jsonify(vendedor.to_dict())

# Endpoint para obtener precios en un rango específico
@bp.route('/api/precios/rango', methods=['GET'])
def get_precios_rango():
    desde = request.args.get('desde', type=float)
    hasta = request.args.get('hasta', type=float)
    precios = Precio.query.filter(Precio.Desde >= desde, Precio.Hasta <= hasta).all()
    return jsonify([precio.to_dict() for precio in precios])
