from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify
from flask_login import login_required, current_user
from app.extensions import db
from app.models.custom_module import CustomModule, CustomModuleAssignment
from app.models.project import Project
from app.models.aufmass import Aufmass
from app.models.position import Position
from app.models.user import User
from app.models.company import Company
from app.services.custom_module_renderer import render_form
from app.services.custom_module_executor import execute_rules
import json

custom_modules_bp = Blueprint('custom_modules', __name__, url_prefix='/custom-modules')

def _can_manage(user, module=None):
    if user.is_superadmin():
        return True
    if user.is_firmadmin():
        if module is None:
            return True
        if module.is_template:
            return False
        return module.company_id == user.company_id
    return False

def _can_use(user, module):
    if user.is_superadmin():
        return True
    if user.is_firmadmin() and module.company_id == user.company_id:
        return True
    if not module.is_active:
        return False
    return CustomModuleAssignment.query.filter_by(
        module_id=module.id, user_id=user.id
    ).first() is not None

@custom_modules_bp.route('/')
@login_required
def index():
    if not _can_manage(current_user):
        flash('Keine Berechtigung.', 'danger')
        return redirect(url_for('admin.dashboard'))

    if current_user.is_superadmin():
        templates = CustomModule.query.filter_by(is_template=True).order_by(CustomModule.sort_index).all()
        company_modules = CustomModule.query.filter_by(is_template=False).order_by(CustomModule.company_id, CustomModule.sort_index).all()
        companies = Company.query.order_by(Company.name).all()
    else:
        templates = CustomModule.query.filter_by(is_template=True, is_active=True).order_by(CustomModule.sort_index).all()
        company_modules = CustomModule.query.filter_by(
            company_id=current_user.company_id, is_template=False
        ).order_by(CustomModule.sort_index).all()
        companies = []

    return render_template('custom_modules/index.html',
                         templates=templates,
                         company_modules=company_modules,
                         companies=companies)

@custom_modules_bp.route('/neu', methods=['GET', 'POST'])
@login_required
def neu():
    if not _can_manage(current_user):
        flash('Keine Berechtigung.', 'danger')
        return redirect(url_for('admin.dashboard'))

    if request.method == 'POST':
        name = request.form.get('name', '').strip()
        if not name:
            flash('Name ist erforderlich.', 'danger')
            return render_template('custom_modules/edit.html', module=None)

        module = CustomModule(
            company_id=current_user.company_id if not current_user.is_superadmin() else None,
            name=name,
            description=request.form.get('description', ''),
            kategorie=request.form.get('kategorie', 'allgemein'),
            icon=request.form.get('icon', '🔧'),
            is_template=bool(request.form.get('is_template')) if current_user.is_superadmin() else False,
            form_json='[]',
            rules_json='[]',
            created_by=current_user.id,
        )
        db.session.add(module)
        db.session.commit()
        flash(f'Modul "{name}" erstellt.', 'success')
        return redirect(url_for('custom_modules.edit', module_id=module.id))

    return render_template('custom_modules/edit.html', module=None,
                         is_superadmin=current_user.is_superadmin())

@custom_modules_bp.route('/<int:module_id>/bearbeiten', methods=['GET', 'POST'])
@login_required
def edit(module_id):
    module = CustomModule.query.get_or_404(module_id)
    if not _can_manage(current_user, module):
        flash('Keine Berechtigung.', 'danger')
        return redirect(url_for('admin.dashboard'))

    if request.method == 'POST':
        module.name = request.form.get('name', module.name).strip()
        module.description = request.form.get('description', '')
        module.kategorie = request.form.get('kategorie', 'allgemein')
        module.icon = request.form.get('icon', '🔧')
        module.is_active = bool(request.form.get('is_active', True))
        if current_user.is_superadmin():
            module.is_template = bool(request.form.get('is_template', module.is_template))
        db.session.commit()
        flash('Modul aktualisiert.', 'success')
        return redirect(url_for('custom_modules.index'))

    users = []
    if module.company_id:
        users = User.query.filter_by(company_id=module.company_id, aktiv=True).order_by(User.vorname).all()
    assignments = {a.user_id: a for a in module.assignments}

    return render_template('custom_modules/edit.html', module=module,
                         users=users, assignments=assignments,
                         is_superadmin=current_user.is_superadmin())

@custom_modules_bp.route('/<int:module_id>/builder')
@login_required
def builder(module_id):
    module = CustomModule.query.get_or_404(module_id)
    if not _can_manage(current_user, module):
        flash('Keine Berechtigung.', 'danger')
        return redirect(url_for('admin.dashboard'))
    return render_template('custom_modules/builder.html', module=module)

@custom_modules_bp.route('/<int:module_id>/loeschen', methods=['POST'])
@login_required
def loeschen(module_id):
    module = CustomModule.query.get_or_404(module_id)
    if not _can_manage(current_user, module):
        flash('Keine Berechtigung.', 'danger')
        return redirect(url_for('admin.dashboard'))

    name = module.name
    db.session.delete(module)
    db.session.commit()
    flash(f'Modul "{name}" gelöscht.', 'success')
    return redirect(url_for('custom_modules.index'))

