<?php

namespace App\Controllers\Admin;

use App\Controllers\BaseController;
use App\Models\OrderModel;
use App\Models\PaymentModel;
use App\Models\PaymentMethodModel;
use App\Models\OrderItemModel;
use App\Services\NotificationService;
use App\Services\InvoiceService;
use App\Controllers\Admin\ProductionController;

class PaymentController extends BaseController
{
    protected OrderModel $orderModel;
    protected PaymentModel $paymentModel;
    protected PaymentMethodModel $paymentMethodModel;
    protected OrderItemModel $itemModel;

    public function __construct()
    {
        helper(['form','url']);

        $this->orderModel         = new OrderModel();
        $this->paymentModel       = new PaymentModel();
        $this->paymentMethodModel = new PaymentMethodModel();
        $this->itemModel          = new OrderItemModel();
    }

    public function index()
    {
        $data = [

            'title' => 'Pembayaran',

            'payments' => $this->paymentModel
                ->select('
                    payments.*,
                    orders.order_number,
                    orders.customer_name,
                    payment_methods.nama_metode
                ')
                ->join(
                    'orders',
                    'orders.id_order=payments.id_order'
                )
                ->join(
                    'payment_methods',
                    'payment_methods.id_payment_method=payments.id_payment_method',
                    'left'
                )
                ->orderBy('payments.id_payment','DESC')
                ->findAll()

        ];

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

    public function create($orderId)
{
        $order = $this->orderModel->find($orderId);

        if(!$order){

            return redirect()
                ->to('/admin/orders');

        }

        $data=[

            'title'=>'Tambah Pembayaran',

            'order'=>$order,

            'methods'=>$this->paymentMethodModel->active()

        ];

        return view('admin/payments/create',$data);
    }

    public function store()
    {
        $db=\Config\Database::connect();

        $db->transBegin();

        try{

            $orderId=(int)$this->request->getPost('id_order');
            $amount=(float)$this->request->getPost('jumlah_bayar');
            $methodId=(int) $this->request->getPost('id_payment_method');

            $result = $this->recordPayment($orderId, $amount, $methodId);

            $db->transCommit();

            return redirect()->to('/admin/orders/show/'.$orderId)->with(
                'success',
                'Pembayaran berhasil dicatat. Invoice sudah dibuat dan dapat dikirim dari detail order.'
            );

        }catch(\Throwable $e){

            $db->transRollback();

            return redirect()->back()

                ->withInput()

                ->with('error',$e->getMessage());

        }

    }

    public function recordPayment(int $orderId, float $amount, int $methodId, string $status = 'verified'): array
    {
        $order=$this->orderModel->find($orderId);
        $method=$this->paymentMethodModel->find($methodId);

        if (! $order || ! $method || ! $method['is_active']) {
            throw new \RuntimeException('Order atau metode pembayaran tidak valid.');
        }

        $totalPaid = $this->paymentModel->getTotalPaid($orderId);
        $remaining = max(0, (float) $order['total'] - $totalPaid);

        if ($amount <= 0 || $amount > $remaining) {
            throw new \RuntimeException('Jumlah pembayaran harus lebih dari nol dan tidak boleh melebihi sisa tagihan.');
        }

        $db = \Config\Database::connect();
        $db->table('payments')->insert([
            'id_order'          => $orderId,
            'id_payment_method' => $methodId,
            'tanggal_bayar'     => date('Y-m-d H:i:s'),
            'jumlah_bayar'      => $amount,
            'status'            => $status,
            'created_at'        => date('Y-m-d H:i:s'),
        ]);

        $this->orderModel->update($orderId, [
            'payment_method' => $method['kode'] ?? 'cash',
        ]);

        $this->syncOrderPaymentState($orderId);

        $order=$this->orderModel->find($orderId);
        $invoiceService = new InvoiceService();
        $invoice = $invoiceService->syncForOrder($order);
        // reload to include timestamps and other fields
        $invoice = $invoiceService->findByOrder((int) $orderId) ?? $invoice;

        // PO yang sudah berstatus production langsung muncul pada daftar produksi.
        if (($order['order_type'] ?? null) === 'po' && ($order['order_status'] ?? null) === 'production') {
            $productionController = new ProductionController();
            $productionController->createProductionFromOrder($orderId, $order['target_date'] ?? null);
        }


        // Notifikasi sengaja tidak dikirim di sini. SMTP, Dompdf, dan Fonnte dapat
        // menunggu puluhan detik sehingga tidak boleh menahan proses pembayaran.
        // Admin dapat mengirim invoice lewat tombol "Kirim invoice" setelahnya.
        return ['order' => $order, 'invoice' => $invoice];
    }

    /** Re-send the current invoice without creating another payment. */
    public function sendInvoice(int $orderId)
    {
        $order = $this->orderModel->find($orderId);
        if (! $order) {
            return redirect()->back()->with('error', 'Order tidak ditemukan.');
        }

        $invoice = (new InvoiceService())->syncForOrder($order);
        $result = (new NotificationService())->sendOrderNotifications($order, $invoice);
        $channels = array_filter([
            ! empty($result['whatsapp']) ? 'WhatsApp' : null,
        ]);
        $failureReason = ! empty($result['errors']) ? ' ' . implode(' ', array_unique($result['errors'])) : '';

        return redirect()->to('/admin/orders/show/' . $orderId)->with(
            $channels ? 'success' : 'error',
            $channels ? 'Notifikasi invoice berhasil dikirim via WhatsApp.' : 'Invoice dibuat, tetapi notifikasi WhatsApp tidak berhasil dikirim.' . $failureReason
        );
    }

    /** Render invoice PDF HTML in browser (no notifications). */
    public function viewInvoice(int $orderId)
    {
        $order = $this->orderModel->find($orderId);
        if (! $order) {
            return redirect()->back()->with('error', 'Order tidak ditemukan.');
        }

        $invoice = (new InvoiceService())->syncForOrder($order);
        $items = $this->itemModel->getItems($orderId);
        $payments = (new \App\Models\PaymentModel())->getByOrder($orderId);

        return view('admin/orders/invoice_pdf', [
            'order' => $order,
            'invoice' => $invoice,
            'items' => $items,
            'payments' => $payments,
        ]);
    }

    protected function syncOrderPaymentState(int $orderId): void
    {
        $order = $this->orderModel->find($orderId);

        if (!$order) {
            return;
        }

        $paidAmount = $this->paymentModel->getTotalPaid($orderId);
        $remainingAmount = $this->orderModel->calculateRemaining((float) $order['total'], $paidAmount);
        $paymentStatus = $this->orderModel->calculatePaymentStatus((float) $order['total'], $paidAmount);

        $currentStatus = $order['order_status'] ?? 'waiting_payment';

        if ($currentStatus === 'draft' || $currentStatus === 'waiting_payment') {
            if ($paidAmount <= 0) {
                $currentStatus = 'waiting_payment';
            } elseif ($order['order_type'] === 'po') {
                $currentStatus = 'production';
            } else {
                $currentStatus = 'completed';
            }
        }

        $this->orderModel->update($orderId, [
            'paid_amount'      => $paidAmount,
            'remaining_amount' => $remainingAmount,
            'payment_status'   => $paymentStatus,
            'order_status'     => $currentStatus,
        ]);
    }

    public function delete($id)
    {
        $payment=$this->paymentModel->find($id);

        if(!$payment){

            return redirect()->back();

        }

        $orderId=$payment['id_order'];
        $db = \Config\Database::connect();
        $db->transBegin();
        try {
        $this->paymentModel->delete($id);

        $this->syncOrderPaymentState($orderId);
        $db->transCommit();
        } catch (\Throwable $e) {
            $db->transRollback();
            return redirect()->back()->with('error', $e->getMessage());
        }

        return redirect()

            ->back()

            ->with('success','Pembayaran dihapus.');

    }
}
