# -*- coding: utf-8 -*-
"""
Modul Instalari v3 - routes Flask
Integrat cu pontaj: sesiune comuna, fara login separat.

Adauga in app_pontaj.py:
    from routes_instalari import register_instalari_routes
    register_instalari_routes(app, get_db_connection)
"""

import os, time, random, string
from datetime import date
from flask import request, jsonify, session, Response
from functools import wraps

UPLOAD_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'uploads_instalari')
ALLOWED_EXT = {'jpg', 'jpeg', 'png', 'webp', 'heic'}

def _rnd(n=8):
    return ''.join(random.choices('abcdef0123456789', k=n))

def _serial(row):
    if not row:
        return row
    import decimal
    from datetime import datetime, date as date_type
    out = {}
    for k, v in row.items():
        if isinstance(v, datetime):
            out[k] = v.isoformat()
        elif isinstance(v, date_type):
            out[k] = v.isoformat()
        elif isinstance(v, decimal.Decimal):
            out[k] = float(v)
        else:
            out[k] = v
    return out


def register_instalari_routes(app, get_db):

    os.makedirs(UPLOAD_DIR, exist_ok=True)

    def login_required(f):
        @wraps(f)
        def decorated(*args, **kwargs):
            if 'user_id' not in session:
                return jsonify({'error': 'Neautentificat'}), 401
            return f(*args, **kwargs)
        return decorated

    def admin_required(f):
        @wraps(f)
        def decorated(*args, **kwargs):
            if 'user_id' not in session:
                return jsonify({'error': 'Neautentificat'}), 401
            if session.get('role') != 'admin':
                return jsonify({'error': 'Acces interzis'}), 403
            return f(*args, **kwargs)
        return decorated

    # ── SERVE HTML ─────────────────────────────────────────────────────────────
    @app.route('/instalari')
    @app.route('/instalari/')
    def serve_instalari():
        base = os.path.dirname(os.path.abspath(__file__))
        with open(os.path.join(base, 'instalari.html'), 'r', encoding='utf-8') as f:
            content = f.read()
        return Response(content, mimetype='text/html')

    # ── SESIUNE CURENTA ────────────────────────────────────────────────────────
    @app.route('/api/inst/me')
    def inst_me():
        if 'user_id' not in session:
            return jsonify(None)
        return jsonify({
            'id':       session['user_id'],
            'name':     session.get('name', ''),
            'username': session.get('username', ''),
            'role':     session.get('role', 'user'),
        })

    # ── LUCRARI LA CARE A PONTAT ANGAJATUL ────────────────────────────────────
    @app.route('/api/inst/lucrari-mele')
    @login_required
    def inst_lucrari_mele():
        """
        Returneaza lucrari la care angajatul curent a pontat,
        optionala filtrare pe data (implicit azi).
        Admin vede toate lucrari active.
        """
        user_id = session['user_id']
        role    = session.get('role', 'user')
        data    = request.args.get('data') or date.today().isoformat()

        conn = get_db()
        cur  = conn.cursor(dictionary=True)

        if role == 'admin':
            cur.execute("""
                SELECT id, nume, locatie, status
                FROM lucrari
                WHERE status = 'activa'
                ORDER BY nume
            """)
        else:
            cur.execute("""
                SELECT DISTINCT l.id, l.nume, l.locatie, l.status
                FROM lucrari l
                JOIN pontaje p ON p.lucrare_id = l.id
                WHERE p.employee_id = %s
                  AND DATE(p.checkin_ora) = %s
                ORDER BY l.nume
            """, (user_id, data))

        rows = cur.fetchall()
        cur.close(); conn.close()
        return jsonify(rows)

    # ── PONTAJE ZI (info afisare) ──────────────────────────────────────────────
    @app.route('/api/inst/pontaje-zi')
    @login_required
    def inst_pontaje_zi():
        user_id    = session['user_id']
        role       = session.get('role', 'user')
        data       = request.args.get('data') or date.today().isoformat()
        lucrare_id = request.args.get('lucrare_id')

        conn = get_db()
        cur  = conn.cursor(dictionary=True)
        sql = """
            SELECT p.id, p.checkin_ora, p.checkout_ora, p.durata_minute,
                   e.name AS angajat_nume, l.nume AS lucrare_nume
            FROM pontaje p
            JOIN employees e ON e.id = p.employee_id
            JOIN lucrari   l ON l.id = p.lucrare_id
            WHERE DATE(p.checkin_ora) = %s
        """
        params = [data]
        if role != 'admin':
            sql += " AND p.employee_id = %s"
            params.append(user_id)
        if lucrare_id:
            sql += " AND p.lucrare_id = %s"
            params.append(int(lucrare_id))
        sql += " ORDER BY p.checkin_ora"
        cur.execute(sql, params)
        rows = [_serial(r) for r in cur.fetchall()]
        cur.close(); conn.close()
        return jsonify(rows)

    # ── ARTICOLE ───────────────────────────────────────────────────────────────
    @app.route('/api/inst/articole', methods=['GET'])
    @login_required
    def inst_get_articole():
        conn = get_db()
        cur  = conn.cursor(dictionary=True)
        cur.execute("SELECT * FROM inst_articole WHERE activ=1 ORDER BY tip, ordine, denumire")
        rows = [_serial(r) for r in cur.fetchall()]
        cur.close(); conn.close()
        return jsonify(rows)

    @app.route('/api/inst/articole', methods=['POST'])
    @admin_required
    def inst_add_articol():
        d = request.get_json()
        denumire = (d.get('denumire') or '').strip()
        if not denumire:
            return jsonify({'error': 'Denumirea este obligatorie'}), 400
        tip    = d.get('tip', 'manopera')
        um     = (d.get('um') or 'buc').strip()
        pret   = d.get('pret_unitar') or None
        ordine = int(d.get('ordine') or 0)
        conn = get_db(); cur = conn.cursor(dictionary=True)
        cur.execute("INSERT INTO inst_articole (tip,denumire,um,pret_unitar,ordine) VALUES (%s,%s,%s,%s,%s)",
                    (tip, denumire, um, pret, ordine))
        conn.commit()
        cur.execute("SELECT * FROM inst_articole WHERE id=%s", (cur.lastrowid,))
        row = _serial(cur.fetchone())
        cur.close(); conn.close()
        return jsonify(row), 201

    @app.route('/api/inst/articole/<int:aid>', methods=['PUT'])
    @admin_required
    def inst_update_articol(aid):
        d = request.get_json()
        denumire = (d.get('denumire') or '').strip()
        if not denumire:
            return jsonify({'error': 'Denumirea este obligatorie'}), 400
        conn = get_db(); cur = conn.cursor(dictionary=True)
        # istoric pret
        cur.execute("SELECT pret_unitar FROM inst_articole WHERE id=%s", (aid,))
        ex = cur.fetchone()
        pret_nou = d.get('pret_unitar') or None
        pret_nou_f = float(pret_nou) if pret_nou is not None else None
        if ex:
            pret_vechi = float(ex['pret_unitar']) if ex['pret_unitar'] is not None else None
            if pret_vechi != pret_nou_f:
                cur.execute("SELECT name FROM employees WHERE id=%s", (session['user_id'],))
                emp = cur.fetchone()
                cur.execute("""INSERT INTO inst_preturi_istoric
                    (articol_id,pret_vechi,pret_nou,modificat_de,modificat_de_nume)
                    VALUES (%s,%s,%s,%s,%s)""",
                    (aid, pret_vechi, pret_nou_f, session['user_id'], emp['name'] if emp else ''))
        cur.execute("UPDATE inst_articole SET tip=%s,denumire=%s,um=%s,pret_unitar=%s,ordine=%s WHERE id=%s",
                    (d.get('tip','manopera'), denumire, (d.get('um') or 'buc').strip(),
                     pret_nou, int(d.get('ordine') or 0), aid))
        conn.commit(); cur.close(); conn.close()
        return jsonify({'success': True})

    @app.route('/api/inst/articole/<int:aid>', methods=['DELETE'])
    @admin_required
    def inst_delete_articol(aid):
        conn = get_db(); cur = conn.cursor()
        cur.execute("UPDATE inst_articole SET activ=0 WHERE id=%s", (aid,))
        conn.commit(); cur.close(); conn.close()
        return jsonify({'success': True})

    @app.route('/api/inst/articole/<int:aid>/preturi-istoric')
    @admin_required
    def inst_preturi_istoric(aid):
        conn = get_db(); cur = conn.cursor(dictionary=True)
        cur.execute("SELECT * FROM inst_preturi_istoric WHERE articol_id=%s ORDER BY modificat_la DESC LIMIT 30", (aid,))
        rows = [_serial(r) for r in cur.fetchall()]
        cur.close(); conn.close()
        return jsonify(rows)

    # ── RAPOARTE ───────────────────────────────────────────────────────────────
    @app.route('/api/inst/rapoarte', methods=['GET'])
    @login_required
    def inst_get_rapoarte():
        user_id     = session['user_id']
        role        = session.get('role', 'user')
        lucrare_id  = request.args.get('lucrare_id')
        employee_id = request.args.get('employee_id')
        data_start  = request.args.get('data_start')
        data_end    = request.args.get('data_end')

        conn = get_db(); cur = conn.cursor(dictionary=True)
        sql = """
            SELECT r.*, e.name AS angajat_nume, l.nume AS lucrare_nume,
                   COALESCE(SUM(ra.cantitate * ra.pret_unitar_snapshot),0) AS valoare_totala,
                   COUNT(DISTINCT CASE WHEN ra.cantitate>0 THEN ra.id END) AS nr_articole
            FROM inst_rapoarte r
            LEFT JOIN employees e ON e.id = r.employee_id
            LEFT JOIN lucrari   l ON l.id = r.lucrare_id
            LEFT JOIN inst_raport_articole ra ON ra.raport_id = r.id
            WHERE 1=1
        """
        params = []
        if role != 'admin':
            sql += " AND r.employee_id=%s"; params.append(user_id)
        if lucrare_id:
            sql += " AND r.lucrare_id=%s"; params.append(int(lucrare_id))
        if employee_id and role == 'admin':
            sql += " AND r.employee_id=%s"; params.append(int(employee_id))
        if data_start:
            sql += " AND r.data_lucru>=%s"; params.append(data_start)
        if data_end:
            sql += " AND r.data_lucru<=%s"; params.append(data_end)
        sql += " GROUP BY r.id ORDER BY r.data_lucru ASC, r.creat_la ASC"
        cur.execute(sql, params)
        rows = [_serial(r) for r in cur.fetchall()]
        cur.close(); conn.close()
        return jsonify(rows)

    @app.route('/api/inst/rapoarte/<int:rid>', methods=['GET'])
    @login_required
    def inst_get_raport(rid):
        user_id = session['user_id']; role = session.get('role','user')
        conn = get_db(); cur = conn.cursor(dictionary=True)
        cur.execute("""SELECT r.*, e.name AS angajat_nume, l.nume AS lucrare_nume
            FROM inst_rapoarte r
            LEFT JOIN employees e ON e.id=r.employee_id
            LEFT JOIN lucrari   l ON l.id=r.lucrare_id
            WHERE r.id=%s""", (rid,))
        r = cur.fetchone()
        if not r: cur.close(); conn.close(); return jsonify({'error':'Negasit'}), 404
        if role != 'admin' and r['employee_id'] != user_id:
            cur.close(); conn.close(); return jsonify({'error':'Acces interzis'}), 403
        r = _serial(r)
        cur.execute("""SELECT ra.*, a.denumire, a.um, a.tip, a.ordine
            FROM inst_raport_articole ra JOIN inst_articole a ON a.id=ra.articol_id
            WHERE ra.raport_id=%s ORDER BY a.tip, a.ordine""", (rid,))
        r['articole'] = [_serial(x) for x in cur.fetchall()]
        cur.execute("SELECT * FROM inst_raport_poze WHERE raport_id=%s ORDER BY creat_la", (rid,))
        r['poze'] = [_serial(x) for x in cur.fetchall()]
        cur.close(); conn.close()
        return jsonify(r)

    @app.route('/api/inst/rapoarte', methods=['POST'])
    @login_required
    def inst_save_raport():
        d = request.get_json()
        user_id    = session['user_id']
        role       = session.get('role','user')
        lucrare_id = int(d.get('lucrare_id', 0))
        emp_id     = int(d.get('employee_id') or user_id) if role == 'admin' else user_id
        data_lucru = d.get('data_lucru') or date.today().isoformat()
        observatii = (d.get('observatii') or '').strip()
        articole   = d.get('articole', [])
        if not lucrare_id:
            return jsonify({'error': 'Lucrarea este obligatorie'}), 400

        conn = get_db(); cur = conn.cursor(dictionary=True)
        cur.execute("SELECT id FROM inst_rapoarte WHERE lucrare_id=%s AND employee_id=%s AND data_lucru=%s",
                    (lucrare_id, emp_id, data_lucru))
        ex = cur.fetchone()
        if ex:
            rid = ex['id']
            cur.execute("UPDATE inst_rapoarte SET observatii=%s, modificat_la=NOW() WHERE id=%s", (observatii, rid))
            cur.execute("DELETE FROM inst_raport_articole WHERE raport_id=%s", (rid,))
        else:
            cur.execute("INSERT INTO inst_rapoarte (lucrare_id,employee_id,data_lucru,observatii) VALUES (%s,%s,%s,%s)",
                        (lucrare_id, emp_id, data_lucru, observatii))
            rid = cur.lastrowid

        for art in articole:
            cant = float(art.get('cantitate') or 0)
            if cant > 0:
                pret = art.get('pret_unitar_snapshot') or art.get('pret_unitar') or None
                pret = float(pret) if pret is not None else None
                cur.execute("INSERT INTO inst_raport_articole (raport_id,articol_id,cantitate,pret_unitar_snapshot) VALUES (%s,%s,%s,%s)",
                            (rid, int(art['articol_id']), cant, pret))
        conn.commit(); cur.close(); conn.close()
        return jsonify({'success': True, 'id': rid})

    @app.route('/api/inst/rapoarte/<int:rid>', methods=['DELETE'])
    @login_required
    def inst_delete_raport(rid):
        user_id = session['user_id']; role = session.get('role','user')
        conn = get_db(); cur = conn.cursor(dictionary=True)
        cur.execute("SELECT employee_id FROM inst_rapoarte WHERE id=%s", (rid,))
        row = cur.fetchone()
        if not row: cur.close(); conn.close(); return jsonify({'error':'Negasit'}), 404
        if role != 'admin' and row['employee_id'] != user_id:
            cur.close(); conn.close(); return jsonify({'error':'Acces interzis'}), 403
        cur.execute("SELECT filename FROM inst_raport_poze WHERE raport_id=%s", (rid,))
        for p in cur.fetchall():
            fp = os.path.join(UPLOAD_DIR, p['filename'])
            if os.path.exists(fp): os.unlink(fp)
        cur.execute("DELETE FROM inst_rapoarte WHERE id=%s", (rid,))
        conn.commit(); cur.close(); conn.close()
        return jsonify({'success': True})

    # ── SUMAR ──────────────────────────────────────────────────────────────────
    @app.route('/api/inst/sumar')
    @login_required
    def inst_sumar():
        lucrare_id  = request.args.get('lucrare_id')
        employee_id = request.args.get('employee_id')
        data_start  = request.args.get('data_start')
        data_end    = request.args.get('data_end')
        user_id = session['user_id']; role = session.get('role','user')
        if not lucrare_id:
            return jsonify({'error': 'lucrare_id obligatoriu'}), 400

        conn = get_db(); cur = conn.cursor(dictionary=True)
        cond = "AND r.lucrare_id=%s"; params = [int(lucrare_id)]
        if role != 'admin':
            cond += " AND r.employee_id=%s"; params.append(user_id)
        elif employee_id:
            cond += " AND r.employee_id=%s"; params.append(int(employee_id))
        if data_start:
            cond += " AND r.data_lucru>=%s"; params.append(data_start)
        if data_end:
            cond += " AND r.data_lucru<=%s"; params.append(data_end)

        cur.execute(f"""
            SELECT a.id, a.denumire, a.um, a.tip, a.pret_unitar,
                   COALESCE(SUM(ra.cantitate),0) AS cantitate_totala,
                   COALESCE(SUM(ra.cantitate*ra.pret_unitar_snapshot),0) AS valoare_totala
            FROM inst_articole a
            LEFT JOIN inst_raport_articole ra ON ra.articol_id=a.id
            LEFT JOIN inst_rapoarte r ON r.id=ra.raport_id {cond}
            GROUP BY a.id HAVING cantitate_totala>0 ORDER BY a.tip, a.ordine
        """, params)
        articole = [_serial(r) for r in cur.fetchall()]

        cur.execute(f"SELECT COUNT(*) AS zile, MIN(data_lucru) AS prima_zi, MAX(data_lucru) AS ultima_zi FROM inst_rapoarte r WHERE 1=1 {cond}", params)
        meta = _serial(cur.fetchone())

        angajati = []
        if role == 'admin':
            cur.execute("""
                SELECT e.id, e.name,
                       COUNT(DISTINCT r.data_lucru) AS zile,
                       COALESCE(SUM(ra.cantitate*ra.pret_unitar_snapshot),0) AS valoare
                FROM inst_rapoarte r
                LEFT JOIN employees e ON e.id=r.employee_id
                LEFT JOIN inst_raport_articole ra ON ra.raport_id=r.id
                WHERE r.lucrare_id=%s GROUP BY e.id ORDER BY e.name
            """, (int(lucrare_id),))
            angajati = [_serial(r) for r in cur.fetchall()]

        cur.close(); conn.close()
        return jsonify({'articole': articole, 'meta': meta, 'angajati': angajati})

    # ── POZE ───────────────────────────────────────────────────────────────────
    @app.route('/api/inst/rapoarte/<int:rid>/poze', methods=['POST'])
    @login_required
    def inst_upload_poza(rid):
        user_id = session['user_id']; role = session.get('role','user')
        conn = get_db(); cur = conn.cursor(dictionary=True)
        cur.execute("SELECT employee_id FROM inst_rapoarte WHERE id=%s", (rid,))
        row = cur.fetchone()
        if not row or (role != 'admin' and row['employee_id'] != user_id):
            cur.close(); conn.close(); return jsonify({'error':'Acces interzis'}), 403
        if 'poza' not in request.files:
            cur.close(); conn.close(); return jsonify({'error':'Fisier lipsa'}), 400
        f = request.files['poza']
        ext = f.filename.rsplit('.',1)[-1].lower() if '.' in f.filename else ''
        if ext not in ALLOWED_EXT:
            cur.close(); conn.close(); return jsonify({'error':'Format nepermis'}), 400
        fname = f"r{rid}_{int(time.time())}_{_rnd()}.{ext}"
        f.save(os.path.join(UPLOAD_DIR, fname))
        desc = (request.form.get('descriere') or '').strip()
        cur.execute("INSERT INTO inst_raport_poze (raport_id,filename,descriere) VALUES (%s,%s,%s)", (rid, fname, desc))
        conn.commit(); new_id = cur.lastrowid
        cur.close(); conn.close()
        return jsonify({'success': True, 'id': new_id, 'filename': fname})

    @app.route('/api/inst/poze/<int:pid>', methods=['DELETE'])
    @login_required
    def inst_delete_poza(pid):
        user_id = session['user_id']; role = session.get('role','user')
        conn = get_db(); cur = conn.cursor(dictionary=True)
        cur.execute("""SELECT p.filename, r.employee_id FROM inst_raport_poze p
            JOIN inst_rapoarte r ON r.id=p.raport_id WHERE p.id=%s""", (pid,))
        row = cur.fetchone()
        if not row or (role != 'admin' and row['employee_id'] != user_id):
            cur.close(); conn.close(); return jsonify({'error':'Acces interzis'}), 403
        fp = os.path.join(UPLOAD_DIR, row['filename'])
        if os.path.exists(fp): os.unlink(fp)
        cur.execute("DELETE FROM inst_raport_poze WHERE id=%s", (pid,))
        conn.commit(); cur.close(); conn.close()
        return jsonify({'success': True})

    @app.route('/uploads_instalari/<path:filename>')
    def inst_serve_upload(filename):
        from flask import send_from_directory
        return send_from_directory(UPLOAD_DIR, filename)

