from flask import (
    Blueprint,
    render_template,
    redirect,
    url_for,
    flash,
    request,
    jsonify,
    current_app,
)
from flask_login import login_required, current_user
from flask_wtf import FlaskForm
from wtforms import (
    StringField,
    TextAreaField,
    FieldList,
    FormField,
    SelectField,
    IntegerField,
    SubmitField,
)
from wtforms.validators import DataRequired, Length, NumberRange

from services.schema_service import (
    get_all_schemas,
    get_schema_by_id,
    create_schema,
    update_schema,
    delete_schema,
)
from services.document_service import get_allowed_filetypes
from utils.security import permission_required
from utils.validators import validate_schema_data

# Definir Blueprint
schemas_bp = Blueprint("schemas", __name__, url_prefix="/schemas")


# Formularios
class DocumentTypeForm(FlaskForm):
    """Formulario para tipo de documento en esquema."""

    tipo = StringField("Tipo de Documento", validators=[DataRequired()])
    nombre = StringField("Nombre", validators=[DataRequired()])
    nivel_ver = IntegerField("Nivel para Ver", default=0)
    nivel_editar = IntegerField("Nivel para Editar", default=5000)


class SchemaForm(FlaskForm):
    """Formulario para esquema."""

    codigo = StringField("Código", validators=[DataRequired(), Length(1, 20)])
    descripcion = TextAreaField("Descripción", validators=[DataRequired()])
    documentos = FieldList(FormField(DocumentTypeForm), min_entries=1)
    submit = SubmitField("Guardar")


# Rutas
@schemas_bp.route("/")
@login_required
@permission_required(5000)  # Nivel mínimo para ver esquemas
def list():
    """Lista todos los esquemas disponibles."""
    schemas = get_all_schemas()
    return render_template("schemas/list.html", schemas=schemas)


@schemas_bp.route("/view/<schema_id>")
@login_required
@permission_required(5000)
def view(schema_id):
    """Ver detalle de un esquema."""
    schema = get_schema_by_id(schema_id)
    if not schema:
        flash("Esquema no encontrado.", "danger")
        return redirect(url_for("schemas.list"))

    return render_template("schemas/view.html", schema=schema)


@schemas_bp.route("/create", methods=["GET", "POST"])
@login_required
@permission_required(9000)  # Solo administradores
def create():
    """Crear nuevo esquema."""
    form = SchemaForm()

    if form.validate_on_submit():
        data = {
            "codigo": form.codigo.data,
            "descripcion": form.descripcion.data,
            "documentos": [],
        }

        for doc_form in form.documentos:
            data["documentos"].append(
                {
                    "tipo": doc_form.tipo.data,
                    "nombre": doc_form.nombre.data,
                    "nivel_ver": doc_form.nivel_ver.data,
                    "nivel_editar": doc_form.nivel_editar.data,
                }
            )

        success, message = create_schema(data, current_user.id)

        if success:
            flash(message, "success")
            return redirect(url_for("schemas.list"))
        else:
            flash(message, "danger")

    return render_template("schemas/create.html", form=form)


@schemas_bp.route("/edit/<schema_id>", methods=["GET", "POST"])
@login_required
def edit_schema(schema_id):
    schema = get_schema_by_id(schema_id)

    if not schema:
        flash("Esquema no encontrado", "danger")
        return redirect(url_for("schemas.list"))

    filetypes = get_allowed_filetypes()

    if request.method == "POST":
        # Extract form data
        nombre = request.form.get("nombre")
        descripcion = request.form.get("descripcion")

        # Update schema data
        updated_schema = {
            "id": schema_id,
            "nombre": nombre,
            "descripcion": descripcion,
            "created_by": schema.get("created_by"),
            "created_at": schema.get("created_at"),
            "documentos": schema.get("documentos", []),
        }

        success = update_schema(schema_id, updated_schema)

        if success:
            flash("Esquema actualizado correctamente", "success")
            return redirect(url_for("schemas.list"))
        else:
            flash("Error al actualizar el esquema", "danger")

    return render_template("schemas/edit.html", schema=schema, filetypes=filetypes)


@schemas_bp.route("/delete/<schema_id>", methods=["POST"])
@login_required
@permission_required(9000)  # Solo administradores
def delete(schema_id):
    """Eliminar esquema."""
    success, message = delete_schema(schema_id)

    if success:
        flash(message, "success")
    else:
        flash(message, "danger")

    return redirect(url_for("schemas.list"))


@schemas_bp.route("/api/list")
@login_required
def api_list():
    """API para listar esquemas."""
    schemas = get_all_schemas()
    return jsonify(
        [
            {"code": code, "description": schema["descripcion"]}
            for code, schema in schemas.items()
        ]
    )


@schemas_bp.route("/api/get/<schema_code>")
@login_required
def api_get(schema_code):
    """API para obtener un esquema específico."""
    schema = get_schema_by_id(schema_code)

    if not schema:
        return jsonify({"error": "Esquema no encontrado"}), 404

    return jsonify(schema)
