<?php
declare(strict_types=1);

namespace App\Modules\PublicArea;

use App\Core\Auth;
use App\Core\AuditLogger;
use App\Core\Config;
use App\Core\Database;
use App\Core\RateLimiter;
use App\Core\Request;
use App\Core\Session;
use App\Core\Validator;
use App\Core\View;

final class AuthController
{
    public function showRegister(Request $request): string
    {
        return View::renderTemplate('public/auth/register');
    }

    public function register(Request $request): never
    {
        verify_csrf((string) $request->input('_token', ''));

        $input = array_map('trim', [
            'nama' => (string) $request->input('nama', ''),
            'whatsapp' => (string) $request->input('whatsapp', ''),
            'email' => (string) $request->input('email', ''),
            'password' => (string) $request->input('password', ''),
            'password_confirmation' => (string) $request->input('password_confirmation', ''),
        ]);

        Session::flash('old_input', [
            'nama' => $input['nama'],
            'whatsapp' => $input['whatsapp'],
            'email' => $input['email'],
        ]);

        $errors = Validator::make($input, [
            'nama' => ['required', 'string', 'min:3', 'max:100'],
            'whatsapp' => ['required', 'whatsapp'],
            'email' => ['required', 'email', 'max:120'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
        ]);

        if ($errors !== []) {
            Session::flash('errors', $errors);
            redirect('/register');
        }

        $duplicate = Database::query(
            'SELECT id FROM users WHERE email = :email OR whatsapp = :whatsapp LIMIT 1',
            [
                'email' => $input['email'],
                'whatsapp' => $input['whatsapp'],
            ]
        )->fetch();

        if (is_array($duplicate)) {
            Session::flash('errors', [
                'email' => ['Email atau WhatsApp sudah terdaftar.'],
            ]);
            redirect('/register');
        }

        $algorithm = defined('PASSWORD_ARGON2ID') ? PASSWORD_ARGON2ID : PASSWORD_BCRYPT;
        $hash = password_hash($input['password'], $algorithm);
        $now = date('Y-m-d H:i:s');

        Database::query(
            'INSERT INTO users (nama, email, whatsapp, password, role, created_at, updated_at)
             VALUES (:nama, :email, :whatsapp, :password, :role, :created_at, :updated_at)',
            [
                'nama' => $input['nama'],
                'email' => $input['email'],
                'whatsapp' => $input['whatsapp'],
                'password' => $hash,
                'role' => 'client',
                'created_at' => $now,
                'updated_at' => $now,
            ]
        );

        $userId = (int) Database::connection()->lastInsertId();
        AuditLogger::log('register', $userId, ['email' => $input['email']]);
        Session::flash('status', 'Akun berhasil dibuat. Silakan login.');
        redirect('/login');
    }

    public function showLogin(Request $request): string
    {
        return View::renderTemplate('public/auth/login');
    }

    public function login(Request $request): never
    {
        verify_csrf((string) $request->input('_token', ''));

        $input = array_map('trim', [
            'identifier' => (string) $request->input('identifier', ''),
            'password' => (string) $request->input('password', ''),
        ]);

        Session::flash('old_input', [
            'identifier' => $input['identifier'],
        ]);

        $errors = Validator::make($input, [
            'identifier' => ['required', 'string', 'min:3', 'max:120'],
            'password' => ['required', 'string', 'min:8'],
        ]);

        if ($errors !== []) {
            Session::flash('errors', $errors);
            redirect('/login');
        }

        $maxAttempts = (int) Config::get('app.security.rate_limit_max', 5);
        $window = (int) Config::get('app.security.rate_limit_window', 900);
        $rateKey = 'login:' . sha1($request->ip() . '|' . mb_strtolower($input['identifier']));

        if (RateLimiter::tooManyAttempts($rateKey, $maxAttempts, $window)) {
            Session::flash('errors', [
                'identifier' => ['Terlalu banyak percobaan. Coba lagi dalam ' . RateLimiter::availableIn($rateKey, $window) . ' detik.'],
            ]);
            redirect('/login');
        }

        $user = Auth::attempt($input['identifier'], $input['password']);

        if (! is_array($user)) {
            RateLimiter::hit($rateKey, $window);
            AuditLogger::log('failed_login', null, [
                'identifier' => $input['identifier'],
            ]);

            Session::flash('errors', [
                'identifier' => ['Email/WhatsApp atau password salah.'],
            ]);
            redirect('/login');
        }

        RateLimiter::clear($rateKey);
        Auth::login($user);
        AuditLogger::log('login', (int) $user['id'], [
            'identifier' => $input['identifier'],
        ]);
        Session::flash('status', 'Login berhasil.');
        if (($user['role'] ?? 'client') === 'admin') {
            redirect('/admin/dashboard');
        }

        redirect('/dashboard');
    }

    public function logout(Request $request): never
    {
        verify_csrf((string) $request->input('_token', ''));

        $user = Auth::user();
        Auth::logout();
        AuditLogger::log('logout', isset($user['id']) ? (int) $user['id'] : null);
        Session::flash('status', 'Anda sudah logout.');
        redirect('/login');
    }
}
