<?php
namespace App\Controllers;

use CodeIgniter\Controller;
use Config\Database;
use Config\Tax;

class Payments extends Controller
{
    public function index()
    {
        $db = Database::connect();

        // Load supporting data
        $paymentTypes = $schoolYears = $classes = $sections = $students = [];
        // Resolve VAT rate: prefer settings_vat percent, fallback to config('Tax')->vatRate
        $vatRate = 0.15;
        try {
            $settings = $db->table('settings_vat')->orderBy('id','desc')->get()->getRowArray();
            if ($settings && isset($settings['vat_rate'])) {
                $vatRate = ((float) $settings['vat_rate']) / 100.0; // convert percent to fraction
            } else {
                $tax = config('Tax');
                $vatRate = (float) ($tax->vatRate ?? 0.15);
            }
        } catch (\Throwable $e) { $tax = config('Tax'); $vatRate = (float) ($tax->vatRate ?? 0.15); }

        try { $paymentTypes = $db->table('payment_types')->orderBy('id','asc')->get()->getResultArray(); } catch (\Throwable $e) { $paymentTypes = []; }
        try { $schoolYears = $db->table('school_years')->orderBy('id','desc')->get()->getResultArray(); } catch (\Throwable $e) { $schoolYears = []; }
        try { $classes = $db->table('classes')->orderBy('name_en','asc')->get()->getResultArray(); } catch (\Throwable $e) { $classes = []; }
        try { $sections = $db->table('sections')->orderBy('name_en','asc')->get()->getResultArray(); } catch (\Throwable $e) { $sections = []; }

        $q = trim((string)($this->request->getGet('q') ?? ''));
        if ($q !== '') {
            $like = '%' . $q . '%';
            try {
                $builder = $db->table('students')
                    ->select('id, student_id, first_name, last_name, name_ar, parent_name, parent_phone, parent_iqama');

                $builder = $builder->groupStart()
                    ->like('student_id', $like, 'both')
                    ->orLike('first_name', $like, 'both')
                    ->orLike('last_name', $like, 'both')
                    ->orLike('name_ar', $like, 'both')
                    ->orLike('parent_name', $like, 'both')
                    ->orLike('parent_iqama', $like, 'both')
                    ->orLike('parent_phone', $like, 'both')
                    ->groupEnd();

                $students = $builder->limit(50)->get()->getResultArray();
            } catch (\Throwable $e) { $students = []; }
        }

        return view('payments/index', [
            // Localized page title
            'title' => lang('App.payment_receipts'),
            'paymentTypes' => $paymentTypes,
            'schoolYears' => $schoolYears,
            'classes' => $classes,
            'sections' => $sections,
            'students' => $students,
            'query' => $q,
            'vatRate' => $vatRate,
        ]);
    }

    public function store()
    {
        $db = Database::connect();
        $req = $this->request;

        $studentId = (int) ($req->getPost('student_id') ?? 0);
        $schoolYearId = (int) ($req->getPost('school_year_id') ?? 0);
        $classId = (int) ($req->getPost('class_id') ?? 0);
        $sectionId = (int) ($req->getPost('section_id') ?? 0);
        $paymentMethod = trim((string) ($req->getPost('payment_method') ?? 'cash'));

        $items = [];
        $ptIds = $req->getPost('item_payment_type_id');
        $descs = $req->getPost('item_description');
        $amts = $req->getPost('item_amount');
        if (is_array($amts)) {
            foreach ($amts as $i => $amount) {
                $amount = (float) $amount;
                if ($amount <= 0) { continue; }
                $items[] = [
                    'payment_type_id' => (int) ($ptIds[$i] ?? 0),
                    'description' => (string) ($descs[$i] ?? ''),
                    'amount' => $amount,
                ];
            }
        }

        if (! $items) {
            return redirect()->back()->with('error', 'Add at least one receipt item with amount.')->withInput();
        }

        $total = 0.0;
        foreach ($items as $it) { $total += (float) $it['amount']; }
        $tax = config('Tax');

        // Read VAT settings
        $settings = [];
        try { $settings = $db->table('settings_vat')->orderBy('id','desc')->get()->getRowArray(); } catch (\Throwable $e) { $settings = []; }
        $vatEnabled = ($settings && !empty($settings['vat_number']) && ((float)($settings['vat_rate'] ?? 0)) > 0);
        $vatRate = $vatEnabled ? ((float) $settings['vat_rate']) / 100.0 : (float) ($tax->vatRate ?? 0.15);

        $vat = $vatEnabled ? round($total * $vatRate, 2) : 0.0;
        $grand = round($total + $vat, 2);

        $year = date('Y');
        $prefix = 'RCPT-' . $year . '-';
        $counter = '000001';
        try {
            $latest = $db->table('receipts')->select('receipt_no')->like('receipt_no', $prefix, 'after')->orderBy('receipt_no', 'DESC')->limit(1)->get()->getRowArray();
            if ($latest && isset($latest['receipt_no'])) {
                $last = (int) substr($latest['receipt_no'], strlen($prefix));
                $counter = str_pad($last + 1, 6, '0', STR_PAD_LEFT);
            }
        } catch (\Throwable $e) {
            // ignore
        }
        $receiptNo = $prefix . $counter;

        $db->transStart();
        try {
            $seller = $settings['school_name'] ?? ($tax->sellerName ?? 'School');
            $vatNumber = $vatEnabled ? ($settings['vat_number'] ?? '') : '';
            $qrPayload = '';
            if (($tax->qrEnabled ?? true) && $vatEnabled) {
                $qrPayload = $this->buildQrPayload($seller, $vatNumber, date('c'), $grand, $vat);
            }
            $receiptData = [
                'receipt_no' => $receiptNo,
                'student_id' => $studentId,
                'school_year_id' => $schoolYearId,
                'class_id' => $classId,
                'section_id' => $sectionId,
                'total' => $total,
                'vat' => $vat,
                'vat_rate' => $vatEnabled ? $vatRate : 0.0,
                'grand_total' => $grand,
                'vat_number' => $vatEnabled ? $vatNumber : null,
                'qr_payload' => $qrPayload,
                'payment_method' => $paymentMethod,
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s'),
            ];
            $db->table('receipts')->insert($receiptData);
            $receiptId = (int) $db->insertID();

            foreach ($items as $it) {
                $row = [
                    'receipt_id' => $receiptId,
                    'payment_type_id' => $it['payment_type_id'] ?? null,
                    'description' => $it['description'] ?? null,
                    'amount' => $it['amount'] ?? 0,
                ];
                $db->table('receipt_items')->insert($row);
            }

            $db->transComplete();
            if ($db->transStatus() === false) {
                return redirect()->back()->with('error', 'Failed to save receipt.')->withInput();
            }
            return redirect()->to('/payments/print/' . $receiptId)->with('success', 'Receipt saved.');
        } catch (\Throwable $e) {
            $db->transRollback();
            return redirect()->back()->with('error', 'Error saving receipt: ' . $e->getMessage())->withInput();
        }
    }