@custom_modules_bp.route('/<int:module_id>/importieren', methods=['POST'])
@login_required
def importieren(module_id):
    template = CustomModule.query.get_or_404(module_id)
    if not template.is_template:
        flash('Nur Vorlagen können importiert werden.', 'danger')
        return redirect(url_for('custom_modules.index'))
    if not current_user.is_firmadmin():
        flash('Keine Berechtigung.', 'danger')
        return redirect(url_for('custom_modules.index'))

    existing = CustomModule.query.filter_by(
        company_id=current_user.company_id,
        original_template_id=template.id
    ).first()
    if existing:
        flash(f'Vorlage "{template.name}" bereits als "{existing.name}" importiert.', 'warning')
        return redirect(url_for('custom_modules.index'))

    copy = CustomModule(
        company_id=current_user.company_id,
        original_template_id=template.id,
        name=template.name,
        description=template.description,
        kategorie=template.kategorie,
        icon=template.icon,
        form_json=template.form_json,
        rules_json=template.rules_json,
        is_template=False,
        created_by=current_user.id,
    )
    db.session.add(copy)
    db.session.commit()
    flash(f'Vorlage "{template.name}" importiert – jetzt kannst du sie anpassen.', 'success')
    return redirect(url_for('custom_modules.edit', module_id=copy.id))

@custom_modules_bp.route('/<int:module_id>/als-vorlage', methods=['POST'])
@login_required
def als_vorlage(module_id):
    module = CustomModule.query.get_or_404(module_id)
    if not current_user.is_superadmin():
        flash('Keine Berechtigung.', 'danger')
        return redirect(url_for('admin.dashboard'))

    template = CustomModule(
        company_id=None,
        original_template_id=None,
        name=module.name,
        description=module.description,
        kategorie=module.kategorie,
        icon=module.icon,
        form_json=module.form_json,
        rules_json=module.rules_json,
        is_template=True,
        created_by=current_user.id,
    )
    db.session.add(template)
    db.session.commit()
    flash(f'Modul "{module.name}" als globale Vorlage gespeichert.', 'success')
    return redirect(url_for('custom_modules.index'))

@custom_modules_bp.route('/<int:module_id>/user/<int:user_id>/toggle', methods=['POST'])
@login_required
def user_toggle(module_id, user_id):
    module = CustomModule.query.get_or_404(module_id)
    if not _can_manage(current_user, module):
        return jsonify({'error': 'Keine Berechtigung'}), 403

    user = User.query.get_or_404(user_id)
    assignment = CustomModuleAssignment.query.filter_by(
        module_id=module.id, user_id=user.id
    ).first()

    data = request.get_json(silent=True) or {}
    active = data.get('active', False)
    can_edit = data.get('can_edit', False)

    if active:
        if not assignment:
            assignment = CustomModuleAssignment(
                module_id=module.id, user_id=user.id, can_edit=can_edit
            )
            db.session.add(assignment)
            db.session.commit()
            return jsonify({'message': f'{user.full_name} hat jetzt Zugriff.', 'active': True})
        return jsonify({'active': True})
    else:
        if assignment:
            db.session.delete(assignment)
            db.session.commit()
            return jsonify({'message': f'Zugriff für {user.full_name} entzogen.', 'active': False})
        return jsonify({'active': False})

@custom_modules_bp.route('/<int:module_id>/api/form-json', methods=['GET', 'PUT'])
@login_required
def api_form_json(module_id):
    module = CustomModule.query.get_or_404(module_id)
    if not _can_manage(current_user, module):
        return jsonify({'error': 'Keine Berechtigung'}), 403

    if request.method == 'PUT':
        try:
            data = request.get_json(force=True)
            module.form_json = json.dumps(data, ensure_ascii=False)
            db.session.commit()
            return jsonify({'ok': True})
        except Exception as e:
            return jsonify({'error': str(e)}), 400

    return jsonify(json.loads(module.form_json or '[]'))

@custom_modules_bp.route('/<int:module_id>/api/rules-json', methods=['GET', 'PUT'])
@login_required
def api_rules_json(module_id):
    module = CustomModule.query.get_or_404(module_id)
    if not _can_manage(current_user, module):
        return jsonify({'error': 'Keine Berechtigung'}), 403

    if request.method == 'PUT':
        try:
            data = request.get_json(force=True)
            module.rules_json = json.dumps(data, ensure_ascii=False)
            db.session.commit()
            return jsonify({'ok': True})
        except Exception as e:
            return jsonify({'error': str(e)}), 400

    return jsonify(json.loads(module.rules_json or '[]'))

@custom_modules_bp.route('/<int:module_id>/api/preview')
@login_required
def api_preview(module_id):
    module = CustomModule.query.get_or_404(module_id)
    if not _can_manage(current_user, module):
        return '<div class="notification is-danger">Keine Berechtigung.</div>'
    html = render_form(module.form_json, module_id)
    return html

