<?php

namespace App\Controllers;

use App\Controllers\BaseController;
use App\Models\KaryawanModel;
use App\Models\AbsensiModel;
use App\Models\PenggajianModel;
use App\Models\TransaksiKasModel;

class HRD extends BaseController
{
    protected $karyawanModel;
    protected $absensiModel;
    protected $penggajianModel;
    protected $kasModel;

    public function __construct()
    {
        $this->karyawanModel   = new KaryawanModel();
        $this->absensiModel    = new AbsensiModel();
        $this->penggajianModel = new PenggajianModel();
        $this->kasModel        = new TransaksiKasModel();
    }

    // ==========================================
    // KARYAWAN
    // ==========================================
    public function karyawan()
    {
        $data['karyawan'] = $this->karyawanModel->findAll();
        return view('hrd/karyawan', $data);
    }

    public function storeKaryawan()
    {
        $id = $this->request->getPost('id_karyawan');

        $data = [
            'nama_karyawan'              => $this->request->getPost('nama_karyawan'),
            'posisi_karyawan'            => $this->request->getPost('posisi_karyawan'),
            'rate_gaji_per_jam_karyawan' => $this->request->getPost('rate_gaji_per_jam_karyawan') ?? 10000,
            'status_karyawan'            => $this->request->getPost('status_karyawan') ?? 'Aktif',
        ];

        if ($id) {
            $this->karyawanModel->update($id, $data);
            $msg = 'Data Karyawan berhasil diperbarui.';
        } else {
            $this->karyawanModel->save($data);
            $msg = 'Data Karyawan berhasil ditambahkan.';
        }

        return redirect()->to('/hrd/karyawan')->with('success', $msg);
    }

    public function deleteKaryawan($id)
    {
        $this->karyawanModel->delete($id);
        return redirect()->to('/hrd/karyawan')->with('success', 'Data Karyawan berhasil dihapus.');
    }

    public function toggleStatusKaryawan($id)
    {
        $model = new \App\Models\KaryawanModel();

        $data = $model->find($id);

        if (!$data) {
            return redirect()->back()->with('error', 'Data tidak ditemukan');
        }

        $this->karyawanModel->toggleStatusKaryawan($id);

        return redirect()->back()->with('success', 'Status karyawan berhasil diubah');
    }

    // ==========================================
    // ABSENSI
    // ==========================================
    public function absensi()
    {
        $rows = $this->absensiModel->getAbsensiWithKaryawan();

        // Decode kolom 'sesi' (JSON) → array PHP supaya view bisa loop langsung
        foreach ($rows as &$row) {
            if (!empty($row['sesi']) && is_string($row['sesi'])) {
                $decoded = json_decode($row['sesi'], true);
                $row['sesi'] = (is_array($decoded) && count($decoded)) ? $decoded : null;
            }

            // Fallback: data lama yang belum punya kolom sesi
            if (empty($row['sesi'])) {
                $row['sesi'] = [[
                    'masuk'  => $row['jam_masuk_absensi'],
                    'keluar' => $row['jam_keluar_absensi'],
                    'jam'    => $row['total_jam_kerja_absensi'],
                ]];
            }
        }
        unset($row);

        $data['absensi']  = $rows;
        $data['karyawan'] = $this->karyawanModel->findAll();
        return view('hrd/absensi', $data);
    }

