<?php

namespace App\Controllers\Owner;

use App\Controllers\BaseController;
use App\Models\CategoryModel;
use App\Models\ProductModel;
use App\Models\SupplierModel;
use CodeIgniter\HTTP\ResponseInterface;

class Product extends BaseController
{
    protected ProductModel $product;
    protected SupplierModel $supplier;
    protected CategoryModel $category;

    public function __construct()
    {
        helper(['form', 'url']);
        $this->product  = new ProductModel();
        $this->supplier = new SupplierModel();
        $this->category = new CategoryModel();
    }

    /**
     * Halaman Utama / Daftar Produk Katalog
     */
    public function index()
    {
        $products = $this->product
            ->select('products.*, categories.nama_kategori, suppliers.nama_supplier')
            ->join('categories', 'categories.id_category = products.id_category', 'left')
            ->join('suppliers', 'suppliers.id_supplier = products.id_supplier', 'left')
            ->orderBy('products.id_product', 'DESC')
            ->findAll();

        return view('owner/product/index', [
            'title'    => 'Barang Center',
            'products' => $products
        ]);
    }

    /**
     * Form Tambah Produk Baru
     */
    public function create()
    {
        return view('owner/product/create', $this->formData('Tambah Barang'));
    }

    /**
     * Proses Simpan Produk Baru
     */
    public function store()
    {
        if (!$this->validateProduct()) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        $data = $this->productData();

        // Unggah Foto Produk jika ada
        $photo = $this->storePhoto();
        if ($photo === false) {
            return redirect()->back()->withInput()->with('error', 'Foto harus berupa JPG, PNG, atau WEBP dengan ukuran maksimal 5 MB.');
        }
        $data['product_photo'] = $photo;

        $db = \Config\Database::connect();
        $db->transStart();

        $this->product->insert($data);

        $db->transComplete();

        if ($db->transStatus() === false) {
            return redirect()->back()->withInput()->with('error', 'Gagal menyimpan data produk ke database.');
        }

        return redirect()->to('/owner/product')->with('success', 'Barang berhasil ditambahkan dan langsung tersedia di katalog.');
    }

    /**
     * Detail Spesifikasi Produk
     */
    public function detail($id = null)
    {
        if (empty($id)) {
            return redirect()->to('/owner/product')->with('error', 'ID Barang tidak valid.');
        }

        $product = $this->product
            ->select('products.*, categories.nama_kategori, suppliers.nama_supplier')
            ->join('categories', 'categories.id_category = products.id_category', 'left')
            ->join('suppliers', 'suppliers.id_supplier = products.id_supplier', 'left')
            ->where('products.id_product', $id)
            ->first();

        if (!$product) {
            return redirect()->to('/owner/product')->with('error', 'Barang tidak ditemukan.');
        }

        return view('owner/product/detail', [
            'title'   => 'Detail Barang',
            'product' => $product
        ]);
    }

    /**
     * Form Edit Produk
     */
    public function edit($id = null)
    {
        if (empty($id)) {
            return redirect()->to('/owner/product')->with('error', 'ID Barang tidak valid.');
        }

        $product = $this->product->find($id);
        if (!$product) {
            return redirect()->to('/owner/product')->with('error', 'Barang tidak ditemukan.');
        }

        return view('owner/product/edit', $this->formData('Edit Barang', $product));
    }

    /**
     * Proses Perbarui Data Produk
     */
    public function update($id = null)
    {
        if (empty($id)) {
            return redirect()->to('/owner/product')->with('error', 'ID Barang tidak valid.');
        }

        $product = $this->product->find($id);
        if (!$product) {
            return redirect()->to('/owner/product')->with('error', 'Barang tidak ditemukan.');
        }

        if (!$this->validateProduct()) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        $data = $this->productData();
        $photo = $this->storePhoto();

        if ($photo === false) {
            return redirect()->back()->withInput()->with('error', 'Foto harus berupa JPG, PNG, atau WEBP dengan ukuran maksimal 5 MB.');
        }

        // Hapus foto lama jika mengunggah foto baru
        if ($photo !== null) {
            $data['product_photo'] = $photo;
            $this->removePhoto($product['product_photo'] ?? null);
        }

        $db = \Config\Database::connect();
        $db->transStart();

        $this->product->update($id, $data);

        $db->transComplete();

        if ($db->transStatus() === false) {
            return redirect()->back()->withInput()->with('error', 'Gagal memperbarui data produk.');
        }

        return redirect()->to('/owner/product')->with('success', 'Barang berhasil diperbarui di katalog owner dan admin.');
    }

