<?php

namespace App\Controllers;

use App\Models\SystemSettingModel;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\ResponseInterface;

class SettingsController extends BaseController
{
    private const SESSION_UNLOCK_KEY = 'branding_settings_unlocked';

    public function index(): string|RedirectResponse
    {
        if (! $this->session->get(self::SESSION_UNLOCK_KEY)) {
            return redirect()->to(site_url('dashboard'))->with('error', 'Ingresa el PIN para abrir el panel de branding.');
        }

        $company = company_profile();

        return view('settings/branding', [
            'title' => 'Branding del sistema',
            'settings' => [
                'company_name' => $company['name'],
                'brand_mark' => $company['brand_mark'],
                'company_tagline' => $company['tagline'],
                'company_website' => $company['website'],
                'company_linkedin' => $company['linkedin'],
                'company_whatsapp' => $company['whatsapp'],
                'company_emails' => settings_lines_text($company['emails']),
                'company_phones' => settings_lines_text($company['phones']),
                'company_intro_lead' => $company['intro_lead'],
                'company_intro_body' => $company['intro_body'],
                'company_strengths' => settings_lines_text($company['strengths']),
                'default_delivery_time' => $company['default_delivery_time'],
                'default_payment_terms' => $company['default_payment_terms'],
                'condition_lines' => settings_lines_text($company['condition_lines']),
                'developer_footer' => $company['developer_footer'],
            ],
            'logoUrl' => company_brand_asset_url('logo'),
            'qrUrl' => company_brand_asset_url('qr'),
        ]);
    }

    public function unlock(): ResponseInterface
    {
        $pin = trim((string) $this->request->getPost('pin'));

        if ($pin === '') {
            return $this->response->setStatusCode(422)->setJSON([
                'ok' => false,
                'message' => 'Captura el PIN para continuar.',
                'csrf_token' => csrf_hash(),
            ]);
        }

        if (! password_verify($pin, branding_pin_hash())) {
            return $this->response->setStatusCode(422)->setJSON([
                'ok' => false,
                'message' => 'PIN incorrecto.',
                'csrf_token' => csrf_hash(),
            ]);
        }

        $this->session->set(self::SESSION_UNLOCK_KEY, true);

        return $this->response->setJSON([
            'ok' => true,
            'redirect' => site_url('settings/branding'),
            'csrf_token' => csrf_hash(),
        ]);
    }

    public function update(): RedirectResponse
    {
        if (! $this->session->get(self::SESSION_UNLOCK_KEY)) {
            return redirect()->to(site_url('dashboard'))->with('error', 'Ingresa el PIN para abrir el panel de branding.');
        }

        $newPin = trim((string) $this->request->getPost('new_pin'));
        $confirmPin = trim((string) $this->request->getPost('confirm_pin'));

        if ($newPin !== '' && strlen($newPin) < 4) {
            return redirect()->back()->withInput()->with('error', 'El nuevo PIN debe tener al menos 4 caracteres.');
        }

        if ($newPin !== '' && $newPin !== $confirmPin) {
            return redirect()->back()->withInput()->with('error', 'La confirmación del PIN no coincide.');
        }

        $model = new SystemSettingModel();

        $values = [
            'company_name' => trim((string) $this->request->getPost('company_name')),
            'brand_mark' => strtoupper(trim((string) $this->request->getPost('brand_mark'))),
            'company_tagline' => trim((string) $this->request->getPost('company_tagline')),
            'company_website' => trim((string) $this->request->getPost('company_website')),
            'company_linkedin' => trim((string) $this->request->getPost('company_linkedin')),
            'company_whatsapp' => trim((string) $this->request->getPost('company_whatsapp')),
            'company_emails' => trim((string) $this->request->getPost('company_emails')),
            'company_phones' => trim((string) $this->request->getPost('company_phones')),
            'company_intro_lead' => trim((string) $this->request->getPost('company_intro_lead')),
            'company_intro_body' => trim((string) $this->request->getPost('company_intro_body')),
            'company_strengths' => trim((string) $this->request->getPost('company_strengths')),
            'default_delivery_time' => trim((string) $this->request->getPost('default_delivery_time')),
            'default_payment_terms' => trim((string) $this->request->getPost('default_payment_terms')),
            'condition_lines' => trim((string) $this->request->getPost('condition_lines')),
            'developer_footer' => trim((string) $this->request->getPost('developer_footer')),
        ];

        try {
            $values = array_merge($values, $this->handleBrandUploads());
            if ($newPin !== '') {
                $values['branding_pin_hash'] = password_hash($newPin, PASSWORD_DEFAULT);
            }

            $model->setMany($values);
        } catch (\Throwable $e) {
            return redirect()->back()->withInput()->with('error', 'No fue posible guardar los ajustes de branding.');
        }

        return redirect()->to(site_url('settings/branding'))->with('success', 'Branding actualizado correctamente.');
    }

    public function lock(): RedirectResponse
    {
        $this->session->remove(self::SESSION_UNLOCK_KEY);

        return redirect()->to(site_url('dashboard'))->with('success', 'Panel de branding bloqueado.');
    }

    private function handleBrandUploads(): array
    {
        $saved = [];
        $saved = array_merge($saved, $this->storeBrandAsset('logo_file', 'company_logo_path', 'logo'));
        $saved = array_merge($saved, $this->storeBrandAsset('qr_file', 'company_qr_path', 'qr'));

        return $saved;
    }

    private function storeBrandAsset(string $fieldName, string $settingKey, string $prefix): array
    {
        $file = $this->request->getFile($fieldName);
        if ($file === null || $file->getError() === UPLOAD_ERR_NO_FILE) {
            return [];
        }

        if (! $file->isValid()) {
            throw new \RuntimeException('Archivo inválido.');
        }

        $extension = strtolower((string) $file->getExtension());
        $allowedExtensions = ['png', 'jpg', 'jpeg', 'webp'];
        if (! in_array($extension, $allowedExtensions, true)) {
            throw new \RuntimeException('Formato no permitido.');
        }

        if (($file->getSizeByUnit('kb') ?? 0) > 5120) {
            throw new \RuntimeException('Archivo demasiado grande.');
        }

        $uploadDir = FCPATH . 'uploads' . DIRECTORY_SEPARATOR . 'branding';
        if (! is_dir($uploadDir)) {
            mkdir($uploadDir, 0775, true);
        }

        $current = system_setting($settingKey, '');
        if (is_string($current) && str_starts_with($current, 'uploads/branding/')) {
            $existingPath = FCPATH . str_replace('/', DIRECTORY_SEPARATOR, $current);
            if (is_file($existingPath)) {
                @unlink($existingPath);
            }
        }

        $newName = $prefix . '-' . date('YmdHis') . '-' . bin2hex(random_bytes(4)) . '.' . $extension;
        $file->move($uploadDir, $newName, true);

        return [
            $settingKey => 'uploads/branding/' . $newName,
        ];
    }
}
