<?php

namespace App\Controllers\Owner;

use App\Controllers\BaseController;
use App\Models\ProductionQueueModel;
use App\Models\ProductionQueueHistoryModel;
use App\Models\OrderModel;
use App\Models\CompanySettingModel;
use App\Services\MonthlyPoScheduler;

class Production extends BaseController
{
    protected $queue;
    protected $history;
    protected $order;
    protected $setting;

    public function __construct()
    {
        helper(['form', 'url']);
        $this->queue   = new ProductionQueueModel();
        $this->history = new ProductionQueueHistoryModel();
        $this->order   = new OrderModel();
        
        if (class_exists(\App\Models\CompanySettingModel::class)) {
            $this->setting = new CompanySettingModel();
        }
    }

    public function index()
    {
        $data = [
            'title' => 'Produksi',
            'queues' => $this->queue
                ->select("production_queue.*, orders.order_number, products.nama_product")
                ->join('orders', 'orders.id_order = production_queue.id_order', 'left')
                ->join('products', 'products.id_product = production_queue.id_product', 'left')
                ->orderBy('tanggal_produksi', 'ASC')
                ->findAll(),
            'waiting'   => $this->queue->where('status', 'antrian')->countAllResults(),
            'process'   => $this->queue->where('status', 'produksi')->countAllResults(),
            'completed' => $this->queue->where('status', 'selesai')->countAllResults()
        ];
        return view('owner/production/index', $data);
    }

    public function detail($id)
    {
        $queue = $this->queue->where('id_queue', $id)->first();
        if (!$queue) {
            return redirect()->to('/owner/production');
        }
        $history = $this->history->where('id_queue', $id)->orderBy('updated_at', 'DESC')->findAll();
        return view('owner/production/detail', [
            'title'   => 'Detail Produksi',
            'queue'   => $queue,
            'history' => $history
        ]);
    }

    public function waiting($id)
    {
        $queue = $this->queue->find($id);
        if (!$queue) return redirect()->back();

        $this->queue->update($id, ['status' => $this->queue->normalizeQueueStatus('waiting')]);
        $this->history->insert([
            'id_queue'       => $id,
            'status_sebelum' => $queue['status'],
            'status_sesudah' => $this->queue->normalizeQueueStatus('waiting'),
            'updated_at'     => date('Y-m-d H:i:s')
        ]);
        return redirect()->back()->with('success', 'Queue Waiting.');
    }

    public function process($id)
    {
        $queue = $this->queue->find($id);
        if (!$queue) return redirect()->back();

        if ($this->isFutureBatch($queue)) {
            return redirect()->back()->with('error', 'Batch ini dijadwalkan pada ' . date('m/Y', strtotime($queue['tanggal_produksi'])) . ' dan belum dapat diproses.');
        }

        $this->queue->update($id, ['status' => $this->queue->normalizeQueueStatus('process')]);
        $this->order->update($queue['id_order'], ['production_status' => $this->order->normalizeProductionStatus('process')]);
        $this->history->insert([
            'id_queue'       => $id,
            'status_sebelum' => $queue['status'],
            'status_sesudah' => 'produksi',
            'updated_at'     => date('Y-m-d H:i:s')
        ]);
        return redirect()->back()->with('success', 'Produksi Diproses.');
    }

    public function finish($id)
    {
        $queue = $this->queue->find($id);
        if (!$queue) return redirect()->back();

        if ($this->isFutureBatch($queue)) {
            return redirect()->back()->with('error', 'Batch ini belum memasuki bulan produksi.');
        }

        $this->queue->update($id, ['status' => $this->queue->normalizeQueueStatus('completed'), 'qty_sisa' => 0]);
        $this->history->insert([
            'id_queue'       => $id,
            'status_sebelum' => $queue['status'],
            'status_sesudah' => 'selesai',
            'updated_at'     => date('Y-m-d H:i:s')
        ]);
        $this->syncOrderProductionStatus((int) $queue['id_order']);
        return redirect()->back()->with('success', 'Produksi Selesai.');
    }

    public function cancel($id)
    {
        $queue = $this->queue->find($id);
        if (!$queue) return redirect()->back();

        // Enum database tidak memiliki status cancel; kembalikan ke antrian agar tidak ada data rusak.
        $this->queue->update($id, ['status' => $this->queue->normalizeQueueStatus('waiting')]);
        $this->history->insert([
            'id_queue'       => $id,
            'status_sebelum' => $queue['status'],
            'status_sesudah' => $this->queue->normalizeQueueStatus('waiting'),
            'updated_at'     => date('Y-m-d H:i:s')
        ]);
        return redirect()->back()->with('success', 'Queue Dibatalkan.');
    }

    public function history()
    {
        $history = $this->history->orderBy('updated_at', 'DESC')->findAll();
        return view('owner/production/history', [
            'title'   => 'History Produksi',
            'history' => $history
        ]);
    }

    public function limit()
    {
        return view('owner/production/limit', [
            'title'   => 'Limit PO Bulanan',
            'setting' => $this->setting ? $this->setting->first() : []
        ]);
    }

    public function saveLimit()
    {
        $limit = (int) $this->request->getPost('monthly_po_limit');
        $setting = $this->setting->first();
        $db = \Config\Database::connect();
        $db->transBegin();

        try {
            if ($setting) {
                $this->setting->update($setting['id_setting'], ['monthly_po_limit' => $limit]);
            } else {
                $this->setting->insert(['monthly_po_limit' => $limit]);
            }

            (new MonthlyPoScheduler($db))->rebalance($limit);
            if ($db->transStatus() === false) {
                throw new \RuntimeException('Gagal menyimpan perubahan limit.');
            }
            $db->transCommit();
        } catch (\Throwable $e) {
            $db->transRollback();

            return redirect()->back()->with('error', $e->getMessage());
        }

        return redirect()->back()->with('success', 'Limit berhasil diubah dan batch PO telah disesuaikan.');
    }

    private function isFutureBatch(array $queue): bool
    {
        $scheduled = $queue['tanggal_produksi'] ?? null;

        return $scheduled && date('Y-m-01', strtotime($scheduled)) > date('Y-m-01');
    }

    private function syncOrderProductionStatus(int $orderId): void
    {
        $remaining = $this->queue
            ->where('id_order', $orderId)
            ->where('status !=', 'selesai')
            ->countAllResults();

        $this->order->update($orderId, [
            'production_status' => $this->order->normalizeProductionStatus($remaining === 0 ? 'completed' : 'process'),
            'order_status' => $remaining === 0 ? 'completed' : 'production',
        ]);
    }
}