    /**
     * Hapus Produk
     */
    public function delete($id = null)
    {
        if (empty($id)) {
            return redirect()->to('/owner/product')->with('error', 'ID Barang tidak valid.');
        }

        $product = $this->product->find($id);
        if (!$product) {
            return redirect()->to('/owner/product')->with('error', 'Barang tidak ditemukan.');
        }

        $db = \Config\Database::connect();
        $db->transStart();

        $this->product->delete($id);

        $db->transComplete();

        if ($db->transStatus() === false) {
            return redirect()->to('/owner/product')->with('error', 'Gagal menghapus produk.');
        }

        // Hapus file fisik gambar jika bukan default
        $this->removePhoto($product['product_photo'] ?? null);

        return redirect()->to('/owner/product')->with('success', 'Barang berhasil dihapus.');
    }

    /**
     * AJAX Fast-Add Kategori (Opsional Langsung Dari Form Produk)
     * Mapped URI AutoRouter: owner/product/category-store-ajax
     */
    public function categoryStoreAjax(): ResponseInterface
    {
        if (!$this->request->isAJAX()) {
            return $this->response->setStatusCode(405)->setJSON(['success' => false, 'message' => 'Method Not Allowed']);
        }

        $namaKategori = trim((string) $this->request->getPost('nama_kategori'));

        if (empty($namaKategori)) {
            return $this->response->setJSON([
                'success'  => false,
                'message'  => 'Nama kategori wajib diisi.',
                'csrfHash' => csrf_hash()
            ]);
        }

        try {
            // Cek ketersediaan kategori
            $existing = $this->category->where('nama_kategori', $namaKategori)->first();
            if ($existing) {
                $id = $existing['id_category'];
            } else {
                $id = $this->category->insert(['nama_kategori' => $namaKategori]);
            }

            return $this->response->setJSON([
                'success'  => true,
                'message'  => 'Kategori berhasil ditambahkan.',
                'csrfHash' => csrf_hash(),
                'data'     => [
                    'id_category'   => $id,
                    'nama_kategori' => $namaKategori
                ]
            ]);
        } catch (\Throwable $e) {
            return $this->response->setJSON([
                'success'  => false,
                'message'  => 'Gagal menyimpan kategori.',
                'csrfHash' => csrf_hash()
            ]);
        }
    }

    /**
     * AJAX Fast-Add Supplier (Opsional Langsung Dari Form Produk)
     * Mapped URI AutoRouter: owner/product/supplier-store-ajax
     */
    public function supplierStoreAjax(): ResponseInterface
    {
        if (!$this->request->isAJAX()) {
            return $this->response->setStatusCode(405)->setJSON(['success' => false, 'message' => 'Method Not Allowed']);
        }

        $namaSupplier = trim((string) $this->request->getPost('nama_supplier'));

        if (empty($namaSupplier)) {
            return $this->response->setJSON([
                'success'  => false,
                'message'  => 'Nama supplier wajib diisi.',
                'csrfHash' => csrf_hash()
            ]);
        }

        try {
            // Cek ketersediaan supplier
            $existing = $this->supplier->where('nama_supplier', $namaSupplier)->first();
            if ($existing) {
                $id = $existing['id_supplier'];
            } else {
                $id = $this->supplier->insert(['nama_supplier' => $namaSupplier]);
            }

            return $this->response->setJSON([
                'success'  => true,
                'message'  => 'Supplier berhasil ditambahkan.',
                'csrfHash' => csrf_hash(),
                'data'     => [
                    'id_supplier'   => $id,
                    'nama_supplier' => $namaSupplier
                ]
            ]);
        } catch (\Throwable $e) {
            return $this->response->setJSON([
                'success'  => false,
                'message'  => 'Gagal menyimpan supplier.',
                'csrfHash' => csrf_hash()
            ]);
        }
    }

    /**
     * Helper Form Data
     */
    private function formData(string $title, ?array $product = null): array
    {
        return [
            'title'      => $title,
            'product'    => $product,
            'categories' => $this->category->orderBy('nama_kategori', 'ASC')->findAll(),
            'suppliers'  => $this->supplier->orderBy('nama_supplier', 'ASC')->findAll()
        ];
    }

