from io import StringIO

import markdown
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from flask import (abort, flash, jsonify, redirect, render_template, request,
                   url_for)
from flask_login import current_user, login_required

from ..data import CRITERIA, PILLARS, SCALES_LABELS
from ..extensions import db
from ..models import Article, Score, Solution, Tag, Users
from ..utils import allowed_file, save_logo
from . import bp

matplotlib.use("Agg")


def create_styled_radar_chart(stats, categories):
    """
    stats: Dictionnaire { "Nom Solution": [v1, v2, v3, v4, v5, v6] }
    categories: Liste des labels des axes (ex: ['AS1', 'AS2'...])
    """

    labels = categories
    num_vars = len(labels)

    angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist()
    angles += angles[:1]

    fig, ax = plt.subplots(figsize=(5, 5), subplot_kw=dict(polar=True))

    ax.set_theta_offset(np.pi / 2)
    ax.set_theta_direction(-1)

    ax.set_xticks(angles[:-1])
    ax.set_xticklabels(labels, size=12, color="#444444", weight="normal")
    ax.xaxis.set_tick_params(pad=30)
    ax.set_ylim(0, 5)
    ax.set_yticks([1, 2, 3, 4, 5])
    ax.set_yticklabels(["1", "2", "3", "4", "5"], color="#999999", size=10)
    ax.grid(color="#DDDDDD", linestyle="-", linewidth=1)

    ax.spines["polar"].set_visible(False)

    for name, data in stats.items():
        values = data + data[:1]

        color = "#333333"
        ax.plot(angles, values, color=color, linewidth=2,
                linestyle="solid", label=name)
        ax.fill(angles, values, color=color, alpha=0.25)

    svg_output = StringIO()
    plt.savefig(svg_output, format="svg",
                bbox_inches="tight", transparent=True)
    plt.close(fig)

    svg_content = svg_output.getvalue()

    return svg_content


@bp.route("/")
def home():
    search_query = request.args.get("search")
    tag_filter = request.args.get("tag")

    query = Solution.query.filter_by(is_validated=True)

    if search_query:
        query = query.filter(Solution.name.ilike(f"%{search_query}%"))

    if tag_filter and tag_filter != "all":
        query = query.join(Solution.tags).filter(Tag.name == tag_filter)

    solutions = query.all()

    total_solutions = Solution.query.filter_by(is_validated=True).count()
    total_users = Users.query.count()
    all_tags = Tag.query.order_by(Tag.name).all()

    return render_template(
        "home.html",
        solutions=solutions,
        tags=all_tags,
        total_solutions=total_solutions,
        total_users=total_users,
        active_tag=tag_filter
    )


@bp.route("/submit", methods=["GET", "POST"])
@login_required
def submit_solution():

    if request.method == "POST":

        name = request.form.get("name")

        description = request.form.get("description")

        website = request.form.get("website")

        logo = request.files.get("logo")

        logo_filename = None

        if logo and allowed_file(logo.filename):

            logo_filename = save_logo(logo)

        new_solution = Solution(




            name=name,




            description=description,




            website=website,




            logo_filename=logo_filename,




            origin=request.form.get("origin"),




            license=request.form.get("license"),




            platforms=request.form.get("platforms"),




        )

        tags_input = request.form.get("tags")

        if tags_input:

            tag_names = [t.strip() for t in tags_input.split(",") if t.strip()]

            for tag_name in tag_names:

                tag = Tag.query.filter_by(name=tag_name).first()

                if not tag:

                    tag = Tag(name=tag_name)

                    db.session.add(tag)

                new_solution.tags.append(tag)

        db.session.add(new_solution)

        db.session.commit()

        for p_id, c_id, title, desc, choices in CRITERIA:

            val = request.form.get(f"rating_{c_id}")

            justif = request.form.get(f"justification_{c_id}")

            src = request.form.get(f"source_{c_id}")

            if val is not None:

                new_score = Score(




                    solution_id=new_solution.id,




                    criterion_id=c_id,




                    value=int(val),




                    justification=justif,




                    source=src,




                )

                db.session.add(new_score)

        db.session.commit()

        flash("Solution soumise pour validation !")

        return redirect(url_for("main.home"))

    return render_template(




        "submit.html", pillars=PILLARS, criteria=CRITERIA, scales_labels=SCALES_LABELS




    )


@bp.route("/solution/<int:id>")
def solution_detail(id):
    solution = Solution.query.get_or_404(id)

    stats = solution.calculate_scores()

    chart_labels = []
    chart_data = []

    for p_id, p_name in PILLARS.items():
        chart_labels.append(p_name)
        chart_data.append(stats["pillars"].get(p_id, 0))

    scores_map = {s.criterion_id: s for s in solution.scores}
    radar_svg = create_styled_radar_chart(
        {solution.name: chart_data}, chart_labels)

    return render_template(
        "detail.html",
        solution=solution,
        stats=stats,
        scores_map=scores_map,
        chart_labels=chart_labels,
        chart_data=chart_data,
        radar_svg=radar_svg,
        criteria=CRITERIA,
        pillars=PILLARS,
    )


@bp.route("/referentiel")
def referentiel():
    return render_template("referentiel.html", pillars=PILLARS, criteria=CRITERIA)


@bp.route("/blog")
def blog():
    query = Article.query.filter_by(published=True)
    if current_user.is_authenticated and current_user.is_admin:
        query = Article.query  # Admin sees all

    articles = query.order_by(Article.created_at.desc()).all()
    return render_template("blog.html", articles=articles)


@bp.route("/blog/<slug>")
def blog_post(slug):
    article = Article.query.filter_by(slug=slug).first_or_404()

    if not article.published and not (
        current_user.is_authenticated and current_user.is_admin
    ):
        abort(404)

    content_html = markdown.markdown(article.content)
    return render_template("blog_post.html", article=article, content_html=content_html)


@bp.route("/export/json")
def export_solutions():
    solutions = Solution.query.filter_by(is_validated=True).all()
    data = []

    for sol in solutions:
        scores = {s.criterion_id: s.value for s in sol.scores}
        tags = [t.name for t in sol.tags]

        sol_data = {
            "id": sol.id,
            "name": sol.name,
            "description": sol.description,
            "website": sol.website,
            "origin": sol.origin,
            "license": sol.license,
            "platforms": sol.platforms,
            "tags": tags,
            "scores": scores,
            "validated_at": sol.created_at.isoformat() if sol.created_at else None,
        }
        data.append(sol_data)

    return jsonify(data)
