<?php
namespace App\Controllers;

use App\Core\Controller;
use App\Core\Database;
use App\Core\Dates;
use App\Core\Flash;
use App\Core\Request;
use App\Core\Response;
use App\Core\Settings;
use App\Services\ApprovalService;
use App\Services\ExportService;

/** Inbox & riwayat persetujuan. */
class ApprovalController extends Controller
{
    protected string $module = 'persetujuan';

    private function filters(): array
    {
        $f = [];
        foreach (['status', 'module', 'cari'] as $k) { $v = trim((string)Request::get($k, '')); if ($v !== '') $f[$k] = $v; }
        foreach (['dari', 'sampai'] as $k) { $d = Request::date($k); if ($d) $f[$k] = $d; }
        return $f;
    }

    public function index(): void
    {
        $f = $this->filters();
        [$page, $per] = $this->pageParams();
        $db = Database::i();
        $this->view('persetujuan/index', [
            'judul' => 'Persetujuan',
            'subjudul' => 'Permintaan persetujuan transaksi finansial',
            'p' => ApprovalService::listing($f, $page, $per), 'filters' => $f,
            'flows' => ApprovalService::flows(),
            'stat' => $db->one("SELECT SUM(status='pending') menunggu, SUM(status='approved') disetujui,
                                       SUM(status='rejected') ditolak, COUNT(*) total,
                                       COALESCE(SUM(CASE WHEN status='pending' THEN amount END),0) nilai_menunggu
                                  FROM approval_requests"),
        ]);
    }

    public function show(array $params): void
    {
        $id = (int)($params['id'] ?? 0);
        $r = ApprovalService::find($id);
        if (!$r) Response::abort(404, 'Permintaan persetujuan tidak ditemukan.');

        $entity = null;
        $db = Database::i();
        switch ($r['entity_type']) {
            case 'payment':
                $entity = $db->one('SELECT p.*, c.name AS customer_name FROM payments p
                                     LEFT JOIN customers c ON c.id=p.customer_id WHERE p.id=:id', ['id' => (int)$r['entity_id']]);
                break;
            case 'invoice':
                $entity = (new \App\Models\Invoice())->findFull((int)$r['entity_id']);
                break;
            case 'invoice_revision':
                $entity = $db->one('SELECT r.*, rt.name AS jenis_revisi FROM invoice_revisions r
                                     LEFT JOIN revision_types rt ON rt.id=r.revision_type_id WHERE r.id=:id', ['id' => (int)$r['entity_id']]);
                break;
            case 'credit_note':
                $entity = $db->one('SELECT cn.*, i.invoice_no, c.name AS customer_name FROM credit_notes cn
                                     LEFT JOIN invoices i ON i.id=cn.invoice_id
                                     LEFT JOIN customers c ON c.id=i.customer_id WHERE cn.id=:id', ['id' => (int)$r['entity_id']]);
                break;
            case 'import_batch':
                $entity = $db->one('SELECT * FROM import_batches WHERE id=:id', ['id' => (int)$r['entity_id']]);
                break;
        }

        $this->view('persetujuan/detail', [
            'judul' => 'Persetujuan ' . $r['request_no'],
            'subjudul' => $r['title'],
            'r' => $r, 'entity' => $entity,
            'history' => ApprovalService::history($id),
            'payload' => arr($r['payload_json']),
        ]);
    }

    public function decide(array $params): void
    {
        $id = (int)($params['id'] ?? 0);
        $decision = (string)Request::post('keputusan', '');
        $notes = mb_substr(trim((string)Request::post('catatan', '')), 0, 1000);
        if (!in_array($decision, ['approved', 'rejected', 'cancelled'], true)) {
            Flash::error('Keputusan tidak valid.');
            $this->redirect('/persetujuan/' . $id);
        }
        if ($decision === 'rejected' && $notes === '') {
            Flash::error('Alasan penolakan wajib diisi.');
            $this->redirect('/persetujuan/' . $id);
        }
        try {
            $res = ApprovalService::decide($id, $decision, $notes);
            Flash::success($res['pesan']);
        } catch (\Throwable $e) {
            Flash::error('Keputusan gagal diproses: ' . $e->getMessage());
        }
        $this->redirect('/persetujuan/' . $id);
    }

    public function export(): void
    {
        $f = $this->filters();
        $p = ApprovalService::listing($f, 1, Settings::int('laporan.maks_baris_export', 50000));
        ExportService::send((string)Request::get('format', 'xlsx'), [
            'judul' => 'DAFTAR PERMINTAAN PERSETUJUAN',
            'tanggal_lapor' => Dates::fmt(Dates::today()),
            'nama_berkas' => 'persetujuan', 'sheet' => 'Persetujuan', 'orientasi' => 'landscape',
        ], [
            ['label' => 'No. Permintaan', 'key' => 'request_no',        'type' => 'text'],
            ['label' => 'Tanggal',        'key' => 'created_at',        'type' => 'text'],
            ['label' => 'Modul',          'key' => 'module',            'type' => 'text'],
            ['label' => 'Aksi',           'key' => 'action',            'type' => 'text'],
            ['label' => 'Judul',          'key' => 'title',             'type' => 'text', 'width' => 50, 'pdf_width' => 3],
            ['label' => 'Nilai',          'key' => 'amount',            'type' => 'money'],
            ['label' => 'Diajukan Oleh',  'key' => 'requested_by_name', 'type' => 'text'],
            ['label' => 'Status',         'key' => 'status',            'type' => 'text'],
            ['label' => 'Diputuskan Oleh','key' => 'decided_by_name',   'type' => 'text'],
            ['label' => 'Tgl Keputusan',  'key' => 'decided_at',        'type' => 'text'],
            ['label' => 'Catatan',        'key' => 'notes',             'type' => 'text', 'width' => 45, 'pdf_width' => 2.4],
        ], $p['data']);
    }
}
