from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify
from flask_login import login_required, current_user
from flask_wtf import FlaskForm
from wtforms import StringField, SelectField, TextAreaField, SubmitField
from wtforms.validators import DataRequired, Length

from services.project_service import (
    create_project,
    update_project,
    get_project,
    delete_project,
    get_all_projects,
    get_project_children,
    get_project_document_count,
    filter_projects,
    archive_project,
)
from services.schema_service import get_all_schemas
from utils.security import permission_required

# Definir Blueprint
projects_bp = Blueprint("projects", __name__, url_prefix="/projects")


# Formularios
class ProjectForm(FlaskForm):
    """Formulario de proyecto."""

    descripcion = StringField(
        "Descripción", validators=[DataRequired(), Length(1, 100)]
    )
    cliente = StringField("Cliente", validators=[DataRequired(), Length(1, 100)])
    destinacion = StringField("Destinación", validators=[Length(0, 100)])
    esquema = SelectField("Esquema", validators=[DataRequired()])
    proyecto_padre = SelectField("Proyecto Padre", validators=[])
    submit = SubmitField("Guardar")


class ProjectFilterForm(FlaskForm):
    """Formulario de filtrado de proyectos."""

    cliente = StringField("Cliente")
    estado = SelectField(
        "Estado",
        choices=[("", "Todos"), ("activo", "Activo"), ("inactivo", "Inactivo")],
    )
    ano_inicio = StringField("Año Inicio")
    ano_fin = StringField("Año Fin")
    descripcion = StringField("Descripción")
    submit = SubmitField("Filtrar")


# Rutas
@projects_bp.route("/")
@login_required
def list():
    """Listar proyectos."""
    filter_form = ProjectFilterForm(request.args)

    # Obtener proyectos según filtros
    if request.args:
        projects = filter_projects(request.args)
    else:
        projects = get_all_projects()

    return render_template(
        "projects/list.html", projects=projects, filter_form=filter_form
    )


@projects_bp.route("/create", methods=["GET", "POST"])
@login_required
@permission_required(1000)  # Nivel mínimo para crear proyectos
def create():
    """Crear nuevo proyecto."""
    form = ProjectForm()

    # Cargar opciones para esquemas
    schemas = get_all_schemas()
    form.esquema.choices = [
        (schema["id"], schema.get("name", "") or schema.get("descripcion", ""))
        for schema in schemas
    ]

    # Cargar opciones para proyectos padre
    projects = [(p["codigo"], p["descripcion"]) for p in get_all_projects()]
    form.proyecto_padre.choices = [("", "Ninguno")] + projects

    if form.validate_on_submit():
        # Preparar datos del proyecto
        project_data = {
            "descripcion": form.descripcion.data,
            "cliente": form.cliente.data,
            "destinacion": form.destinacion.data,
            "esquema": form.esquema.data,
            "proyecto_padre": (
                form.proyecto_padre.data if form.proyecto_padre.data else None
            ),
        }

        # Crear proyecto
        success, message, project_id = create_project(
            project_data, current_user.username
        )

        if success:
            flash(message, "success")
            return redirect(url_for("projects.view", project_id=project_id))
        else:
            flash(message, "danger")

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


@projects_bp.route("/<project_id>")
@login_required
def view(project_id):
    """Ver detalles de un proyecto."""
    project = get_project(project_id)

    if not project:
        flash("Proyecto no encontrado.", "danger")
        return redirect(url_for("projects.list"))

    # Obtener información adicional
    children = get_project_children(project_id)
    document_count = get_project_document_count(project_id)

    return render_template(
        "projects/view.html",
        project=project,
        children=children,
        document_count=document_count,
    )


@projects_bp.route("/<project_id>/edit", methods=["GET", "POST"])
@login_required
@permission_required(5000)  # Nivel mínimo para editar proyectos
def edit(project_id):
    """Editar un proyecto."""
    project = get_project(project_id)

    if not project:
        flash("Proyecto no encontrado.", "danger")
        return redirect(url_for("projects.list"))

    form = ProjectForm()

    # Cargar opciones para esquemas
    schemas = get_all_schemas()
    form.esquema.choices = [
        (schema["id"], schema.get("name", "") or schema.get("descripcion", ""))
        for schema in schemas
    ]

    # Cargar opciones para proyectos padre (excluyendo este proyecto y sus hijos)
    all_projects = get_all_projects()
    children_codes = [child["codigo"] for child in get_project_children(project_id)]
    available_projects = [
        (p["codigo"], p["descripcion"])
        for p in all_projects
        if p["codigo"] != project["codigo"] and p["codigo"] not in children_codes
    ]

    form.proyecto_padre.choices = [("", "Ninguno")] + available_projects

    if request.method == "GET":
        # Cargar datos actuales
        form.descripcion.data = project["descripcion"]
        form.cliente.data = project["cliente"]
        form.destinacion.data = project.get("destinacion", "")
        form.esquema.data = project["esquema"]
        form.proyecto_padre.data = project.get("proyecto_padre", "")

    if form.validate_on_submit():
        # Preparar datos actualizados
        project_data = {
            "descripcion": form.descripcion.data,
            "cliente": form.cliente.data,
            "destinacion": form.destinacion.data,
            "esquema": form.esquema.data,
            "proyecto_padre": (
                form.proyecto_padre.data if form.proyecto_padre.data else None
            ),
        }

        # Actualizar proyecto
        success, message = update_project(
            project_id, project_data, current_user.username
        )

        if success:
            flash(message, "success")
            return redirect(url_for("projects.view", project_id=project_id))
        else:
            flash(message, "danger")

    return render_template(
        "projects/edit.html", form=form, project=project, schemas=schemas
    )


@projects_bp.route("/<project_id>/delete", methods=["POST"])
@login_required
@permission_required(9000)  # Nivel alto para eliminar proyectos
def delete(project_id):
    """Eliminar un proyecto (marcar como inactivo)."""
    success, message = delete_project(project_id)

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

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


@projects_bp.route("/<project_id>/archive", methods=["POST"])
@login_required
@permission_required(9000)  # Nivel alto para archivar proyectos
def archive(project_id):
    """Archivar un proyecto."""
    success, message = archive_project(project_id, current_user.username)

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

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


@projects_bp.route("/api/list")
@login_required
def api_list():
    """API para listar proyectos (para selects dinámicos)."""
    projects = get_all_projects()
    return jsonify([{"id": p["codigo"], "text": p["descripcion"]} for p in projects])
