<?php

namespace App\Controllers;

use App\Libraries\TemporaryImageUpload;
use App\Models\SettingModel;
use RuntimeException;

class SettingController extends BaseController
{
    private SettingModel $settingModel;
    private TemporaryImageUpload $temporaryImageUpload;
    private string $uploadPath;

    public function __construct()
    {
        $this->settingModel        = new SettingModel();
        $this->temporaryImageUpload = new TemporaryImageUpload();
        $this->uploadPath          = FCPATH . 'uploads/settings';
    }

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

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

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

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

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

        $rules = [
            'nama_aplikasi'   => 'required|min_length[2]|max_length[100]',
            'judul_aplikasi'  => 'required|min_length[2]|max_length[150]',
            'tagline'         => 'permit_empty|max_length[150]',
            'nama_perusahaan' => 'permit_empty|max_length[150]',
            'pajak_persen'    => 'required|integer|greater_than_equal_to[0]|less_than_equal_to[100]',
            'nota_penjualan_ukuran' => 'required|in_list[thermal_58,thermal_80,a4,continuous_form]',
        ];

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

        $setting = $this->getSetting();
        $data = [
            'nama_aplikasi'   => $this->request->getPost('nama_aplikasi'),
            'judul_aplikasi'  => $this->request->getPost('judul_aplikasi'),
            'tagline'         => $this->request->getPost('tagline'),
            'nama_perusahaan' => $this->request->getPost('nama_perusahaan'),
            'pajak_persen'    => $this->taxPercentFromPost(),
            'nota_penjualan_ukuran' => $this->receiptSizeFromPost(),
        ];

        try {
            $this->temporaryImageUpload->assertAvailable(
                $this->request->getPost('logo_temp'),
                ['jpg', 'jpeg', 'png', 'webp']
            );
            $this->temporaryImageUpload->assertAvailable(
                $this->request->getPost('favicon_temp'),
                ['ico', 'jpg', 'jpeg', 'png', 'webp']
            );

            $logoName = $this->temporaryImageUpload->moveToPermanent(
                $this->request->getPost('logo_temp'),
                $this->uploadPath,
                ['jpg', 'jpeg', 'png', 'webp']
            );
            $faviconName = $this->temporaryImageUpload->moveToPermanent(
                $this->request->getPost('favicon_temp'),
                $this->uploadPath,
                ['ico', 'jpg', 'jpeg', 'png', 'webp']
            );
        } catch (RuntimeException $exception) {
            return redirect()->back()->withInput()->with('errors', [
                'image' => $exception->getMessage(),
            ]);
        }

        if ($logoName !== null) {
            $data['logo'] = $logoName;
            $this->deleteImage($setting['logo'] ?? null);
        }

        if ($faviconName !== null) {
            $data['favicon'] = $faviconName;
            $this->deleteImage($setting['favicon'] ?? null);
        }

        $this->settingModel->update(1, $data);

        return redirect()->to('/admin/setting')->with('success', 'Setting aplikasi berhasil diperbarui.');
    }

    private function getSetting(): array
    {
        $setting = $this->settingModel->find(1);

        if ($setting) {
            return $setting;
        }

        $this->settingModel->insert([
            'setting_id'      => 1,
            'logo'            => null,
            'favicon'         => null,
            'nama_aplikasi'   => 'Aplikasi Admin',
            'judul_aplikasi'  => 'Aplikasi Admin',
            'tagline'         => 'Fondasi aplikasi yang siap dikembangkan',
            'nama_perusahaan' => 'Perusahaan Anda',
            'pajak_persen'    => 11,
            'nota_penjualan_ukuran' => 'thermal_58',
        ]);

        return $this->settingModel->find(1);
    }

    private function taxPercentFromPost(): int
    {
        $value = preg_replace('/\D/', '', (string) $this->request->getPost('pajak_persen')) ?: '0';

        return max(0, min(100, (int) $value));
    }

    private function receiptSizeFromPost(): string
    {
        $value = (string) $this->request->getPost('nota_penjualan_ukuran');

        return in_array($value, ['thermal_58', 'thermal_80', 'a4', 'continuous_form'], true) ? $value : 'thermal_58';
    }

    private function deleteImage(?string $fileName): void
    {
        if (! $fileName) {
            return;
        }

        $filePath = $this->uploadPath . DIRECTORY_SEPARATOR . $fileName;

        if (is_file($filePath)) {
            unlink($filePath);
        }
    }

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