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

class Pembayaran_model extends CI_Model
{
    /** Gunakan nama tabel persis seperti di DB (lowercase) */
    protected $table = 'pembayaran';

    /** cache list kolom agar tidak repeat call list_fields() */
    private $field_cache = null;

    public function __construct()
    {
        parent::__construct();
        $this->load->database();
    }

    /* =========================================================
     * Utilitas internal
     * =======================================================*/

    /** list kolom (lowercase) sekali aja */
    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;
    }

    /** deteksi nama kolom jenis di tabel */
    private function jenis_col(): ?string
    {
        $f = $this->_fields();
        if (in_array('jenispembayaran', $f, true)) return 'JenisPembayaran';
        if (in_array('jenis', $f, true))           return 'Jenis';
        return null;
    }

    /** normalisasi status → `approved|rejected|pending` (lowercase) */
    private function norm_status(?string $s): string
    {
        $s = strtolower((string)$s);
        if ($s === 'approved' || $s === 'approve') return 'approved';
        if ($s === 'rejected' || $s === 'reject')  return 'rejected';
        return 'pending';
    }

    /** jadikan TitleCase untuk disimpan ke DB */
    private function to_db_status(string $s): string
    {
        $n = $this->norm_status($s);
        return ucfirst($n); // approved -> Approved
    }

    /** kolom order tanggal yang aman */
    private function order_col(): string
    {
        $f = $this->_fields();
        if (in_array('tanggalbayar', $f, true)) return 'TanggalBayar';
        if (in_array('createdat', $f, true))    return 'CreatedAt';
        return 'PembayaranID';
    }

    /* =========================================================
     * 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($user_id, $jenis = null)
    {
        $orderCol = $this->order_col();

        $this->db->from($this->table.' p')
                 ->where('p.UserID', (int)$user_id);

        $col = $this->jenis_col();
        if ($jenis !== null && $col) {
            $this->db->where('p.'.$col, $jenis);
        }

        $this->db->order_by('p.'.$orderCol, 'DESC');
        return $this->db->get()->result();
    }

    /** riwayat berdasarkan SiswaID (HSI000xx) */
    public function get_by_siswa($siswa_id, $jenis = null)
    {
        $orderCol = $this->order_col();

        $this->db->from($this->table.' p')
                 ->where('p.SiswaID', $siswa_id);

        $col = $this->jenis_col();
        if ($jenis !== null && $col) {
            $this->db->where('p.'.$col, $jenis);
        }

        $this->db->order_by('p.'.$orderCol, 'DESC');
        return $this->db->get()->result();
    }

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

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

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

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

        // map kolom Jenis/JenisPembayaran jika ada
        $col = $this->jenis_col();
        if (!$col) {
            unset($data['Jenis'], $data['JenisPembayaran']);
        } else {
            if (isset($data['Jenis']) && $col === 'JenisPembayaran') {
                $data['JenisPembayaran'] = $data['Jenis']; unset($data['Jenis']);
            }
            if (isset($data['JenisPembayaran']) && $col === 'Jenis') {
                $data['Jenis'] = $data['JenisPembayaran']; unset($data['JenisPembayaran']);
            }
        }

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

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

    /**
     * Set status (Approved/Rejected/Pending) + optional reason + optional admin
     * - Mengisi ApprovedBy & ApprovedAt saat keputusan approve/reject
     * - Mengosongkan keduanya saat kembali ke Pending
     * - Return true jika row ada (meski nilai sama)
     */
    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
        $dbStatus = $this->to_db_status($norm);    // Approved|Rejected|Pending

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

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

        // simpan alasan jika tabel punya kolomnya
        if ($reason !== null && $reason !== '') {
            if ($this->db->field_exists('Alasan', $this->table)) {
                $data['Alasan'] = $reason;
            } elseif ($this->db->field_exists('Catatan', $this->table)) {
                $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);
    }
}
