import os
from flask import Flask, render_template, request, redirect, url_for, session
import sqlite3

app = Flask(__name__)
app.secret_key = 'secret123'
# Mengunci lokasi folder utama aplikasi Anda
BASE_DIR = os.path.abspath(os.path.dirname(__file__))

# Menunjuk langsung ke file database lama Anda di folder tersebut
# (Ganti 'database.db' sesuai nama file asli Anda jika berbeda)
DATABASE_PATH = os.path.join(BASE_DIR, 'database.db')
def get_db_connection():
    conn = sqlite3.connect(DATABASE_PATH)
    conn.row_factory = sqlite3.Row
    return conn

# fungsi koneksi database
def get_db_connection():
    conn = sqlite3.connect('users.db')
    conn.row_factory = sqlite3.Row
    
    # 1. OTOMATIS MEMBUAT TABEL USERS (Jika belum ada)
    conn.execute('''
        CREATE TABLE IF NOT EXISTS users (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            nama TEXT NOT NULL,
            username TEXT NOT NULL UNIQUE,
            password TEXT NOT NULL,
            role TEXT NOT NULL DEFAULT 'user'
        )
    ''')
    
    # 2. OTOMATIS MEMBUAT TABEL ABSENSI (Jika belum ada)
    conn.execute('''
        CREATE TABLE IF NOT EXISTS absensi (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            nama_user TEXT NOT NULL,
            kode_qr TEXT NOT NULL,
            waktu TEXT NOT NULL
        )
    ''')
    conn.commit()
    return conn

@app.route('/')
def home():
    return render_template('login.html')

@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        nama = request.form['nama']
        username = request.form['username']
        password = request.form['password']

        conn = get_db_connection()
        conn.execute(
            "INSERT INTO users (nama, username, password, role) VALUES (?, ?, ?, ?)",
            (nama, username, password, "user")
        )
        conn.commit()
        conn.close()

        return redirect(url_for('home'))

    return render_template('register.html')

@app.route('/login', methods=['POST'])
def login():
    username = request.form['username']
    password = request.form['password']

    conn = get_db_connection()
    user = conn.execute(
        "SELECT * FROM users WHERE username=? AND password=?",
        (username, password)
    ).fetchone()
    conn.close()

    if user:
        session['user'] = user['nama']
        session['role'] = user['role'] #simpan role
        return redirect(url_for('dashboard'))
    else:
        return "Login gagal!"

@app.route('/dashboard')
def dashboard():
    if 'user' in session:
        return render_template('dashboard.html',
                               username=session['user'],
                               role=session['role'])  # 👈 WAJIB ADA
    return redirect(url_for('home'))

from datetime import datetime
from datetime import datetime # Paling atas file wajib ada ini!

from datetime import datetime, timedelta

@app.route('/absen', methods=['POST'])
def absen():
    try:
        data = request.get_json()
        if not data:
            return {"status": "error", "message": "Data tidak terbaca"}, 400

        kode_qr = data.get('kode_qr')
        nama_user = session.get('user', 'User Umum')

        if not kode_qr:
            return {"status": "error", "message": "Kode QR tidak valid"}, 400

        # ----------------====================================----------------
        # 1. ANTISIPASI DOUBLE INPUT: CEK COOLDOWN 1 MENIT TERAKHIR
        # ----------------====================================----------------
        waktu_sekarang = datetime.now()
        satu_menit_lalu = waktu_sekarang - timedelta(minutes=1)
        
        # Format pencarian jam menit untuk membatasi rentang waktu di SQLite
        waktu_pencarian = satu_menit_lalu.strftime("%H:%M:%S")
        
        conn = get_db_connection()
        
        # Cari apakah user ini sudah melakukan absen dengan QR yang sama hari ini 
        # dan jamnya masih dalam rentang 1 menit terakhir
        cek_absen = conn.execute(
            """
            SELECT id FROM absensi 
            WHERE nama_user = ? 
              AND kode_qr = ? 
              AND waktu LIKE ? 
              AND SUBSTR(waktu, -8) >= ?
            """,
            (nama_user, kode_qr, f"%{waktu_sekarang.day} {['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember'][waktu_sekarang.month - 1]} {waktu_sekarang.year}%", waktu_pencarian)
        ).fetchone()

        if cek_absen:
            conn.close()
            # Kembalikan status sukses semu / pesan peringatan agar frontend tidak error
            print(f" IGNORED: Jeda terlalu cepat, {nama_user} sudah absen dalam 1 menit terakhir.")
            return {"status": "ignored", "message": "Anda sudah melakukan scan baru-baru ini. Tunggu 1 menit."}

        # ----------------====================================----------------
        # 2. FORMAT TANGGAL DAN JAM BAHASA INDONESIA AUTOMATIC BY SERVER
        # ----------------====================================----------------
        hari_id = ["Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Ahad"]
        bulan_id = ["Januari", "Februari", "Maret", "April", "Mei", "Juni", 
                    "Juli", "Agustus", "September", "Oktober", "November", "Desember"]
        
        nama_hari = hari_id[waktu_sekarang.weekday()]
        tgl = waktu_sekarang.day
        nama_bulan = bulan_id[waktu_sekarang.month - 1]
        tahun = waktu_sekarang.year
        jam = waktu_sekarang.strftime("%H:%M:%S")

        # Menggabungkan menjadi: "Minggu, 17 Mei 2026 - 17:15:00"
        waktu_lengkap = f"{nama_hari}, {tgl} {nama_bulan} {tahun} - {jam}"

        # ----------------====================================----------------
        # 3. PROSES SIMPAN KE DATABASE (JIKA LOLOS VALIDASI)
        # ----------------====================================----------------
        conn.execute(
            "INSERT INTO absensi (nama_user, kode_qr, waktu) VALUES (?, ?, ?)",
            (nama_user, kode_qr, waktu_lengkap)
        )
        conn.commit()
        conn.close()

        print(f" SUCCESS: {nama_user} tercatat pada {waktu_lengkap}")
        return {"status": "success"}

    except Exception as e:
        print(f" ERROR: {str(e)}")
        return {"status": "error", "message": "Terjadi kesalahan pada server"}, 500

