#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from flask import Flask, request, jsonify, session
import mysql.connector
from datetime import datetime
from functools import wraps

from routes_instalari import register_instalari_routes
app = Flask(__name__)
app.secret_key = 'R0mt3l3c0m!'  # Acelasi secret key ca la concedii

# Configurare MySQL - identica cu app_mysql_v2.py
DB_CONFIG = {
    'host': 'localhost',
    'user': 'root',
    'password': 'romtelecom',
    'database': 'evidenta_deconturi'
}

def get_db_connection():
    return mysql.connector.connect(**DB_CONFIG)

# ===== AUTENTIFICARE =====

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

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


# ===== CORS - permite requesturi din browser =====
@app.after_request
def after_request(response):
    response.headers.add('Access-Control-Allow-Origin', '*')
    response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
    response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
    response.headers.add('Access-Control-Allow-Credentials', 'true')
    return response

@app.route('/api/<path:path>', methods=['OPTIONS'])
def options_handler(path):
    return jsonify({}), 200


# ===== AUTENTIFICARE =====

@app.route('/api/login', methods=['POST'])
def login():
    data = request.get_json()
    username = data.get('username', '').strip()
    password = data.get('password', '').strip()

    if not username or not password:
        return jsonify({'error': 'Completeaza username si parola'}), 400

    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)
    cursor.execute("SELECT * FROM employees WHERE username = %s", (username,))
    user = cursor.fetchone()
    cursor.close()
    conn.close()

    if not user:
        return jsonify({'error': 'Username sau parola incorecta'}), 401

    # Verificare parola cu bcrypt (identic cu app_mysql_v2.py)
    try:
        import bcrypt
        password_hash = user['password']
        if isinstance(password_hash, str):
            password_hash = password_hash.encode('utf-8')
        if not bcrypt.checkpw(password.encode('utf-8'), password_hash):
            return jsonify({'error': 'Username sau parola incorecta'}), 401
    except Exception as e:
        print(f"Eroare verificare parola: {e}")
        return jsonify({'error': 'Username sau parola incorecta'}), 401

    session['user_id'] = user['id']
    session['username'] = user['username']
    session['name'] = user['name']
    session['role'] = user.get('role', 'user')

    return jsonify({
        'success': True,
        'user': {
            'id': user['id'],
            'name': user['name'],
            'username': user['username'],
            'role': session['role']
        }
    })


@app.route('/api/logout', methods=['POST'])
def logout():
    session.clear()
    return jsonify({'success': True})


@app.route('/api/angajati-publici', methods=['GET'])
def get_angajati_publici():
    """Endpoint public - doar nume si username, fara autentificare, pentru lista de login"""
    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)
    cursor.execute("SELECT username, name FROM employees ORDER BY name")
    angajati = cursor.fetchall()
    cursor.close()
    conn.close()
    return jsonify(angajati)


@app.route('/api/current-user')
@login_required
def current_user():
    return jsonify({
        'id': session['user_id'],
        'name': session['name'],
        'username': session['username'],
        'role': session['role']
    })


# ===== LUCRARI =====

@app.route('/api/lucrari', methods=['GET'])
@login_required
def get_lucrari():
    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)
    cursor.execute("SELECT * FROM lucrari ORDER BY status ASC, nume ASC")
    lucrari = cursor.fetchall()
    cursor.close()
    conn.close()
    # Serializam datetime
    for l in lucrari:
        if l.get('data_creare'):
            l['data_creare'] = l['data_creare'].isoformat()
        if l.get('data_modificare'):
            l['data_modificare'] = l['data_modificare'].isoformat()
    return jsonify(lucrari)


