<?php

namespace App\Controllers;

use App\Models\SuplierModel;
use Config\Database;

class SuplierController extends BaseController
{
    private SuplierModel $suplierModel;

    public function __construct()
    {
        $this->suplierModel = new SuplierModel();
    }

    public function index()
    {
        if (! $this->isLoggedIn()) {
            return redirect()->to('/login')->with('error', 'Silakan login terlebih dahulu.');
        }

        if ($redirect = $this->requireAdministrator('/admin/dashboard', 'Akses ditolak. Data suplier hanya dapat diakses oleh administrator.')) {
            return $redirect;
        }

        $suplier = $this->suplierModel
            ->select('suplier.*')
            ->select('(SELECT COUNT(*) FROM pembelian WHERE pembelian.suplier_id = suplier.id) AS total_pembelian', false)
            ->orderBy('id', 'DESC')
            ->findAll();

        return view('admin/suplier/index', [
            'suplier'   => $suplier,
            'userName'  => session()->get('userName'),
            'userEmail' => session()->get('userEmail'),
            'userRole'  => session()->get('userRole'),
        ]);
    }

    public function create()
    {
        if (! $this->isLoggedIn()) {
            return redirect()->to('/login')->with('error', 'Silakan login terlebih dahulu.');
        }

        if ($redirect = $this->requireAdministrator('/admin/suplier')) {
            return $redirect;
        }

        return view('admin/suplier/create', [
            'kodeSuplier' => $this->nextCode('suplier', 'kode_suplier', 'SUP'),
            'userName'    => session()->get('userName'),
            'userEmail'   => session()->get('userEmail'),
            'userRole'    => session()->get('userRole'),
        ]);
    }

    public function store()
    {
        if (! $this->isLoggedIn()) {
            return redirect()->to('/login')->with('error', 'Silakan login terlebih dahulu.');
        }

        if ($redirect = $this->requireAdministrator('/admin/suplier')) {
            return $redirect;
        }

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

        $data = $this->formData();
        $data['kode_suplier'] = $this->nextCode('suplier', 'kode_suplier', 'SUP');

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

        return redirect()->to('/admin/suplier')->with('success', 'Data suplier berhasil ditambahkan.');
    }

    public function edit(int $id)
    {
        if (! $this->isLoggedIn()) {
            return redirect()->to('/login')->with('error', 'Silakan login terlebih dahulu.');
        }

        if ($redirect = $this->requireAdministrator('/admin/suplier')) {
            return $redirect;
        }

        $suplier = $this->suplierModel->find($id);

        if (! $suplier) {
            return redirect()->to('/admin/suplier')->with('error', 'Data suplier tidak ditemukan.');
        }

        return view('admin/suplier/edit', [
            'suplier'   => $suplier,
            'userName'  => session()->get('userName'),
            'userEmail' => session()->get('userEmail'),
            'userRole'  => session()->get('userRole'),
        ]);
    }

    public function update(int $id)
    {
        if (! $this->isLoggedIn()) {
            return redirect()->to('/login')->with('error', 'Silakan login terlebih dahulu.');
        }

        if ($redirect = $this->requireAdministrator('/admin/suplier')) {
            return $redirect;
        }

        $suplier = $this->suplierModel->find($id);

        if (! $suplier) {
            return redirect()->to('/admin/suplier')->with('error', 'Data suplier tidak ditemukan.');
        }

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

        $this->suplierModel->update($id, $this->formData());

        return redirect()->to('/admin/suplier')->with('success', 'Data suplier berhasil diperbarui.');
    }

    public function delete(int $id)
    {
        if (! $this->isLoggedIn()) {
            return redirect()->to('/login')->with('error', 'Silakan login terlebih dahulu.');
        }

        if ($redirect = $this->requireAdministrator('/admin/suplier')) {
            return $redirect;
        }

        $suplier = $this->suplierModel->find($id);

        if (! $suplier) {
            return redirect()->to('/admin/suplier')->with('error', 'Data suplier tidak ditemukan.');
        }

        if ($this->totalPembelianBySuplier($id) > 0) {
            return redirect()->to('/admin/suplier')->with(
                'error',
                'Data suplier tidak dapat dihapus karena sudah terhubung ke transaksi pembelian.'
            );
        }

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

        return redirect()->to('/admin/suplier')->with('success', 'Data suplier berhasil dihapus.');
    }

    private function totalPembelianBySuplier(int $suplierId): int
    {
        return Database::connect()
            ->table('pembelian')
            ->where('suplier_id', $suplierId)
            ->countAllResults();
    }

    private function validationRules(): array
    {
        return [
            'nama'       => 'required|min_length[2]|max_length[100]',
            'no_hp'      => 'required|min_length[8]|max_length[30]|regex_match[/^[0-9+().\\-\\s]+$/]',
            'email'      => 'permit_empty|valid_email|max_length[150]',
            'alamat'     => 'required|min_length[5]',
            'perusahaan' => 'required|min_length[2]|max_length[150]',
        ];
    }

    private function formData(): array
    {
        return [
            'nama'       => $this->request->getPost('nama'),
            'no_hp'      => $this->request->getPost('no_hp'),
            'email'      => $this->request->getPost('email') ?: null,
            'alamat'     => $this->request->getPost('alamat'),
            'perusahaan' => $this->request->getPost('perusahaan'),
        ];
    }

    private function nextCode(string $table, string $field, string $prefix): string
    {
        $row = Database::connect()
            ->table($table)
            ->select("MAX(CAST(SUBSTRING({$field}, 4) AS UNSIGNED)) AS last_number", false)
            ->get()
            ->getRowArray();

        return $prefix . str_pad((string) (((int) ($row['last_number'] ?? 0)) + 1), 4, '0', STR_PAD_LEFT);
    }

    private function isLoggedIn(): bool
    {
        return (bool) session()->get('isLoggedIn') && $this->isUserAccount();
    }
}