@app.route('/scanner')
def scanner():
    if 'user' in session:
        # Kirim nama pengguna yang sedang login ke scanner.html
        return render_template('scanner.html', username=session['user'])
    
    # Jika belum login tapi nekat buka /scanner, lempar ke login
    return redirect(url_for('home'))    

@app.route('/logout')
def logout():
    session.pop('user', None)
    return redirect(url_for('home'))

# 🔥 halaman khusus admin
import sqlite3
from flask import Flask, render_template

@app.route('/admin')
def admin():
    if 'user' in session and session['role'] == 'admin':
        conn = get_db_connection()
        users = conn.execute("SELECT * FROM users").fetchall()
        data_absensi = conn.execute("SELECT * FROM absensi ORDER BY id DESC").fetchall()
        conn.close()
        return render_template('admin.html', users=users, data_absensi=data_absensi)
    else:
        return "Akses ditolak!"

@app.route('/delete/<int:id>')
def delete_user(id):

    if 'user' in session and session['role'] == 'admin':

        conn = get_db_connection()

        conn.execute("DELETE FROM users WHERE id=?", (id,))
        conn.commit()
        conn.close()

        return redirect(url_for('admin'))

    return "Akses ditolak!"

# Nama fungsi harus 'halaman_qr_gps' agar sesuai dengan url_for() di HTML

import qrcode
import io
import base64
from flask import Flask, render_template, request, redirect, url_for

# Variabel Global penampung sementara di memori server (Idealnya disimpan ke DB SQLite)
konfig_lokasi = {
    "konten_qr": "ABSEN-2026",
    "latitude": "-6.247465",
    "longitude": "106.760414",
    "radius": "50"
}

@app.route('/qr-admin', methods=['GET', 'POST'])
def halaman_qr_gps():
    global konfig_lokasi
    
    if request.method == 'POST':
        # 1. Ambil data baru hasil input admin dari Form HTML
        konfig_lokasi["konten_qr"] = request.form.get('nama_kantor')
        konfig_lokasi["latitude"] = request.form.get('latitude')
        konfig_lokasi["longitude"] = request.form.get('longitude')
        konfig_lokasi["radius"] = request.form.get('radius')
        
        # Di sini Anda bisa menambahkan fungsi save ke DB SQLite jika diperlukan:
        # conn.execute("UPDATE pengaturan_kantor SET konten_qr=?, lat=?, lng=?, radius=?", (...))
        
        return redirect(url_for('halaman_qr_gps'))

    # 2. PROSES REGENERASI DATA QR CODE MENJADI BASE64 IMAGE
    qr = qrcode.QRCode(version=1, box_size=10, border=2)
    qr.add_data(konfig_lokasi["konten_qr"])
    qr.make(fit=True)
    
    img = qr.make_image(fill_color="black", back_color="white")
    
    # Simpan binary gambar ke memori buffer RAM objek bytes
    buffer = io.BytesIO()
    img.save(buffer, format="PNG")
    isi_buffer = buffer.getvalue()
    
    # Enkode data binary menjadi string string base64 URI agar bisa dibaca tag <img> HTML
    qr_base64 = base64.b64encode(isi_buffer).decode('utf-8')
    qr_data_uri = f"data:image/png;base64,{qr_base64}"

    return render_template(
        'halaman_qr_gps.html', 
        konten_qr_sekarang=konfig_lokasi["konten_qr"],
        lat_sekarang=konfig_lokasi["latitude"],
        lng_sekarang=konfig_lokasi["longitude"],
        radius_sekarang=konfig_lokasi["radius"],
        qr_data_uri=qr_data_uri
    )

# Bagian ini untuk menampilkan halaman admin dengan data absensi terbaru, bisa diakses oleh admin saja
@app.route('/halaman_absensi')
def halaman_absensi():
    if 'user' in session and session['role'] == 'admin':
        conn = get_db_connection()
        users = conn.execute("SELECT * FROM users").fetchall()
        data_absensi = conn.execute("SELECT * FROM absensi ORDER BY id DESC").fetchall()
        conn.close()
        return render_template('halaman_absensi.html', users=users, data_absensi=data_absensi)
    else:
        return "Akses ditolak!"