    public function storeAbsensi()
    {
        $id         = $this->request->getPost('id_absensi');
        $idKaryawan = $this->request->getPost('id_karyawan');
        $tanggal    = $this->request->getPost('tanggal_absensi');

        // ── Ambil array sesi dari form ──────────────────────────────────────
        // Format POST: sesi[1][masuk], sesi[1][keluar], sesi[2][masuk], dst.
        $sesiRaw = $this->request->getPost('sesi') ?? [];

        if (empty($sesiRaw)) {
            return redirect()->back()->withInput()
                ->with('error', 'Minimal satu sesi jam kerja harus diisi.');
        }

        // 0. Cek periode terkunci (gaji sudah LUNAS)
        $periodeBulan = substr($tanggal, 0, 7);
        $penggajian = $this->penggajianModel
            ->where('id_karyawan', $idKaryawan)
            ->where('periode_bulan_penggajian', $periodeBulan)
            ->first();

        if ($penggajian && $penggajian['status_pembayaran_penggajian'] === 'Sudah Dibayar') {
            return redirect()->back()->withInput()
                ->with('error', 'Gaji bulan ini sudah LUNAS. Data absensi dikunci dan tidak dapat diubah.');
        }

        // 1. Cek duplikasi (hanya untuk input baru)
        if (!$id) {
            $existing = $this->absensiModel
                ->where('id_karyawan', $idKaryawan)
                ->where('tanggal_absensi', $tanggal)
                ->first();

            if ($existing) {
                return redirect()->back()->withInput()
                    ->with('error', 'Karyawan ini sudah memiliki catatan absensi pada tanggal tersebut.');
            }
        }

        // 2. Validasi & kalkulasi total jam dari semua sesi
        $sesiValid = [];
        $totalJam  = 0;

        foreach ($sesiRaw as $s) {
            $masuk  = trim($s['masuk']  ?? '');
            $keluar = trim($s['keluar'] ?? '');

            if (!$masuk || !$keluar) continue; // skip sesi kosong

            $t1 = strtotime($masuk);
            $t2 = strtotime($keluar);

            if ($t2 <= $t1) {
                return redirect()->back()->withInput()
                    ->with('error', "Jam keluar harus lebih besar dari jam masuk (sesi: $masuk – $keluar).");
            }

            $jamSesi   = round(($t2 - $t1) / 3600, 2);
            $totalJam += $jamSesi;

            $sesiValid[] = [
                'masuk'  => $masuk,
                'keluar' => $keluar,
                'jam'    => $jamSesi,
            ];
        }

        if (empty($sesiValid)) {
            return redirect()->back()->withInput()
                ->with('error', 'Tidak ada sesi jam kerja yang valid.');
        }

        // Ambil jam masuk sesi pertama & jam keluar sesi terakhir
        // (disimpan di kolom lama agar backward-compatible)
        $jamMasukPertama  = $sesiValid[0]['masuk'];
        $jamKeluarTerakhir = end($sesiValid)['keluar'];

        $data = [
            'id_karyawan'             => $idKaryawan,
            'tanggal_absensi'         => $tanggal,
            'jam_masuk_absensi'       => $jamMasukPertama,
            'jam_keluar_absensi'      => $jamKeluarTerakhir,
            'sesi'                    => json_encode($sesiValid),   // kolom baru (JSON/TEXT)
            'total_jam_kerja_absensi' => $totalJam,
        ];

        if ($id) {
            $this->absensiModel->update($id, $data);
            $msg = 'Data Absensi berhasil diperbarui. Penggajian akan disinkronisasi.';
        } else {
            $this->absensiModel->save($data);
            $msg = 'Data Absensi berhasil ditambahkan. Penggajian otomatis disinkronisasi.';
        }

        // 3. Sync ke tabel penggajian
        $this->syncPenggajian($idKaryawan, $tanggal);

        return redirect()->back()->with('success', $msg);
    }

    /**
     * Alias route POST /hrd/update-absensi → sama dengan store, id_absensi sudah ada di POST.
     */
    public function updateAbsensi()
    {
        return $this->storeAbsensi();
    }