@app.route('/api/lucrari', methods=['POST'])
@admin_required
def add_lucrare():
    data = request.get_json()
    nume = data.get('nume', '').strip()
    locatie = data.get('locatie', '').strip()
    status = data.get('status', 'activa')

    if not nume:
        return jsonify({'error': 'Denumirea lucrarii este obligatorie'}), 400

    if status not in ('activa', 'finalizata', 'suspendata'):
        status = 'activa'

    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)
    cursor.execute(
        "INSERT INTO lucrari (nume, locatie, status) VALUES (%s, %s, %s)",
        (nume, locatie or None, status)
    )
    conn.commit()
    new_id = cursor.lastrowid
    cursor.execute("SELECT * FROM lucrari WHERE id = %s", (new_id,))
    lucrare = cursor.fetchone()
    cursor.close()
    conn.close()

    lucrare['data_creare'] = lucrare['data_creare'].isoformat()
    lucrare['data_modificare'] = lucrare['data_modificare'].isoformat()
    return jsonify(lucrare), 201


@app.route('/api/lucrari/<int:id>', methods=['PUT'])
@admin_required
def update_lucrare(id):
    data = request.get_json()
    conn = get_db_connection()
    cursor = conn.cursor()
    cursor.execute(
        "UPDATE lucrari SET nume=%s, locatie=%s, status=%s WHERE id=%s",
        (data.get('nume'), data.get('locatie'), data.get('status'), id)
    )
    conn.commit()
    cursor.close()
    conn.close()
    return jsonify({'success': True})


@app.route('/api/lucrari/<int:id>', methods=['DELETE'])
@admin_required
def delete_lucrare(id):
    conn = get_db_connection()
    cursor = conn.cursor()
    # Verifica daca are pontaje asociate
    cursor.execute("SELECT COUNT(*) FROM pontaje WHERE lucrare_id = %s", (id,))
    count = cursor.fetchone()[0]
    if count > 0:
        cursor.close()
        conn.close()
        return jsonify({'error': 'Lucrarea are pontaje asociate si nu poate fi stearsa. Marcheaz-o ca finalizata.'}), 400
    cursor.execute("DELETE FROM lucrari WHERE id = %s", (id,))
    conn.commit()
    cursor.close()
    conn.close()
    return jsonify({'success': True})


# ===== PONTAJE =====

@app.route('/api/pontaje', methods=['GET'])
@login_required
def get_pontaje():
    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)

    role = session.get('role', 'user')
    user_id = session['user_id']

    # Filtre optionale din query string
    lucrare_id = request.args.get('lucrare_id')
    data_start = request.args.get('data_start')
    data_end = request.args.get('data_end')

    sql = """
        SELECT p.*,
               e.name   AS angajat_nume,
               e.username AS angajat_username,
               l.nume   AS lucrare_nume,
               l.locatie AS lucrare_locatie
        FROM pontaje p
        LEFT JOIN employees e ON p.employee_id = e.id
        LEFT JOIN lucrari l   ON p.lucrare_id  = l.id
        WHERE 1=1
    """
    params = []

    # Angajatii normali vad doar pontajele lor
    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))

    if data_start:
        sql += " AND DATE(p.checkin_ora) >= %s"
        params.append(data_start)

    if data_end:
        sql += " AND DATE(p.checkin_ora) <= %s"
        params.append(data_end)

    sql += " ORDER BY p.checkin_ora DESC"

    cursor.execute(sql, params)
    pontaje = cursor.fetchall()
    cursor.close()
    conn.close()

    # Serializam datetime si Decimal
    for p in pontaje:
        for key in ['checkin_ora', 'checkout_ora', 'data_creare']:
            if p.get(key):
                p[key] = p[key].isoformat()
        for key in ['checkin_lat', 'checkin_lng', 'checkout_lat', 'checkout_lng']:
            if p.get(key) is not None:
                p[key] = float(p[key])

    return jsonify(pontaje)