def halaman_absensi():
    conn = get_db_connection()
    # Mengambil data dari tabel absensi yang sudah ada di database lama Anda
    data_absensi = conn.execute("SELECT nama_user, kode_qr, waktu FROM absensi ORDER BY id DESC").fetchall()
    conn.close()
    return render_template('halaman_absensi.html', data_absensi=data_absensi) # Sesuaikan nama file .html Anda

# Bagian data karyawan, bisa diakses oleh admin saja, menampilkan semua user
@app.route('/halaman_karyawan')
def halaman_karyawan():
    # Pastikan file html ini ada di dalam folder 'templates'
    if 'user' in session and session['role'] == 'admin':
        conn = get_db_connection()
        users = conn.execute("SELECT * FROM users").fetchall()
        data_absensi = conn.execute("SELECT * FROM absensi ORDER BY id DESC").fetchall()
        conn.close()
        return render_template('halaman_karyawan.html', users=users, data_absensi=data_absensi)
    else:
        return "Akses ditolak!"
    
from flask import Flask, render_template, request
import sqlite3

from datetime import datetime

@app.route('/laporan')
def halaman_laporan():
    tgl_mulai = request.args.get('tanggal_mulai')   # Menghasilkan format: 'YYYY-MM-DD'
    tgl_selesai = request.args.get('tanggal_selesai') # Menghasilkan format: 'YYYY-MM-DD'
    
    conn = get_db_connection()
    
    if tgl_mulai and tgl_selesai:
        # 1. Konversi string input HTML ('2026-05-20') menjadi objek datetime Python
        obj_mulai = datetime.strptime(tgl_mulai, '%Y-%m-%d')
        obj_selesai = datetime.strptime(tgl_selesai, '%Y-%m-%d')
        
        # 2. Ambil semua data terlebih dahulu dari database lama Anda
        semua_absen = conn.execute("SELECT nama_user, kode_qr, waktu FROM absensi ORDER BY id DESC").fetchall()
        
        # 3. Kamus lokal nama bulan Indonesia untuk mencocokkan string di database Anda
        bulan_indo = {
            'Januari': 1, 'Februari': 2, 'Maret': 3, 'April': 4, 'Mei': 5, 'Juni': 6,
            'Juli': 7, 'Agustus': 8, 'September': 9, 'Oktober': 10, 'November': 11, 'Desember': 12,
            'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'Jun': 6, 'Jul': 7, 'Agu': 8, 'Sep': 9, 'Okt': 10, 'Nov': 11, 'Des': 12
        }
        
        data_absensi = []
        for row in semua_absen:
            try:
                # Contoh isi teks row['waktu']: "Rabu, 20 Mei 2026 - 11:34:06"
                teks_waktu = row['waktu']
                
                # Potong bagian hari depan (ambil setelah tanda koma jika ada)
                if ',' in teks_waktu:
                    teks_waktu = teks_waktu.split(',')[1].strip()
                
                # Pisahkan komponen tanggal, bulan, tahun dan jam
                # Hasil split: ['20', 'Mei', '2026', '-', '11:34:06']
                komponen = teks_waktu.split()
                
                tgl = int(komponen[0])
                nama_bln = komponen[1]
                thn = int(komponen[2])
                
                angka_bulan = bulan_indo.get(nama_bln, 1)
                
                # Bentuk objek tanggal record data untuk dibandingkan
                tanggal_record = datetime(thn, angka_bulan, tgl)
                
                # Lakukan penyaringan rentang waktu secara akurat di level Python
                if obj_mulai <= tanggal_record <= obj_selesai:
                    data_absensi.append(row)
            except Exception as e:
                # Jika ada format teks waktu yang tidak sesuai, skip record tersebut agar tidak crash
                continue
    else:
        # Jika filter kosong, tampilkan seluruh data histori lama Anda secara default
        data_absensi = conn.execute("SELECT nama_user, kode_qr, waktu FROM absensi ORDER BY id DESC").fetchall()
        
    conn.close()
    return render_template('halaman_laporan.html', data_absensi=data_absensi)

@app.route('/edit/<int:id>', methods=['GET', 'POST'])
def edit_user(id):

    if 'user' not in session or session['role'] != 'admin':
        return "Akses ditolak!"

    conn = get_db_connection()

    user = conn.execute(
        "SELECT * FROM users WHERE id=?",
        (id,)
    ).fetchone()

    if request.method == 'POST':

        nama = request.form['nama']
        username = request.form['username']
        role = request.form['role']

        conn.execute(
            "UPDATE users SET nama=?, username=?, role=? WHERE id=?",
            (nama, username, role, id)
        )

        conn.commit()
        conn.close()

        return redirect(url_for('admin'))

    conn.close()

    return render_template('edit_user.html', user=user)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)
