<?php defined('BASEPATH') OR exit('No direct script access allowed');

class Pembayaran_model extends CI_Model
{
    /** Nama tabel di DB */
    private $table = 'pembayaran';

    /** cache list kolom */
    private $field_cache = null;

    public function __construct()
    {
        parent::__construct();
        $this->load->database();
        date_default_timezone_set('Asia/Jakarta');
    }

    /* =========================================================
     * Utilities internal
     * =======================================================*/

    /** ambil daftar kolom (lowercase) sekali saja */
    private function _fields(): array
    {
        if ($this->field_cache === null) {
            $this->field_cache = array_map('strtolower', $this->db->list_fields($this->table));
        }
        return $this->field_cache;
    }

    /** cek punya kolom */
    private function _has(string $col): bool
    {
        return in_array(strtolower($col), $this->_fields(), true);
    }

    /** nama kolom jenis yang tersedia (JenisPembayaran|Jenis|null) */
    private function _jenis_col(): ?string
    {
        if ($this->_has('JenisPembayaran')) return 'JenisPembayaran';
        if ($this->_has('Jenis'))           return 'Jenis';
        return null;
    }

    /** normalisasi status → lowercase: approved|rejected|pending */
    private function _norm_status(?string $s): string
    {
        $s = strtolower((string)$s);
        if (in_array($s, ['approved','approve'], true)) return 'approved';
        if (in_array($s, ['rejected','reject'], true))  return 'rejected';
        return 'pending';
    }

    /** kolom order tanggal yang aman */
    private function _order_col(): string
    {
        if ($this->_has('TanggalBayar')) return 'TanggalBayar';
        if ($this->_has('CreatedAt'))    return 'CreatedAt';
        return 'PembayaranID';
    }

    /** base query builder: where kolom utama (UserID/SiswaID) + filter jenis bila ada */
    private function _qb_base(string $col, $val, ?string $jenis_label = null): CI_DB_query_builder
    {
        $qb = $this->db->from($this->table.' p')->where('p.'.$col, $val);

        $jcol = $this->_jenis_col();
        if ($jenis_label && $jcol) {
            $qb->where('p.'.$jcol, $jenis_label);
        }
        return $qb;
    }

    /** injeksi nilai jenis ke payload sesuai kolom yang tersedia */
    private function _inject_jenis(array &$data, ?string $default = null): void
    {
        $jcol = $this->_jenis_col();
        if (!$jcol) {
            unset($data['Jenis'], $data['JenisPembayaran']);
            return;
        }
        // bila data punya salah satu kolom, map ke kolom sebenarnya
        if (isset($data['Jenis']) && $jcol === 'JenisPembayaran') {
            $data['JenisPembayaran'] = $data['Jenis']; unset($data['Jenis']);
        }
        if (isset($data['JenisPembayaran']) && $jcol === 'Jenis') {
            $data['Jenis'] = $data['JenisPembayaran']; unset($data['JenisPembayaran']);
        }
        // kalau kosong dan ada default, isi
        if (!isset($data[$jcol]) && $default !== null) {
            $data[$jcol] = $default;
        }
    }

    /* =========================================================
     * Query umum
     * =======================================================*/