    public function deleteAbsensi($id)
    {
        $absensi = $this->absensiModel->find($id);
        if (!$absensi) {
            return redirect()->to('/hrd/absensi')->with('error', 'Data tidak ditemukan.');
        }

        // Proteksi hapus jika gaji sudah LUNAS
        $periodeBulan = substr($absensi['tanggal_absensi'], 0, 7);
        $penggajian = $this->penggajianModel
            ->where('id_karyawan', $absensi['id_karyawan'])
            ->where('periode_bulan_penggajian', $periodeBulan)
            ->first();

        if ($penggajian && $penggajian['status_pembayaran_penggajian'] === 'Sudah Dibayar') {
            return redirect()->to('/hrd/absensi')
                ->with('error', 'Gaji untuk absensi ini sudah LUNAS. Data tidak dapat dihapus.');
        }

        $idKar = $absensi['id_karyawan'];
        $tgl   = $absensi['tanggal_absensi'];

        $this->absensiModel->delete($id);
        $this->syncPenggajian($idKar, $tgl);

        return redirect()->to('/hrd/absensi')
            ->with('success', 'Data Absensi berhasil dihapus. Gaji dikalkulasi ulang secara realtime.');
    }

    /**
     * Engine Realtime Sync Penggajian
     * Menghitung ulang total jam dari kolom total_jam_kerja_absensi
     * (sudah mencerminkan penjumlahan semua sesi sejak disimpan di storeAbsensi).
     */
    private function syncPenggajian($idKaryawan, $tanggal)
    {
        $periodeBulan = substr($tanggal, 0, 7);

        $penggajian = $this->penggajianModel
            ->where('id_karyawan', $idKaryawan)
            ->where('periode_bulan_penggajian', $periodeBulan)
            ->first();

        if ($penggajian && $penggajian['status_pembayaran_penggajian'] === 'Belum Dibayar') {
            $karyawan = $this->karyawanModel->find($idKaryawan);

            $db    = \Config\Database::connect();
            $query = $db->query("
                SELECT SUM(total_jam_kerja_absensi) AS total_jam
                FROM tb_absensi
                WHERE id_karyawan = ?
                  AND DATE_FORMAT(tanggal_absensi, '%Y-%m') = ?
            ", [$idKaryawan, $periodeBulan]);

            $totalJam = $query->getRow()->total_jam ?? 0;

            if ($totalJam <= 0) {
                $this->penggajianModel->delete($penggajian['id_penggajian']);
            } else {
                $totalGaji = $totalJam * $karyawan['rate_gaji_per_jam_karyawan'];
                $this->penggajianModel->update($penggajian['id_penggajian'], [
                    'total_jam_penggajian'  => $totalJam,
                    'total_gaji_penggajian' => $totalGaji,
                ]);
            }
        }
    }

    //

    public function laporanAbsensi()
{
    $bulan = $this->request->getGet('bulan') ?? date('Y-m');

    $db = \Config\Database::connect();

    $query = $db->query("
        SELECT 
            k.nama_karyawan,
            k.posisi_karyawan,
            COUNT(a.id_absensi) as total_hadir,
            SUM(a.total_jam_kerja_absensi) as total_jam
        FROM tb_absensi a
        JOIN tb_karyawan k 
        ON k.id_karyawan = a.id_karyawan
        WHERE DATE_FORMAT(a.tanggal_absensi, '%Y-%m') = ?
        GROUP BY a.id_karyawan
        ORDER BY k.nama_karyawan ASC
    ", [$bulan]);

    $data['laporan'] = $query->getResultArray();
    $data['bulan']   = $bulan;

    return view('hrd/laporan_absensi', $data);
}

//

public function laporanPenggajian()
{
    $bulan = $this->request->getGet('bulan') ?? date('Y-m');

    $db = \Config\Database::connect();

    $query = $db->query("
        SELECT 
            k.nama_karyawan,
            k.posisi_karyawan,
            p.periode_bulan_penggajian,
            p.total_jam_penggajian,
            p.total_gaji_penggajian,
            p.status_pembayaran_penggajian
        FROM tb_penggajian p
        JOIN tb_karyawan k
        ON k.id_karyawan = p.id_karyawan
        WHERE p.periode_bulan_penggajian = ?
        ORDER BY p.total_gaji_penggajian DESC
    ", [$bulan]);

    $data['laporan'] = $query->getResultArray();
    $data['bulan']   = $bulan;

    return view('hrd/laporan_penggajian', $data);
}





    // ==========================================
    // PENGGAJIAN
    // ==========================================
    public function penggajian()
    {
        $data['penggajian'] = $this->penggajianModel->getPenggajianWithKaryawan();
        $data['karyawan']   = $this->karyawanModel->findAll();
        return view('hrd/penggajian', $data);
    }

    public function generateGaji()
    {
        $idKaryawan   = $this->request->getPost('id_karyawan');
        $periodeBulan = $this->request->getPost('periode_bulan_penggajian');

        // 0. Cek duplikasi slip gaji
        $existing = $this->penggajianModel
            ->where('id_karyawan', $idKaryawan)
            ->where('periode_bulan_penggajian', $periodeBulan)
            ->first();

        if ($existing) {
            $statusStr = $existing['status_pembayaran_penggajian'] === 'Sudah Dibayar'
                ? 'sudah LUNAS'
                : 'sedang MENUNGGU PEMBAYARAN';
            return redirect()->back()
                ->with('error', "Slip gaji untuk periode $periodeBulan sudah digenerate dan saat ini $statusStr.");
        }

        // 1. Dapatkan detail karyawan
        $karyawan = $this->karyawanModel->find($idKaryawan);
        if (!$karyawan) {
            return redirect()->back()->with('error', 'Karyawan tidak ditemukan.');
        }

        // 2. Kalkulasi total jam kerja periode terkait
        $db    = \Config\Database::connect();
        $query = $db->query("
            SELECT SUM(total_jam_kerja_absensi) AS total_jam
            FROM tb_absensi
            WHERE id_karyawan = ?
              AND DATE_FORMAT(tanggal_absensi, '%Y-%m') = ?
        ", [$idKaryawan, $periodeBulan]);

        $totalJam = $query->getRow()->total_jam ?? 0;

        if ($totalJam <= 0) {
            return redirect()->back()
                ->with('error', 'Karyawan belum memiliki jam kerja pada periode ini.');
        }

        $totalGaji = $totalJam * $karyawan['rate_gaji_per_jam_karyawan'];

        // 3. Simpan draft penggajian
        $this->penggajianModel->save([
            'id_karyawan'                  => $idKaryawan,
            'periode_bulan_penggajian'     => $periodeBulan,
            'total_jam_penggajian'         => $totalJam,
            'total_gaji_penggajian'        => $totalGaji,
            'status_pembayaran_penggajian' => 'Belum Dibayar',
        ]);

        return redirect()->to('/hrd/penggajian')
            ->with('success', "Gaji Periode $periodeBulan berhasil di-generate otomatis.");
    }

    public function bayarGaji($id)
    {
        $gaji = $this->penggajianModel->find($id);

        if ($gaji && $gaji['status_pembayaran_penggajian'] === 'Belum Dibayar') {

            // 1. Update status penggajian
            $this->penggajianModel->update($id, [
                'status_pembayaran_penggajian' => 'Sudah Dibayar',
                'tanggal_bayar_penggajian'     => date('Y-m-d H:i:s'),
            ]);

            $karyawan = $this->karyawanModel->find($gaji['id_karyawan']);

            // 2. Otomasi: catat pengeluaran kas
            $this->kasModel->save([
                'tanggal_transaksi_kas'    => date('Y-m-d'),
                'tipe_transaksi_kas'       => 'Pengeluaran',
                'kategori_transaksi_kas'   => 'Biaya Gaji / Upah Karyawan',
                'keterangan_transaksi_kas' => 'Pembayaran Gaji an. ' . $karyawan['nama_karyawan']
                                           . ' Periode ' . $gaji['periode_bulan_penggajian'],
                'nominal_transaksi_kas'    => $gaji['total_gaji_penggajian'],
            ]);

            return redirect()->to('/hrd/penggajian')
                ->with('success', 'Gaji berhasil dibayarkan dan Kas berkurang otomatis.');
        }

        return redirect()->back()->with('error', 'Data tidak valid atau sudah dibayar.');
    }
}