<?php
namespace App\Controllers;

use App\Models\Hargamodel;
use App\Models\Mejamodel;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;

use CodeIgniter\API\ResponseTrait;
use App\Models\Ordermodel;
use App\Models\Orderdetailmodel;
use App\Models\Pajakmodel;
use App\Models\Transaksimodel;

use Dompdf\Dompdf;
use Dompdf\Options;

class Order extends BaseController
{
    use ResponseTrait;

    private $user;

    public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger) 
    {
        parent::initController($request, $response, $logger);
        $this->user = service("user_data");
    }

    private function check_access(){
        $user = service("user_data");
        if($user->data->group != 'admin'){
            return false;
        }else{
            return true;
        }
    }

    public function index(){
        $data['user'] = $this->user->data;
        $mejamodel = new Mejamodel();
        $builder = $mejamodel->builder();
        $data['meja'] = $builder->get()->getResult();

        return view('admin/order/index',$data);
    }

    public function pesanan($id){
        $data['user'] = $this->user->data;
        $mejamodel = new Mejamodel();
        $builder = $mejamodel->builder();
        $data['meja'] = $builder->where("id_meja",$id)->get()->getRow();
        
        $ordermodel = new Ordermodel();
        $builder = $ordermodel->builder("vorder");
        $builder->where("id_meja",$id);
        $builder->where("status_order","open");
        $order = $builder->get()->getRow();
        if($order){
            $data['emode'] = '1';
            $data['order'] = $order;
            $orderdetailmodel = new Orderdetailmodel();
            $builder = $orderdetailmodel->builder("vorderdetail");
            $data['order_detail'] = $builder->where("id_order",$order->id_order)->get()->getResult();
        }else{
            $data['emode'] = '0';
        }

        return view('admin/order/pesanan',$data);
    }

    public function list_products(){
        $db = db_connect();
        $q     = $this->request->getGet('q') ?? '';
        $page  = max(1, (int) $this->request->getGet('page'));
        $limit = max(1, (int) $this->request->getGet('limit'));
        $offset = ($page - 1) * $limit;
        
        $builder = $db->table('vproduk');
        if ($q !== '') {
            $builder->groupStart()
                    ->like('nama_produk', $q)
                    ->orLike('kode_produk', $q)
                    ->groupEnd();
        }

        $total = $builder->countAllResults(false); // tidak reset query
        $builder->orderBy('nama_produk', 'ASC')
                ->limit($limit, $offset);
        $query = $builder->get();

        $data = $query->getResultArray();

        return $this->response->setJSON([
            'data' => $data,
            'page' => $page,
            'per_page' => $limit,
            'total' => $total
        ]);
    }

    public function save_order()
    {
        $data = array();
        $data['status'] = 'success';
        $user = $this->user->data;

        $json_request = $this->request->getJson();

        $id_order = $json_request->id_order;
        $emode = $json_request->emode;
        $items = $json_request->items;
        $kode = $json_request->kode_order;

        $request = [
            'id_meja' => $json_request->id_meja,
            'tanggal_order' => $json_request->tanggal_order,
        ];

        $validation = \Config\Services::validation();
        $validation->setRule('id_meja', 'Meja', 'required');

        if (!$validation->run($request)) {
            return $this->fail($validation->getErrors(),400,null,'input');
        }else{
            $mejamodel = new Mejamodel();
            $mejamodel->db->transBegin();

            $orderdetailmodel = new Orderdetailmodel();
            $orderdetailmodel->db->transBegin();

            $ordermodel = new Ordermodel();
            $ordermodel->db->transBegin();
            if(empty($id_order)){
                $builder = $mejamodel->builder();
                $builder->where("id_meja",$request["id_meja"]);
                $builder->where("status", "kosong");
                $meja = $builder->get()->getRow();
                if($meja){
                    $request['id_operator'] = $user->id_user;
                    if(empty($kode)){
                        $tahunbulan = date("Ym");
                        $kode = $ordermodel->getNewKode($tahunbulan);
                        if(empty($kode)){
                            return $this->fail(["error" => "Generate Kode Error!"],400,null,'db');
                        }
                    }

                    $request['kode_order'] = $kode;
                    $id_order = $ordermodel->insert($request,true);
                    if($ordermodel->db->transStatus() === false){
                        $ordermodel->db->transRollback();
                        return $this->fail(["error" => "Database Error Order!"],400,null,'db');
                    }

                    $mejamodel->update($meja->id_meja,["status" => "terisi"]);
                    if($mejamodel->db->transStatus() === false){
                        $ordermodel->db->transRollback();
                        $mejamodel->db->transRollback();
                        return $this->fail(["error" => "Database Error!"],400,null,'db');
                    }
                }
            }else{
                $builder = $ordermodel->builder();
                $builder->where("id_order",$id_order);
                // $builder->where("status_order","open");
                $order = $builder->get()->getRow();
                if(!$order){
                    return $this->fail(["error" => "Invalid Order! Order sudah di closed!"],400,null,'db');
                }

                if(empty($kode)){
                    $tahunbulan = date("Ym");
                    $kode = $ordermodel->getNewKode($tahunbulan);
                    if(empty($kode)){
                        return $this->fail(["error" => "Generate Kode Error!"],400,null,'db');
                    }
                }

                $request['kode_order'] = $kode;
                $ordermodel->update($id_order, $request);
                if($ordermodel->db->transStatus() === false){
                    $ordermodel->db->transRollback();
                    return $this->fail(["error" => "Database Error Order!"],400,null,'db');
                }
            }

            $builder = $orderdetailmodel->builder();
            $builder->where("id_order",$id_order);
            $builder->delete();
            foreach($items as $item){
                $hargamodel = new Hargamodel();
                $builder = $hargamodel->builder();
                $harga = $builder->where("id_harga",$item->id_harga)->get()->getRow();
                if(!$harga){
                    $ordermodel->db->transRollback();
                    $mejamodel->db->transRollback();
                    $orderdetailmodel->db->transRollback();
                    return $this->fail(["error" => "Invalid Harga!"],400,null,'db');
                }

                $q = [
                    "id_order" => $id_order,
                    "id_produk" => $item->id_produk,
                    "id_harga" => $item->id_harga,
                    "harga_modal" => $harga->harga_modal,
                    "harga_jual" => $harga->harga_jual,
                    "qty" => $item->qty,
                    "subtotal" => ($item->qty * $harga->harga_jual)
                ];

                $orderdetailmodel->insert($q);
                if($mejamodel->db->transStatus() === false){
                    $ordermodel->db->transRollback();
                    $mejamodel->db->transRollback();
                    $orderdetailmodel->db->transRollback();
                    return $this->fail(["error" => "Items Insert Failed!"],400,null,'db');
                }
            }

            $ordermodel->db->transCommit();
            $mejamodel->db->transCommit();
            $orderdetailmodel->db->transCommit();

            $data['id_order'] = $id_order;
            return $this->respond($data,200);
        }
    }

    public function cancel_order()
    {
        $data = array();
        $data['status'] = 'success';
        $user = $this->user->data;

        $json_request = $this->request->getJson();

        $id_order = $json_request->id_order;
        // $emode = $json_request->emode;
        $items = $json_request->items;

        $request = [
            'id_meja' => $json_request->id_meja,
            'tanggal_order' => $json_request->tanggal_order,
        ];

        $validation = \Config\Services::validation();
        $validation->setRule('id_meja', 'Meja', 'required');

        if (!$validation->run($request)) {
            return $this->fail($validation->getErrors(),400,null,'input');
        }else{
            $mejamodel = new Mejamodel();
            $mejamodel->db->transBegin();

            $ordermodel = new Ordermodel();
            $ordermodel->db->transBegin();

            $builder = $ordermodel->builder();
            $builder->where("id_order",$id_order);
            $order = $builder->get()->getRow();
            if(!$order){
                return $this->fail(["error" => "Invalid Order! Silahkan lakukan simpan order terlebih dahulu..."],400,null,'db');
            }
            $ordermodel->update($order->id_order,["status_order" => "canceled"]);

            $builder = $mejamodel->builder();
            $builder->where("id_meja",$request["id_meja"]);
            $builder->where("status", "terisi");
            $meja = $builder->get()->getRow();
            if($meja){
                $ordermodel2 = new Ordermodel();
                $builder2 = $ordermodel2->builder();
                $builder2->where("id_order!=",$id_order);
                $builder2->where("id_meja",$request['id_meja']);
                $builder2->where("status_order","open");
                $order2 = $builder2->get()->getRow();
                if(!$order2){
                    $mejamodel->update($meja->id_meja,["status" => "kosong"]);
                    if($mejamodel->db->transStatus() === false){
                        $mejamodel->db->transRollback();
                        return $this->fail(["error" => "Database Error!"],400,null,'db');
                    }
                }
            }

            $transaksimodel = new Transaksimodel();
            $transaksimodel->db->transBegin();
            $builder = $transaksimodel->builder();
            $builder->where("id_order",$order->id_order);
            $builder->where("status","closed");
            $transaksi = $builder->get()->getRow();
            if($transaksi){
                $transaksimodel->update($transaksi->id_transaksi,["status" => "canceled"]);
                if($transaksimodel->db->transStatus() === false){
                    $ordermodel->db->transRollback();
                    $mejamodel->db->transRollback();
                    return $this->fail(["error" => "DB Error! Transaction update.."],400,null,'db');
                }
            }
            $ordermodel->db->transCommit();
            $mejamodel->db->transCommit();
            $transaksimodel->db->transCommit();

            $data['id_order'] = $id_order;
            return $this->respond($data,200);
        }
    }

    public function checkout($id_order){
        $data['user'] = $this->user->data;
        $ordermodel = new Ordermodel();
        $builder = $ordermodel->builder("vorder");
        $builder->where("id_order",$id_order);
        $order = $builder->get()->getRow();
        if(!$order){
            $data['error'] = "Order not found!";
            return view('admin/order/checkout_error',$data);
        }

        $mejamodel = new Mejamodel();
        $builder = $mejamodel->builder();
        $data['meja'] = $builder->where("id_meja",$order->id_meja)->get()->getRow();

        $pajakmodel = new Pajakmodel();
        $builder = $pajakmodel->builder();
        $builder->where("status","aktif");
        $builder->orderBy("updated_at","DESC");
        $builder->limit(1);
        $data['pajak'] = $builder->get()->getRow();

        $data['order'] = $order;

        return view('admin/order/checkout',$data);
    }

    public function get_order_items($id_order){
        $orderdetailmodel = new Orderdetailmodel();
        $builder = $orderdetailmodel->builder("vorderdetail");
        $builder->where("id_order", $id_order);
        $orderdetail = $builder->get()->getResultArray();

        $transaksimodel = new Transaksimodel();
        $builder = $transaksimodel->builder("vtransaksi");
        $builder->where("id_order",$id_order);
        $builder->where("status","closed");
        $transaksi = $builder->get()->getRow();
        
        $data_transaksi = [
            "id_transaksi" => "0",
            "diskon_nominal" => 0,
            "diskon_persen" => 0,
            "pajak_persen" => 0,
            "service_persen" => 0,
            "pembulatan" => "0",
            "tunai" => 0,
            "metode" => "cash"
        ];

        if($transaksi){
            $data_transaksi = [
                "id_transaksi" => $transaksi->id_transaksi,
                "diskon_nominal" => $transaksi->diskon_nominal,
                "diskon_persen" => $transaksi->diskon_persen,
                "pajak_persen" => $transaksi->pajak_persen,
                "service_persen" => $transaksi->service_persen,
                "pembulatan" => $transaksi->pembulatan,
                "tunai" => $transaksi->tunai,
                "metode" => $transaksi->metode
            ];
        }else{
            $pajakmodel = new Pajakmodel();
            $builder = $pajakmodel->builder();
            $builder->where("status","aktif");
            $builder->orderBy("updated_at","DESC");
            $builder->limit(1);
            $pajak = $builder->get()->getRow();
            if($pajak){
                $data_transaksi['pajak_persen'] = $pajak->persen;
            }
        }
        return $this->response->setJSON([
            'items' => $orderdetail,
            'transaksi' => $data_transaksi
        ]);
    }

    public function checkout_submit()
    {
        $data = array();
        $data['status'] = 'success';
        $user = $this->user->data;

        $json_request = $this->request->getJson();

        $id_order = $json_request->id_order;
        $subtotal = $json_request->summary->subtotal;
        $diskon_persen = $json_request->summary->diskon_persen;
        $diskon_nominal = $json_request->summary->diskon_nominal;
        $diskon_total = $json_request->summary->diskon_total;
        $pajak_persen = $json_request->summary->pajak_persen;
        $pajak_nominal = $json_request->summary->pajak_nominal;
        $service_persen = $json_request->summary->service_persen;
        $service_nominal = $json_request->summary->service_nominal;
        $pembulatan = $json_request->summary->pembulatan_step;
        $grand_total = $json_request->summary->grand_total;

        $metode = $json_request->payment->method;
        $metode_ref = $json_request->payment->reference;
        $tunai = $json_request->payment->bayar_tunai;
        $kembalian = $json_request->payment->kembalian;

        if ($metode=="cash" && ($tunai<$grand_total)) {
            return $this->fail(["error" => "Jumlah bayar tidak sesuai!"],400,null,'data');
        }else{
            $ordermodel = new Ordermodel();
            $ordermodel->db->transBegin();

            $transaksimodel = new Transaksimodel();
            $transaksimodel->db->transBegin();

            $builder = $ordermodel->builder("vorder");
            $builder->where("id_order",$id_order);
            $builder->where("status_order","open");
            $order = $builder->get()->getRow();
            if(!$order){
                return $this->fail(["error" => "Order sudah di closed/canceled! Silahkan Periksa Kembali"],400,null,'data');
            }

            $builder = $transaksimodel->builder("vtransaksi");
            $builder->where("id_order",$id_order);
            $builder->where("status","closed");
            $transaksi = $builder->get()->getRow();
            if($transaksi){
                return $this->fail(["error" => "Transaksi sudah di closed! Silahkan Periksa Kembali atau Batalkan Transaksi terlebih dahulu.."],400,null,'data');
            }

            $total_modal = 0;
            $total_jual = 0;
            $total_bayar = 0;

            $orderdetailmodel = new Orderdetailmodel();
            $builder = $orderdetailmodel->builder("vorderdetail");
            $builder->where("id_order", $id_order);
            $orderdetail = $builder->get()->getResult();
            foreach($orderdetail as $detail){
                $total_modal += ($detail->harga_modal * $detail->qty);
                $total_jual += ($detail->harga_jual * $detail->qty);
                $total_bayar += (($detail->harga_jual * $detail->qty) - ($detail->harga_jual * $detail->qty));
            }

            $insert_transaksi = [
                "id_order" => $id_order,
                "tanggal_transaksi" => date("Y-m-d H:i:s"),
                "total_modal" => $total_modal,
                "total_jual" => $total_jual,
                "total_bayar" => $total_bayar,
                "tunai" => $tunai,
                "kembalian" => $kembalian,
                "metode" => $metode,
                "metode_ref" => $metode_ref,
                "id_operator" => $user->id_user,
                "diskon_persen" => $diskon_persen,
                "diskon_nominal" => $diskon_nominal,
                "diskon_total" => $diskon_total,
                "pajak_persen" => $pajak_persen,
                "pajak_nominal" => $pajak_nominal,
                "service_persen" => $service_persen,
                "service_nominal" => $service_nominal,
                "pembulatan" => $pembulatan,
                "grand_total" => $grand_total,
                "status" => "closed"
            ];

            $id_transaksi = $transaksimodel->insert($insert_transaksi);
            if($transaksimodel->db->transStatus() === false){
                return $this->fail(["error" => "DB Error Transaksi"],400,null,'data');
            }

            $ordermodel->update($id_order,["status_order" => "closed", "checkout_at" => date("Y-m-d H:i:s")]);
            if($ordermodel->db->transStatus() === false){
                return $this->fail(["error" => "DB Error Order"],400,null,'data');
            }

            $mejamodel = new Mejamodel();
            $mejamodel->db->transBegin();
            $mejamodel->update($order->id_meja,["status" => "kosong"]);
            if($mejamodel->db->transStatus() === false){
                return $this->fail(["error" => "DB Error Meja"],400,null,'data');
            }

            $ordermodel->db->transCommit();
            $transaksimodel->db->transCommit();
            $mejamodel->db->transCommit();

            $data['id_transaksi'] = $id_transaksi;
            return $this->respond($data,200);
        }
    }

    public function print_struk($id_order){
        $data = array();
        $data['status'] = 'success';
        $user = $this->user->data;

        $ordermodel = new Ordermodel();
        $builder = $ordermodel->builder("vorder");
        $builder->where("id_order", $id_order);
        $order = $builder->get()->getRow();
        if(!$order){
            die("Order not found!");
        }

        $transaksimodel = new Transaksimodel();
        $builder = $transaksimodel->builder("vtransaksi");
        $builder->where("id_order", $id_order);
        $builder->where("status", "closed");
        $transaksi = $builder->get()->getRow();
        if(!$transaksi){
            die("Transaksi not found!");
        }

        $dibayar = 0;
        $kembalian = 0;
        if($transaksi->metode == 'cash'){
            $dibayar = $transaksi->tunai;
            $kembalian = $transaksi->kembalian;
        }else{
            $dibayar = $transaksi->grand_total;
        }

        $order = [
            'kode'   => $order->kode_order,
            'meja'   => $order->nama_meja,
            'tanggal'=> date('Y-m-d H:i:s'),
            'kasir'  => $order->nama,
            'metode' => $transaksi->metode,
            'dibayar'=> $dibayar,
            'kembalian'=> $kembalian,
        ];

        $items = [];

        $subtotal = 0;

        $orderdetailmodel = new Orderdetailmodel();
        $builder = $orderdetailmodel->builder("vorderdetail");
        $builder->where("id_order", $id_order);
        $orderdetails = $builder->get()->getResult();
        foreach($orderdetails as $detail){
            $items[] = [
                'nama' => $detail->nama_produk,
                'qty' => $detail->qty,
                'harga' => $detail->harga_jual,
                'subtotal' => $detail->subtotal
            ];
            $subtotal += $detail->subtotal;
        }

        $total = [
            'subtotal'=>$subtotal,
            'diskon'=>$transaksi->diskon_total,
            'pajak'=>$transaksi->pajak_nominal,
            'grand_total'=>$transaksi->grand_total,
        ];

        $html = view('print/receipt_58mm', compact('order','items','total'));

        $opt = new Options();
        $opt->set('isHtml5ParserEnabled', true);
        $opt->set('defaultFont', 'DejaVu Sans');
        $pdf = new Dompdf($opt);
        $pdf->loadHtml($html, 'UTF-8');
        $pdf->setPaper([0,0,164,1000], 'portrait'); // 58mm
        $pdf->render();
        return $pdf->stream('struk-'.$order['kode'].'.pdf', ['Attachment'=>false]);
    }

    public function cancel_transaksi()
    {
        $data = array();
        $data['status'] = 'success';
        $user = $this->user->data;

        $json_request = $this->request->getJson();

        $id_transaksi = $json_request->id_transaksi;
        
        $ordermodel = new Ordermodel();
        $ordermodel->db->transBegin();
        $transaksimodel = new Transaksimodel();
        $transaksimodel->db->transBegin();
        $mejamodel = new Mejamodel();
        $mejamodel->db->transBegin();

        $builder = $transaksimodel->builder("vtransaksi");
        $builder->where("id_transaksi",$id_transaksi);
        $builder->where("status","closed");
        $transaksi = $builder->get()->getRow();
        if(!$transaksi){
            return $this->fail(["error" => "Invalid closed transaction! Silahkan Periksa Kembali"],400,null,'data');
        }

        $builder = $ordermodel->builder("vorder");
        $builder->where("id_order",$transaksi->id_order);
        $builder->where("status_order","closed");
        $order = $builder->get()->getRow();
        if(!$order){
            return $this->fail(["error" => "Invalid closed order! Silahkan Periksa Kembali"],400,null,'data');
        }

        $mejamodel->update($order->id_meja,["status" => "terisi"]);
        if($mejamodel->db->transStatus() === false){
            return $this->fail(["error" => "DB Error Meja"],400,null,'data');
        }

        $ordermodel->update($transaksi->id_order,["status_order" => "open", "checkout_at" => null]);
        if($ordermodel->db->transStatus() === false){
            return $this->fail(["error" => "DB Error Order"],400,null,'data');
        }

        $transaksimodel->update($id_transaksi,["status" => "canceled"]);
        if($transaksimodel->db->transStatus() === false){
            return $this->fail(["error" => "DB Error Order"],400,null,'data');
        }

        $mejamodel->db->transCommit();
        $ordermodel->db->transCommit();
        $transaksimodel->db->transCommit();
        
        return $this->respond($data,200);
    }

    public function riwayat()
    {
        $data['user'] = $this->user->data;
        return view('admin/order/riwayat',$data);
    }

    public function ajax_dt(){
        $data_post = [
            'draw' => $this->request->getPost('draw'),
            'columns' => $this->request->getPost('columns'),
            'order' => $this->request->getPost('order'),
            'start' => $this->request->getPost('start'),
            'length' => $this->request->getPost('length'),
            'search' => $this->request->getPost('search'),
            'searchBuilder' => $this->request->getPost('searchBuilder'),
        ];
        $DataModel = new Ordermodel();
        return $DataModel->GetDT($data_post,"");
    }

    public function view_riwayat($id){
        $data['user'] = $this->user->data;
        $ordermodel = new Ordermodel();
        $builder = $ordermodel->builder("vorder");
        $data['order'] = $builder->where("id_order",$id)->get()->getRow();
        
        if(!$data['order']){
            die('<h4>Invalid Data!</h4>');
        }

        $orderdetailmodel = new Orderdetailmodel();
        $builder = $orderdetailmodel->builder("vorderdetail");
        $data['order_detail'] = $builder->where("id_order",$data['order']->id_order)->get()->getResult();

        return view('admin/order/view_riwayat',$data);
    }
}
?>