import os, sys, argparse
from functools import wraps
from flask import Flask, request, session, redirect, url_for, render_template, flash, send_file, abort, jsonify
from database import get_db, hash_password, init_db
from questions import QUESTIONS, CATEGORIES, ORG_FIELDS, AMBITION_FIELDS, SCORE_LABELS
from report_generator import generate_report

bp = os.environ.get('BASE_PATH', '')

app = Flask(__name__, static_url_path=(bp + '/static') if bp else '/static')
app.secret_key = os.environ.get('FLASK_SECRET_KEY', 'groots-mt-scan-secret-2026')

def bp_url(endpoint, **values):
    return url_for(endpoint, **values)

app.jinja_env.globals['bp'] = bp
app.jinja_env.globals['bp_url'] = bp_url

def login_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        if 'user_id' not in session:
            return redirect(bp_url('admin_login'))
        return f(*args, **kwargs)
    return decorated

@app.route(bp + '/admin/login', methods=['GET', 'POST'])
def admin_login():
    error = None
    if request.method == 'POST':
        username = request.form.get('username', '').strip()
        password = request.form.get('password', '')
        conn = get_db()
        user = conn.execute("SELECT * FROM users WHERE username=?", (username,)).fetchone()
        conn.close()
        if user and user['password_hash'] == hash_password(password):
            session['user_id'] = user['id']
            session['user_name'] = user['name']
            return redirect(bp_url('admin_dashboard'))
        error = "Ongeldige inloggegevens"
    return render_template('admin/login.html', error=error)

@app.route(bp + '/admin/logout')
def admin_logout():
    session.clear()
    return redirect(bp_url('admin_login'))

@app.route(bp + '/admin/')
@login_required
def admin_dashboard():
    conn = get_db()
    scans = conn.execute("SELECT s.*, (SELECT COUNT(*) FROM scan_responses WHERE scan_id=s.id AND part=2) as response_count FROM scans s ORDER BY s.created_date DESC").fetchall()
    total = len(scans)
    completed = sum(1 for s in scans if s['status'] == 'completed')
    reports = conn.execute("SELECT COUNT(*) as c FROM reports WHERE status='generated'").fetchone()['c']

    # Calculate average score across all scans
    all_scores = conn.execute("SELECT score FROM scan_responses WHERE part=2").fetchall()
    avg_score = round(sum(r['score'] for r in all_scores) / len(all_scores), 1) if all_scores else 0

    # Category averages across all scans
    cat_avgs = {}
    for cat in CATEGORIES:
        cs = conn.execute("SELECT score FROM scan_responses WHERE category=? AND part=2", (cat,)).fetchall()
        cat_avgs[cat] = round(sum(r['score'] for r in cs) / len(cs), 1) if cs else 0

    conn.close()
    return render_template('admin/dashboard.html', scans=scans, total=total, completed=completed,
        reports=reports, avg_score=avg_score, cat_avgs=cat_avgs, categories=CATEGORIES)

@app.route(bp + '/admin/scan/<int:scan_id>', methods=['GET', 'POST'])
@login_required
def admin_scan_detail(scan_id):
    conn = get_db()
    scan = conn.execute("SELECT * FROM scans WHERE id=?", (scan_id,)).fetchone()
    if not scan:
        conn.close()
        abort(404)
    responses = conn.execute("SELECT * FROM scan_responses WHERE scan_id=? ORDER BY question_id", (scan_id,)).fetchall()
    expert = conn.execute("SELECT * FROM expert_inputs WHERE scan_id=? ORDER BY created_date DESC LIMIT 1", (scan_id,)).fetchone()

    # Category scores (only part 2)
    cat_scores = {}
    for cat in CATEGORIES:
        cs = [r['score'] for r in responses if r['category'] == cat and r['part'] == 2]
        cat_scores[cat] = round(sum(cs)/len(cs), 1) if cs else 0

    # Group responses by category
    cat_responses = {}
    for cat in CATEGORIES:
        cat_responses[cat] = [r for r in responses if r['category'] == cat and r['part'] == 2]

    conn.close()

    if request.method == 'POST':
        author = session.get('user_name', 'Admin')
        observation = request.form.get('observation', '')
        context = request.form.get('context', '')
        recommendations = request.form.get('recommendations', '')
        conn = get_db()
        conn.execute("INSERT INTO expert_inputs (scan_id, author, observation, context, recommendations) VALUES (?,?,?,?,?)",
            (scan_id, author, observation, context, recommendations))
        conn.execute("UPDATE scans SET status='reviewed', notes=? WHERE id=?",
            (request.form.get('notes', scan['notes']), scan_id))
        conn.commit()
        conn.close()
        flash("Expert input opgeslagen")
        return redirect(bp_url('admin_scan_detail', scan_id=scan_id))

    return render_template('admin/scan_detail.html', scan=scan, responses=responses,
        expert=expert, cat_scores=cat_scores, cat_responses=cat_responses,
        categories=CATEGORIES, score_labels=SCORE_LABELS)