@custom_modules_bp.route('/api/available')
@login_required
def api_available():
    modules = CustomModule.query.filter(
        CustomModule.is_active == True,
        CustomModule.is_template == False,
        CustomModule.company_id == current_user.company_id
    ).order_by(CustomModule.sort_index).all()

    result = []
    for m in modules:
        if current_user.is_firmadmin() or current_user.is_superadmin():
            result.append({'id': m.id, 'name': m.name, 'icon': m.icon, 'kategorie': m.kategorie})
        elif _can_use(current_user, m):
            result.append({'id': m.id, 'name': m.name, 'icon': m.icon, 'kategorie': m.kategorie})

    return jsonify(result)


@custom_modules_bp.route('/<int:module_id>/formular')
@login_required
def formular(module_id):
    module = CustomModule.query.get_or_404(module_id)
    if not _can_use(current_user, module):
        return '<div class="notification is-danger">Keine Berechtigung für dieses Modul.</div>'

    aufmass_id = request.args.get('aufmass_id')
    html = render_form(module.form_json, module_id, aufmass_id=aufmass_id)
    return html


@custom_modules_bp.route('/<int:module_id>/berechnen', methods=['POST'])
@login_required
def berechnen(module_id):
    module = CustomModule.query.get_or_404(module_id)
    if not _can_use(current_user, module):
        return '<div class="notification is-danger">Keine Berechtigung.</div>'

    aufmass_id = request.args.get('aufmass_id')
    if not aufmass_id:
        return '<div class="notification is-danger">Kein Aufmaß ausgewählt.<br><button class="button is-small is-light mt-2" onclick="closeModulModal()">Schließen</button></div>'

    aufmass = Aufmass.query.get_or_404(aufmass_id)
    project = Project.query.get(aufmass.project_id)
    if not project:
        return '<div class="notification is-danger">Projekt nicht gefunden.<br><button class="button is-small is-light mt-2" onclick="closeModulModal()">Schließen</button></div>'
    project_id = project.id
    company_id = project.company_id

    form_data = {k: v for k, v in request.form.items()}

    rules = json.loads(module.rules_json) if isinstance(module.rules_json, str) else module.rules_json
    positions_data = execute_rules(form_data, module.rules_json, company_id)

    if not positions_data:
        return '''
<div class="notification is-warning" style="margin-top:10px">
  Keine Bedingungen erfüllt – es wurden keine Positionen erzeugt.
  <button class="delete" onclick="closeModulModal()"></button>
</div>
<button class="button is-small is-light mt-2" onclick="closeModulModal()">Schließen</button>'''

    created = 0
    for pd in positions_data:
        pos = Position(
            aufmass_id=aufmass.id,
            project_id=project_id,
            pos_nr=pd.get('pos_nr', ''),
            kurztext=pd.get('kurztext', ''),
            langtext=pd.get('langtext', ''),
            einheit=pd.get('einheit', 'ST'),
            menge=pd.get('menge', 0),
            faktor=pd.get('faktor', 1),
            laenge=pd.get('laenge', 0),
            breite=pd.get('breite', 0),
            tiefe=pd.get('tiefe', 0),
            einzelpreis=pd.get('einzelpreis', 0),
            bemerkung=pd.get('bemerkung', ''),
            sort_index=pd.get('sort_index', 0),
        )
        db.session.add(pos)
        created += 1

    db.session.commit()

    return f'''<div class="notification is-success">
  <strong>{created} Positionen</strong> ins Aufmaß übernommen.
  <span class="is-pulled-right tag is-light is-info">Seite wird neu geladen...</span>
</div>
<script>
  setTimeout(function() {{
    var m = document.getElementById('modul-modal');
    if (m) m.classList.remove('is-active');
    location.reload();
  }}, 1200);
</script>'''


@custom_modules_bp.route('/api/sort-batch', methods=['POST'])
@login_required
def sort_batch():
    if not _can_manage(current_user):
        return jsonify({'error': 'Keine Berechtigung'}), 403

    data = request.get_json(force=True)
    if not isinstance(data, list):
        return jsonify({'error': 'Erwarte Liste von {id, sort_index}'}), 400

    for item in data:
        module = CustomModule.query.get(item.get('id'))
        if not module:
            continue
        if not _can_manage(current_user, module):
            continue
        module.sort_index = item.get('sort_index', 0)

    db.session.commit()
    return jsonify({'ok': True, 'updated': len(data)})


@custom_modules_bp.route('/<int:module_id>/sort', methods=['POST'])
@login_required
def sort(module_id):
    module = CustomModule.query.get_or_404(module_id)
    if not _can_manage(current_user, module):
        return jsonify({'error': 'Keine Berechtigung'}), 403

    data = request.get_json(force=True)
    sort_index = data.get('sort_index', 0)
    module.sort_index = sort_index
    db.session.commit()
    return jsonify({'ok': True})