@app.route('/api/pontaje', methods=['POST'])
@login_required
def add_pontaj():
    """Check-In: inceput sesiune de lucru"""
    data = request.get_json()

    lucrare_id = data.get('lucrare_id')
    if not lucrare_id:
        return jsonify({'error': 'Lucrarea este obligatorie'}), 400
    try:
        lucrare_id = int(lucrare_id)
    except (ValueError, TypeError):
        return jsonify({'error': 'lucrare_id invalid'}), 400

    user_id = session['user_id']

    # Verifica sa nu existe deja o sesiune activa pentru acest angajat
    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)
    cursor.execute(
        "SELECT id FROM pontaje WHERE employee_id = %s AND checkout_ora IS NULL",
        (user_id,)
    )
    sesiune_activa = cursor.fetchone()
    if sesiune_activa:
        cursor.close()
        conn.close()
        return jsonify({'error': 'Ai deja o sesiune activa. Efectueaza Check-Out inainte de a incepe alta.'}), 400

    # Locatie GPS
    checkin_lat = data.get('checkin_lat')
    checkin_lng = data.get('checkin_lng')
    checkin_accuracy = data.get('checkin_accuracy')
    obs_start = data.get('obs_start', '').strip() or None

    cursor.execute("""
        INSERT INTO pontaje
            (employee_id, lucrare_id, checkin_ora, checkin_lat, checkin_lng, checkin_accuracy, obs_start)
        VALUES (%s, %s, NOW(), %s, %s, %s, %s)
    """, (user_id, lucrare_id, checkin_lat, checkin_lng, checkin_accuracy, obs_start))
    conn.commit()
    new_id = cursor.lastrowid

    # Returnam pontajul complet
    cursor.execute("""
        SELECT p.*, e.name AS angajat_nume, l.nume AS lucrare_nume
        FROM pontaje p
        LEFT JOIN employees e ON p.employee_id = e.id
        LEFT JOIN lucrari l ON p.lucrare_id = l.id
        WHERE p.id = %s
    """, (new_id,))
    pontaj = cursor.fetchone()
    cursor.close()
    conn.close()

    pontaj['checkin_ora'] = pontaj['checkin_ora'].isoformat()
    pontaj['data_creare'] = pontaj['data_creare'].isoformat()
    for key in ['checkin_lat', 'checkin_lng']:
        if pontaj.get(key) is not None:
            pontaj[key] = float(pontaj[key])

    return jsonify(pontaj), 201


@app.route('/api/pontaje/<int:id>/checkout', methods=['PUT'])
@login_required
def checkout_pontaj(id):
    """Check-Out: sfarsit sesiune de lucru"""
    data = request.get_json()
    user_id = session['user_id']
    role = session.get('role', 'user')

    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)

    # Verifica ca pontajul apartine userului curent (sau admin)
    cursor.execute("SELECT * FROM pontaje WHERE id = %s", (id,))
    pontaj = cursor.fetchone()

    if not pontaj:
        cursor.close()
        conn.close()
        return jsonify({'error': 'Pontaj negasit'}), 404

    if role != 'admin' and pontaj['employee_id'] != user_id:
        cursor.close()
        conn.close()
        return jsonify({'error': 'Nu ai acces la acest pontaj'}), 403

    if pontaj['checkout_ora']:
        cursor.close()
        conn.close()
        return jsonify({'error': 'Check-Out deja inregistrat'}), 400

    checkout_lat = data.get('checkout_lat')
    checkout_lng = data.get('checkout_lng')
    checkout_accuracy = data.get('checkout_accuracy')
    obs_end = data.get('obs_end', '').strip() or None

    # Calculeaza durata in minute
    checkin_ora = pontaj['checkin_ora']
    checkout_ora = datetime.now()
    durata_minute = int((checkout_ora - checkin_ora).total_seconds() / 60)

    cursor.execute("""
        UPDATE pontaje SET
            checkout_ora        = NOW(),
            checkout_lat        = %s,
            checkout_lng        = %s,
            checkout_accuracy   = %s,
            obs_end             = %s,
            durata_minute       = %s
        WHERE id = %s
    """, (checkout_lat, checkout_lng, checkout_accuracy, obs_end, durata_minute, id))
    conn.commit()

    # Returnam pontajul actualizat
    cursor.execute("""
        SELECT p.*, e.name AS angajat_nume, l.nume AS lucrare_nume
        FROM pontaje p
        LEFT JOIN employees e ON p.employee_id = e.id
        LEFT JOIN lucrari l ON p.lucrare_id = l.id
        WHERE p.id = %s
    """, (id,))
    pontaj_updated = cursor.fetchone()
    cursor.close()
    conn.close()

    for key in ['checkin_ora', 'checkout_ora', 'data_creare']:
        if pontaj_updated.get(key):
            pontaj_updated[key] = pontaj_updated[key].isoformat()
    for key in ['checkin_lat', 'checkin_lng', 'checkout_lat', 'checkout_lng']:
        if pontaj_updated.get(key) is not None:
            pontaj_updated[key] = float(pontaj_updated[key])

    return jsonify(pontaj_updated)


