import json
from flask import Blueprint, render_template, request, redirect, url_for, flash
from controllers.auth_controller import login_required, admin_required
from models.recommendation_model import RecommendationModel
from models.temperament_model import TemperamentModel
from utils.i18n import t


recommendation_bp = Blueprint('recommendation', __name__)


def _parse_temperament_orders(raw_orders, valid_ids):
    if not raw_orders:
        return []
    try:
        parsed = json.loads(raw_orders)
    except json.JSONDecodeError:
        return []

    cleaned = []
    for value in parsed:
        try:
            temp_id = int(value)
        except (TypeError, ValueError):
            continue
        if temp_id in valid_ids and temp_id not in cleaned:
            cleaned.append(temp_id)
    return cleaned


def _build_context_with_temperaments(selected_ids=None):
    temperaments = TemperamentModel.get_all_temperaments()
    selected_ids = selected_ids or []
    temperament_lookup = {temp['id']: temp for temp in temperaments}
    selected_temperaments = [temperament_lookup[temp_id] for temp_id in selected_ids if temp_id in temperament_lookup]
    selected_ids_json = json.dumps([temp['id'] for temp in selected_temperaments])
    return {
        'temperaments': temperaments,
        'selected_temperaments': selected_temperaments,
        'selected_ids_json': selected_ids_json
    }


@recommendation_bp.route('/')
@login_required
def index():
    recommendations = RecommendationModel.get_all_recommendations()
    temperaments = TemperamentModel.get_all_temperaments()
    temperament_lookup = {temp['id']: temp for temp in temperaments}

    for recommendation in recommendations:
        orders = recommendation.get('temperaments_orders', [])
        recommendation['temperament_details'] = [
            temperament_lookup[temp_id]
            for temp_id in orders
            if temp_id in temperament_lookup
        ]

    return render_template(
        'recommendations/index.html',
        recommendations=recommendations
    )


@recommendation_bp.route('/create', methods=['GET', 'POST'])
@login_required
@admin_required
def create():
    context = _build_context_with_temperaments()

    if request.method == 'POST':
        name = (request.form.get('name') or '').strip()
        description = (request.form.get('description') or '').strip()
        valid_ids = {temp['id'] for temp in context['temperaments']}
        selected_ids = _parse_temperament_orders(request.form.get('temperaments_orders'), valid_ids)

        if not name:
            flash(t('messages.name_required', 'Name is required'), 'error')
            filled_context = _build_context_with_temperaments(selected_ids)
            return render_template('recommendations/create.html', **filled_context, form_data={'name': name, 'description': description})

        if not selected_ids:
            flash(t('messages.recommendation_temperament_required', 'Select at least one temperament order'), 'error')
            filled_context = _build_context_with_temperaments(selected_ids)
            return render_template('recommendations/create.html', **filled_context, form_data={'name': name, 'description': description})

        RecommendationModel.create_recommendation(name, description, selected_ids)
        flash(t('messages.recommendation_created', 'Recommendation created successfully!'), 'success')
        return redirect(url_for('recommendation.index'))

    return render_template('recommendations/create.html', **context, form_data={'name': '', 'description': ''})


@recommendation_bp.route('/edit/<int:recommendation_id>', methods=['GET', 'POST'])
@login_required
@admin_required
def edit(recommendation_id):
    recommendation = RecommendationModel.get_recommendation_by_id(recommendation_id)
    if not recommendation:
        flash(t('messages.recommendation_not_found', 'Recommendation not found'), 'error')
        return redirect(url_for('recommendation.index'))

    context = _build_context_with_temperaments(recommendation.get('temperaments_orders', []))

    if request.method == 'POST':
        name = (request.form.get('name') or '').strip()
        description = (request.form.get('description') or '').strip()
        valid_ids = {temp['id'] for temp in context['temperaments']}
        selected_ids = _parse_temperament_orders(request.form.get('temperaments_orders'), valid_ids)

        if not name:
            flash(t('messages.name_required', 'Name is required'), 'error')
            filled_context = _build_context_with_temperaments(selected_ids)
            temp_recommendation = dict(recommendation)
            temp_recommendation['temperaments_orders'] = selected_ids
            return render_template('recommendations/edit.html', recommendation=temp_recommendation, **filled_context, form_data={'name': name, 'description': description})

        if not selected_ids:
            flash(t('messages.recommendation_temperament_required', 'Select at least one temperament order'), 'error')
            filled_context = _build_context_with_temperaments(selected_ids)
            temp_recommendation = dict(recommendation)
            temp_recommendation['temperaments_orders'] = selected_ids
            return render_template('recommendations/edit.html', recommendation=temp_recommendation, **filled_context, form_data={'name': name, 'description': description})

        RecommendationModel.update_recommendation(recommendation_id, name, description, selected_ids)
        flash(t('messages.recommendation_updated', 'Recommendation updated successfully!'), 'success')
        return redirect(url_for('recommendation.index'))

    form_data = {
        'name': recommendation.get('name', ''),
        'description': recommendation.get('description', '')
    }

    return render_template('recommendations/edit.html', recommendation=recommendation, **context, form_data=form_data)


@recommendation_bp.route('/delete/<int:recommendation_id>')
@login_required
@admin_required
def delete(recommendation_id):
    recommendation = RecommendationModel.get_recommendation_by_id(recommendation_id)
    if not recommendation:
        flash(t('messages.recommendation_not_found', 'Recommendation not found'), 'error')
        return redirect(url_for('recommendation.index'))

    RecommendationModel.delete_recommendation(recommendation_id)
    flash(t('messages.recommendation_deleted', 'Recommendation deleted successfully!'), 'success')
    return redirect(url_for('recommendation.index'))