    public function print($id)
    {
        $db = Database::connect();
        $receipt = $items = $student = [];
        try {
            $receipt = $db->table('receipts')->where('id', (int) $id)->get()->getRowArray();
        } catch (\Throwable $e) { $receipt = []; }
        if (! $receipt) {
            return redirect()->to('/payments')->with('error', 'Receipt not found.');
        }
        try {
            $items = $db->table('receipt_items')->where('receipt_id', (int) $id)->get()->getResultArray();
        } catch (\Throwable $e) { $items = []; }
        try {
            $student = $db->table('students')->select('student_id, first_name, last_name, parent_phone')
                ->where('id', (int) ($receipt['student_id'] ?? 0))
                ->get()->getRowArray();
        } catch (\Throwable $e) { $student = []; }

        // Load VAT settings for school name and logo
        $settings = [];
        try { $settings = $db->table('settings_vat')->orderBy('id','desc')->get()->getRowArray(); } catch (\Throwable $e) { $settings = []; }

        return view('payments/print', [
            'title' => 'Receipt ' . ($receipt['receipt_no'] ?? ''),
            'receipt' => $receipt,
            'items' => $items,
            'student' => $student,
            'settings' => $settings,
        ]);
    }

    public function pending()
    {
        return view('payments/pending', [
            'title' => lang('App.pending_payments'),
        ]);
    }

    public function installments()
    {
        return view('payments/installments', [
            'title' => lang('App.installments_management'),
        ]);
    }

    public function history()
    {
        $db = Database::connect();
        $req = $this->request;
        $q = trim((string) $req->getGet('q'));

        $params = [];
        $where = '';
        if ($q !== '') {
            $like = '%' . $q . '%';
            $where = 'WHERE s.student_id LIKE ? OR s.first_name LIKE ? OR s.last_name LIKE ? OR s.name_ar LIKE ? OR s.parent_name LIKE ? OR s.parent_iqama LIKE ? OR s.parent_phone LIKE ?';
            $params = [$like, $like, $like, $like, $like, $like, $like];
        }

        $sql = "SELECT r.id, r.receipt_no, r.total, r.vat, r.grand_total, r.created_at,
                       s.student_id, s.first_name, s.last_name
                FROM receipts r
                JOIN students s ON s.id = r.student_id
                $where
                ORDER BY r.id DESC
                LIMIT 50";
        $rows = [];
        try { $rows = $db->query($sql, $params)->getResultArray(); } catch (\Throwable $e) { $rows = []; }

        return view('payments/history', [
            'title' => 'Receipt History',
            'rows' => $rows,
            'query' => $q,
        ]);
    }

    private function tlv(int $tag, string $value): string
    {
        $length = strlen($value);
        return chr($tag) . chr($length) . $value;
    }

    private function buildQrPayload(string $seller, string $vatNumber, string $isoDate, $totalWithVat, $vatAmount): string
    {
        $tlv = $this->tlv(1, $seller)
            . $this->tlv(2, $vatNumber)
            . $this->tlv(3, $isoDate)
            . $this->tlv(4, number_format((float) $totalWithVat, 2, '.', ''))
            . $this->tlv(5, number_format((float) $vatAmount, 2, '.', ''));
        return base64_encode($tlv);
    }
}