    /**
     * Rules Validasi Produk
     */
    private function validateProduct(): bool
    {
        return $this->validate([
            'nama_product' => 'required|min_length[2]|max_length[255]',
            'harga'        => 'required|numeric|greater_than_equal_to[0]',
            'harga_modal'  => 'permit_empty|numeric|greater_than_equal_to[0]',
            'stok'         => 'permit_empty|integer|greater_than_equal_to[0]',
            // stock_type digunakan oleh alur order sebagai status ketersediaan,
            // bukan sebagai satuan stok.
            'stock_type'   => 'required|in_list[ready,po]',
            'id_category'  => 'permit_empty|integer|is_not_unique[categories.id_category]',
            'id_supplier'  => 'permit_empty', // Dibuat opsional
            'status'       => 'permit_empty|in_list[active,inactive]',
        ]);
    }

    /**
     * Mapping Input Post ke Array Model
     */
    private function productData(): array
    {
        // Kategori hanya dapat dipilih dari data kategori yang sudah ada.
        $idCategory = null;
        $catInput   = $this->request->getPost('id_category');
        if (!empty($catInput)) {
            $idCategory = (int) $catInput;
        }

        // 2. Penanganan Supplier (Opsional / Angka ID / Nama Teks Manual)
        $idSupplier    = null;
        $supplierInput = $this->request->getPost('id_supplier');
        if (!empty($supplierInput)) {
            if (is_numeric($supplierInput)) {
                $idSupplier = (int) $supplierInput;
            } else {
                // Jika diisi manual dengan string nama supplier baru
                $supplierName = trim((string) $supplierInput);
                $existing     = $this->supplier->where('nama_supplier', $supplierName)->first();
                if ($existing) {
                    $idSupplier = (int) $existing['id_supplier'];
                } else {
                    $idSupplier = (int) $this->supplier->insert(['nama_supplier' => $supplierName]);
                }
            }
        }

        $namaProduct = trim((string) $this->request->getPost('nama_product'));
        $stockType   = strtolower(trim((string) $this->request->getPost('stock_type'))) === 'po'
            ? 'po'
            : 'ready';

        return [
            'id_category'     => $idCategory,
            'id_supplier'     => $idSupplier,
            'owner_id'        => session('id_user') ?: null,
            'nama_product'    => $namaProduct,
            'description'     => $this->request->getPost('description') ?: null,
            'technical_notes' => $this->request->getPost('technical_notes') ?: null,
            'stock_type'      => $stockType,
            // Produk PO tidak memakai persediaan siap jual.
            'stok'            => $stockType === 'po' ? 0 : (int) ($this->request->getPost('stok') ?: 0),
            'harga'           => (float) ($this->request->getPost('harga') ?: 0),
            'harga_modal'     => (float) ($this->request->getPost('harga_modal') ?: 0),
            'is_custom'       => $this->request->getPost('is_custom') ? 1 : 0,
            'barcode'         => $this->request->getPost('barcode') ?: null,
            'sku'             => $this->request->getPost('sku') ?: null,
            'status'          => $this->request->getPost('status') ?: 'active',
            'jenis'           => $this->request->getPost('jenis') ?: $namaProduct,
        ];
    }

    /**
     * Helper Penyimpanan Foto Produk
     */
    private function storePhoto(): string|false|null
    {
        $photo = $this->request->getFile('product_photo');
        if (!$photo || $photo->getError() === UPLOAD_ERR_NO_FILE) {
            return null;
        }

        if (!$photo->isValid() || $photo->getSize() > 5 * 1024 * 1024) {
            return false;
        }

        $extension = strtolower($photo->getExtension());
        if (!in_array($extension, ['jpg', 'jpeg', 'png', 'webp'], true)) {
            return false;
        }

        $uploadPath = FCPATH . 'uploads/products';
        if (!is_dir($uploadPath)) {
            mkdir($uploadPath, 0755, true);
        }

        $name = $photo->getRandomName();
        $photo->move($uploadPath, $name);

        return $name;
    }

    /**
     * Helper Penghapusan Foto Lama
     */
    private function removePhoto(?string $name): void
    {
        if ($name && $name !== 'default.png') {
            $path = FCPATH . 'uploads/products/' . basename($name);
            if (is_file($path)) {
                @unlink($path);
            }
        }
    }
}