@app.route('/api/pontaje/sesiune-activa', methods=['GET'])
@login_required
def get_sesiune_activa():
    """Returneaza sesiunea activa (fara checkout) a angajatului curent"""
    user_id = session['user_id']
    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)
    cursor.execute("""
        SELECT p.*, e.name AS angajat_nume, l.nume AS lucrare_nume
        FROM pontaje p
        LEFT JOIN employees e ON p.employee_id = e.id
        LEFT JOIN lucrari l ON p.lucrare_id = l.id
        WHERE p.employee_id = %s AND p.checkout_ora IS NULL
        ORDER BY p.checkin_ora DESC LIMIT 1
    """, (user_id,))
    pontaj = cursor.fetchone()
    cursor.close()
    conn.close()

    if not pontaj:
        return jsonify(None)

    pontaj['checkin_ora'] = pontaj['checkin_ora'].isoformat()
    pontaj['data_creare'] = pontaj['data_creare'].isoformat()
    for key in ['checkin_lat', 'checkin_lng']:
        if pontaj.get(key) is not None:
            pontaj[key] = float(pontaj[key])

    return jsonify(pontaj)


# ===== COMENTARII =====

@app.route('/api/comentarii', methods=['GET'])
@login_required
def get_comentarii():
    pontaj_id = request.args.get('pontaj_id')
    if not pontaj_id:
        return jsonify({'error': 'pontaj_id este obligatoriu'}), 400

    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)
    cursor.execute("""
        SELECT c.*, e.name AS angajat_nume
        FROM pontaje_comentarii c
        LEFT JOIN employees e ON c.employee_id = e.id
        WHERE c.pontaj_id = %s
        ORDER BY c.ora ASC
    """, (int(pontaj_id),))
    comentarii = cursor.fetchall()
    cursor.close()
    conn.close()

    for c in comentarii:
        if c.get('ora'):
            c['ora'] = c['ora'].isoformat()
        for key in ['locatie_lat', 'locatie_lng']:
            if c.get(key) is not None:
                c[key] = float(c[key])

    return jsonify(comentarii)


@app.route('/api/comentarii', methods=['POST'])
@login_required
def add_comentariu():
    data = request.get_json()

    pontaj_id = data.get('pontaj_id')
    text = data.get('text', '').strip()

    if not pontaj_id or not text:
        return jsonify({'error': 'pontaj_id si text sunt obligatorii'}), 400

    user_id = session['user_id']
    role = session.get('role', 'user')

    # Verifica ca pontajul apartine userului curent (sau admin)
    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)
    cursor.execute("SELECT employee_id, checkout_ora FROM pontaje WHERE id = %s", (pontaj_id,))
    pontaj = cursor.fetchone()

    if not pontaj:
        cursor.close()
        conn.close()
        return jsonify({'error': 'Pontaj negasit'}), 404

    if role != 'admin' and pontaj['employee_id'] != user_id:
        cursor.close()
        conn.close()
        return jsonify({'error': 'Nu ai acces la acest pontaj'}), 403

    tip = data.get('tip', 'alt_motiv')
    valid_tipuri = ('front_lucru', 'materiale', 'utilaje', 'conditii', 'alt_motiv')
    if tip not in valid_tipuri:
        tip = 'alt_motiv'

    locatie_lat = data.get('locatie_lat')
    locatie_lng = data.get('locatie_lng')
    locatie_accuracy = data.get('locatie_accuracy')

    cursor.execute("""
        INSERT INTO pontaje_comentarii
            (pontaj_id, employee_id, tip, text, locatie_lat, locatie_lng, locatie_accuracy)
        VALUES (%s, %s, %s, %s, %s, %s, %s)
    """, (pontaj_id, user_id, tip, text, locatie_lat, locatie_lng, locatie_accuracy))
    conn.commit()
    new_id = cursor.lastrowid

    cursor.execute("""
        SELECT c.*, e.name AS angajat_nume
        FROM pontaje_comentarii c
        LEFT JOIN employees e ON c.employee_id = e.id
        WHERE c.id = %s
    """, (new_id,))
    comentariu = cursor.fetchone()
    cursor.close()
    conn.close()

    comentariu['ora'] = comentariu['ora'].isoformat()
    for key in ['locatie_lat', 'locatie_lng']:
        if comentariu.get(key) is not None:
            comentariu[key] = float(comentariu[key])

    return jsonify(comentariu), 201