    /** untuk admin dashboard ringkas */
    public function get_all_with_siswa()
    {
        $orderCol = $this->_order_col();

        return $this->db->select("
                    p.*,
                    COALESCE(s.NamaLengkap, p.NamaLengkap) AS NamaTampil,
                    u.Email, u.Phone, ss.NamaStatus
                ")
                ->from($this->table.' p')
                ->join('siswa s', 's.SiswaID = p.SiswaID', 'left')
                ->join('users u', 'u.UserID = p.UserID', 'left')
                ->join('statussiswa ss', 'ss.StatusID = s.StatusID', 'left')
                ->order_by('p.'.$orderCol, 'DESC')
                ->get()->result();
    }

    /** riwayat berdasarkan UserID (calon) */
    public function get_by_user(int $user_id, ?string $jenis = null): array
    {
        $orderCol = $this->_order_col();

        $qb = $this->_qb_base('UserID', $user_id, $jenis);
        $qb->order_by('p.'.$orderCol, 'DESC');
        return $qb->get()->result();
    }

    /** riwayat berdasarkan SiswaID (HSI000xx) */
    public function get_by_siswa(string $siswa_id, ?string $jenis = null): array
    {
        $orderCol = $this->_order_col();

        $qb = $this->_qb_base('SiswaID', $siswa_id, $jenis);
        $qb->order_by('p.'.$orderCol, 'DESC');
        return $qb->get()->result();
    }

    /** list pending untuk admin */
    public function get_pending_list(): array
    {
        $orderCol = $this->_order_col();

        return $this->db->select('p.*, s.NamaLengkap')
                        ->from($this->table.' p')
                        ->join('siswa s', 's.SiswaID = p.SiswaID', 'left')
                        ->where('p.StatusBayar', 'pending')
                        ->order_by('p.'.$orderCol, 'DESC')
                        ->get()->result();
    }

    /** ambil 1 baris by primary key */
    public function get_by_id(int $id)
    {
        return $this->db->where('PembayaranID', $id)->get($this->table)->row();
    }

    /** hitung termin yang sudah ada (maks 3) untuk (SiswaID|UserID) pada jenis tertentu */
    public function count_termin(?string $siswa_id, ?int $user_id, ?string $jenis_label = null): int
    {
        if ($siswa_id) {
            $qb = $this->_qb_base('SiswaID', $siswa_id, $jenis_label);
        } else {
            $qb = $this->_qb_base('UserID', (int)$user_id, $jenis_label);
        }
        return (int)$qb->count_all_results();
    }

    /* =========================================================
     * Mutasi
     * =======================================================*/

    /** create baris pending dari siswa */
    public function create_pending(array $data)
    {
        // status → lowercase
        $data['StatusBayar'] = $this->_norm_status($data['StatusBayar'] ?? 'pending');

        // tanggal default
        if (empty($data['TanggalBayar'])) $data['TanggalBayar'] = date('Y-m-d H:i:s');

        // map kolom Jenis/JenisPembayaran jika ada (default Pelatihan)
        $this->_inject_jenis($data, $data['Jenis'] ?? $data['JenisPembayaran'] ?? 'Pelatihan');

        // TerminKe otomatis (jika kolomnya ada & belum diisi)
        if ($this->_has('TerminKe') && empty($data['TerminKe'])) {
            $data['TerminKe'] = $this->count_termin(
                $data['SiswaID'] ?? null,
                $data['UserID'] ?? null,
                $this->_jenis_col() ? ($data[$this->_jenis_col()] ?? null) : null
            ) + 1;
        }

        $this->db->insert($this->table, $data);
        return $this->db->insert_id();
    }

    /**
     * Set status (approved|rejected|pending) + optional reason + optional admin
     * - mengisi ApprovedBy & ApprovedAt ketika approve/reject
     * - mengosongkan ApprovedBy/ApprovedAt bila kembali ke pending
     */
    public function set_status(int $pembayaran_id, string $status, ?string $reason = null, ?int $admin_user_id = null): bool
    {
        // pastikan row ada
        $exists = $this->db->select('PembayaranID')
                           ->where('PembayaranID', $pembayaran_id)
                           ->limit(1)->get($this->table)->num_rows() > 0;
        if (!$exists) return false;

        $norm = $this->_norm_status($status); // approved|rejected|pending

        $data = ['StatusBayar' => $norm];

        // cap keputusan
        if (in_array($norm, ['approved','rejected'], true)) {
            if ($this->_has('ApprovedAt')) $data['ApprovedAt'] = date('Y-m-d H:i:s');
            if ($this->_has('ApprovedBy') && $admin_user_id !== null) {
                $data['ApprovedBy'] = (int)$admin_user_id;
            }
        } else {
            // balik ke pending -> bersihkan cap
            if ($this->_has('ApprovedAt')) $data['ApprovedAt'] = null;
            if ($this->_has('ApprovedBy')) $data['ApprovedBy'] = null;
        }

        // simpan alasan jika ada kolomnya
        if ($reason !== null && $reason !== '') {
            if ($this->_has('Alasan'))      $data['Alasan'] = $reason;
            elseif ($this->_has('Catatan')) $data['Catatan'] = $reason;
        }

        $this->db->where('PembayaranID', $pembayaran_id)->update($this->table, $data);
        return $this->db->affected_rows() >= 0;
    }

    /** helper approve */
    public function approve(int $pembayaran_id, ?int $admin_user_id = null): bool
    {
        return $this->set_status($pembayaran_id, 'approved', null, $admin_user_id);
    }

    /** helper reject */
    public function reject(int $pembayaran_id, ?string $reason = null, ?int $admin_user_id = null): bool
    {
        return $this->set_status($pembayaran_id, 'rejected', $reason, $admin_user_id);
    }
}
