"""
PN / Référentiel de compétences

Emmanuel Viennet, 2021
"""

from flask import url_for, flash
from flask import jsonify
from flask import current_app, g, request
from flask.templating import render_template
from flask_login import current_user
from werkzeug.utils import redirect
from werkzeug.utils import secure_filename

from config import Config

from app import db
from app import models

from app.decorators import scodoc, permission_required
from app.models import Formation
from app.models.but_refcomp import ApcReferentielCompetences
from app.but.import_refcomp import orebut_import_refcomp
from app.but.forms.refcomp_forms import FormationRefCompForm, RefCompLoadForm
from app.scodoc.gen_tables import GenTable
from app.scodoc import html_sidebar
from app.scodoc import sco_utils as scu
from app.scodoc.sco_exceptions import ScoFormatError
from app.scodoc.sco_permissions import Permission
from app.views import notes_bp as bp
from app.views import ScoData


@bp.route("/referentiel/comp/get/<int:refcomp_id>")
@scodoc
@permission_required(Permission.ScoView)
def refcomp(refcomp_id):
    ref = ApcReferentielCompetences.query.get_or_404(refcomp_id)
    return jsonify(ref.to_dict())


@bp.route("/referentiel/comp/show/<int:refcomp_id>")
@scodoc
@permission_required(Permission.ScoView)
def refcomp_show(refcomp_id):
    ref = ApcReferentielCompetences.query.get_or_404(refcomp_id)
    return render_template(
        "but/refcomp_show.html",
        ref=ref,
        title="Référentiel de compétences",
        sco=ScoData(),
    )


@bp.route("/referentiel/comp/delete/<int:refcomp_id>", methods=["GET", "POST"])
@scodoc
@permission_required(Permission.ScoChangeFormation)
def refcomp_delete(refcomp_id):
    ref = ApcReferentielCompetences.query.get_or_404(refcomp_id)
    db.session.delete(ref)
    db.session.commit()
    flash("référentiel de compétences supprimé")
    return redirect(url_for("notes.refcomp_table", scodoc_dept=g.scodoc_dept))


@bp.route("/referentiel/comp/table")
@scodoc
@permission_required(Permission.ScoView)
def refcomp_table():
    """Liste html des ref. comp. chargés dans ce département"""
    refs = ApcReferentielCompetences.query.filter_by(dept_id=g.scodoc_dept_id)
    columns_ids = ("type_titre", "specialite_long", "json", "nb_formations")
    if current_user.has_permission(Permission.ScoChangeFormation):
        columns_ids = ("suppr",) + columns_ids
    suppr_icon = scu.icontag(
        "delete_small_img", border="0", alt="supprimer", title="Supprimer"
    )
    tab = GenTable(
        columns_ids=columns_ids,
        titles={
            "suppr": "",
            "type_titre": "Type",
            "specialite_long": "Spécialité",
            "json": "Export",
            "nb_formations": "Formations",
        },
        rows=[
            {
                "type_titre": ref.type_titre,
                "specialite_long": ref.specialite_long,
                "_specialite_long_target": url_for(
                    "notes.refcomp_show", scodoc_dept=g.scodoc_dept, refcomp_id=ref.id
                ),
                "json": "json",
                "_json_target": url_for(
                    "notes.refcomp", scodoc_dept=g.scodoc_dept, refcomp_id=ref.id
                ),
                "nb_formations": len(ref.formations),
                "suppr": suppr_icon,
                "_suppr_target": url_for(
                    "notes.refcomp_delete", scodoc_dept=g.scodoc_dept, refcomp_id=ref.id
                ),
            }
            for ref in refs
        ],
    )
    return render_template(
        "but/refcomp_table.html",
        tab=tab,
        title="Référentiels de compétences",
        sco=ScoData(),
    )


@bp.route(
    "/referentiel/comp/assoc_formation/<int:formation_id>", methods=["GET", "POST"]
)
@scodoc
@permission_required(Permission.ScoChangeFormation)
def refcomp_assoc_formation(formation_id: int):
    """Formulaire association ref. compétence"""
    formation = Formation.query.get_or_404(formation_id)
    form = FormationRefCompForm()
    form.referentiel_competence.choices = [
        (r.id, f"{r.type_titre} {r.specialite_long}")
        for r in ApcReferentielCompetences.query.filter_by(dept_id=g.scodoc_dept_id)
    ]
    if request.method == "POST" and form.cancel.data:  # cancel button
        return redirect(
            url_for(
                "notes.ue_table", scodoc_dept=g.scodoc_dept, formation_id=formation_id
            )
        )
    if form.validate_on_submit():
        referentiel_competence_id = form.referentiel_competence.data
        assert (
            ApcReferentielCompetences.query.get(referentiel_competence_id) is not None
        )
        formation.referentiel_competence_id = referentiel_competence_id
        db.session.add(formation)
        db.session.commit()
        flash("nouveau référentiel de compétences associé")
        return redirect(
            url_for(
                "notes.ue_table", scodoc_dept=g.scodoc_dept, formation_id=formation_id
            )
        )
    return render_template(
        "but/refcomp_assoc.html",
        form=form,
        referentiel_competence_id=formation.referentiel_competence_id,
        formation=formation,
        title="Association réf. compétences",
    )


@bp.route(
    "/referentiel/comp/load", defaults={"formation_id": None}, methods=["GET", "POST"]
)
@bp.route("/referentiel/comp/load/<int:formation_id>", methods=["GET", "POST"])
@scodoc
@permission_required(Permission.ScoChangeFormation)
def refcomp_load(formation_id=None):
    """Formulaire association ref. compétence"""
    if formation_id is not None:
        formation = Formation.query.get_or_404(formation_id)
    else:
        formation = None
    form = RefCompLoadForm()
    if form.validate_on_submit():
        f = form.upload.data
        filename = secure_filename(f.filename)
        try:
            xml_data = f.read()
            ref = orebut_import_refcomp(
                xml_data, dept_id=g.scodoc_dept_id, orig_filename=filename
            )
        except TypeError as exc:
            raise ScoFormatError("fichier XML Orébut invalide") from exc
        except ScoFormatError:
            raise

        if formation is not None:
            return redirect(
                url_for(
                    "notes.refcomp_assoc_formation",
                    scodoc_dept=g.scodoc_dept,
                    formation_id=formation.formation_id,
                )
            )
        else:
            return redirect(url_for("notes.index_html", scodoc_dept=g.scodoc_dept))

    return render_template(
        "but/refcomp_load.html",
        form=form,
        formation=formation,
        title="Chargement réf. compétences",
    )