# ===== ANGAJATI (doar admin) =====

@app.route('/api/angajati', methods=['GET'])
@login_required
def get_angajati():
    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)
    cursor.execute("SELECT id, name, username, role FROM employees ORDER BY name")
    angajati = cursor.fetchall()
    cursor.close()
    conn.close()
    return jsonify(angajati)


@app.route('/api/angajati', methods=['POST'])
@admin_required
def add_angajat():
    import bcrypt
    data = request.get_json()
    name = data.get('name', '').strip()
    username = data.get('username', '').strip()
    password = data.get('password', '').strip()
    role = data.get('role', 'user')

    if not name or not username or not password:
        return jsonify({'error': 'Nume, username si parola sunt obligatorii'}), 400

    password_hash = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')

    conn = get_db_connection()
    cursor = conn.cursor()
    try:
        cursor.execute(
            "INSERT INTO employees (name, username, password, role) VALUES (%s, %s, %s, %s)",
            (name, username, password_hash, role)
        )
        conn.commit()
        new_id = cursor.lastrowid
    except mysql.connector.IntegrityError:
        cursor.close()
        conn.close()
        return jsonify({'error': 'Username-ul exista deja'}), 400
    cursor.close()
    conn.close()
    return jsonify({'id': new_id, 'name': name, 'username': username, 'role': role}), 201


@app.route('/api/angajati/<int:id>', methods=['DELETE'])
@admin_required
def delete_angajat(id):
    if id == session['user_id']:
        return jsonify({'error': 'Nu te poti sterge pe tine insuti'}), 400
    conn = get_db_connection()
    cursor = conn.cursor()
    cursor.execute("DELETE FROM employees WHERE id = %s", (id,))
    conn.commit()
    cursor.close()
    conn.close()
    return jsonify({'success': True})


# ===== STATISTICI ADMIN =====

@app.route('/api/statistici', methods=['GET'])
@admin_required
def get_statistici():
    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)

    cursor.execute("SELECT COUNT(*) AS total FROM employees")
    total_angajati = cursor.fetchone()['total']

    cursor.execute("SELECT COUNT(*) AS total FROM lucrari WHERE status = 'activa'")
    lucrari_active = cursor.fetchone()['total']

    cursor.execute("SELECT COUNT(*) AS total FROM pontaje")
    total_pontaje = cursor.fetchone()['total']

    cursor.execute("SELECT COUNT(*) AS total FROM pontaje WHERE checkout_ora IS NULL")
    sesiuni_active = cursor.fetchone()['total']

    cursor.execute("SELECT COUNT(*) AS total FROM pontaje_comentarii")
    total_comentarii = cursor.fetchone()['total']

    cursor.close()
    conn.close()

    return jsonify({
        'total_angajati': total_angajati,
        'lucrari_active': lucrari_active,
        'total_pontaje': total_pontaje,
        'sesiuni_active': sesiuni_active,
        'total_comentarii': total_comentarii
    })


# ===== SERVIRE FISIER HTML =====

@app.route('/')
@app.route('/pontaj')
@app.route('/pontaj/')
def serve_pontaj():
    """Serveste fisierul HTML al aplicatiei de pontaj"""
    from flask import send_from_directory
    import os
    base_dir = os.path.dirname(os.path.abspath(__file__))
    return send_from_directory(base_dir, 'pontaj.html')


if __name__ == '__main__':
    register_instalari_routes(app, get_db_connection)
    app.run(host='0.0.0.0', port=5001, debug=False)