@app.route(bp + '/admin/scan/<int:scan_id>/generate', methods=['POST'])
@login_required
def admin_generate_report(scan_id):
    filepath = generate_report(scan_id)
    if filepath:
        flash("Rapport gegenereerd")
    else:
        flash("Fout bij genereren rapport", "error")
    return redirect(bp_url('admin_scan_detail', scan_id=scan_id))

@app.route(bp + '/admin/reports/')
@login_required
def admin_reports():
    conn = get_db()
    reports = conn.execute("""SELECT r.*, s.company_name, s.contact_name FROM reports r JOIN scans s ON r.scan_id=s.id ORDER BY r.created_date DESC""").fetchall()
    conn.close()
    return render_template('admin/reports.html', reports=reports)

@app.route(bp + '/admin/reports/<int:report_id>')
@login_required
def admin_report_detail(report_id):
    conn = get_db()
    report = conn.execute("""SELECT r.*, s.company_name, s.contact_name, s.contact_email FROM reports r JOIN scans s ON r.scan_id=s.id WHERE r.id=?""", (report_id,)).fetchone()
    conn.close()
    if not report:
        abort(404)
    return render_template('admin/report_detail.html', report=report)

@app.route(bp + '/api/report/<int:report_id>/pdf')
def api_report_download(report_id):
    conn = get_db()
    report = conn.execute("SELECT * FROM reports WHERE id=?", (report_id,)).fetchone()
    conn.close()
    if not report or not report['pdf_path'] or not os.path.exists(report['pdf_path']):
        abort(404)
    return send_file(report['pdf_path'], as_attachment=True)

@app.route(bp + '/scan/', methods=['GET', 'POST'])
def scan_index():
    if request.method == 'POST':
        # Part 1: Org context
        org_name = request.form.get('org_name', '').strip()
        org_sector = request.form.get('org_sector', '').strip()
        org_size = request.form.get('org_size', '').strip()
        mt_size = request.form.get('mt_size', '').strip()

        if not org_name or not org_sector or not org_size or not mt_size:
            flash("Vul alle verplichte velden in", "error")
            return redirect(bp_url('scan_index'))

        conn = get_db()
        cur = conn.execute("""INSERT INTO scans (company_name, org_sector, org_size, mt_size, mt_composition,
            strategy_priorities, challenges, scan_reason,
            ambition_changes, ambition_opportunities, ambition_support, remarks, status)
            VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)""",
            (org_name, org_sector, org_size, mt_size,
             request.form.get('mt_composition', '').strip(),
             request.form.get('strategy_priorities', '').strip(),
             request.form.get('challenges', '').strip(),
             request.form.get('scan_reason', '').strip(),
             request.form.get('ambition_changes', '').strip(),
             request.form.get('ambition_opportunities', '').strip(),
             request.form.get('ambition_support', '').strip(),
             request.form.get('remarks', '').strip(),
             'completed'))
        scan_id = cur.lastrowid

        # Part 2: Team scan questions
        for q in QUESTIONS:
            score = int(request.form.get(f'q_{q["id"]}', 3))
            comment = request.form.get(f'c_{q["id"]}', '').strip()
            conn.execute("INSERT INTO scan_responses (scan_id, question_id, category, question_text, score, comment, part, context) VALUES (?,?,?,?,?,?,?,?)",
                (scan_id, q['id'], q['category'], q['text'], score, comment, q['part'], q['context']))

        conn.commit()
        conn.close()
        return render_template('scan/thankyou.html', company=org_name)

    return render_template('scan/index.html', questions=QUESTIONS, categories=CATEGORIES,
        org_fields=ORG_FIELDS, ambition_fields=AMBITION_FIELDS, score_labels=SCORE_LABELS)

if __name__ == '__main__':
    init_db()
    parser = argparse.ArgumentParser()
    parser.add_argument('--port', type=int, default=5053)
    parser.add_argument('--host', type=str, default='0.0.0.0')
    args = parser.parse_args()
    app.run(host=args.host, port=args.port, debug=False)
