<?php
namespace App\Controllers;

use App\Core\Audit;
use App\Core\Auth;
use App\Core\Controller;
use App\Core\Csrf;
use App\Core\Database;
use App\Core\Flash;
use App\Core\Request;
use App\Core\Session;
use App\Core\Settings;
use App\Core\Validator;
use App\Core\View;

/** Autentikasi, penggantian kata sandi, dan profil pengguna. */
class AuthController extends Controller
{
    protected string $module = 'dashboard';

    public function showLogin(): void
    {
        if (Auth::check()) $this->redirect('/');
        $demo = [];
        try {
            $demo = Database::i()->all(
                'SELECT u.username, u.name, r.name AS role_name FROM users u
                   JOIN roles r ON r.id = u.role_id
                  WHERE u.deleted_at IS NULL AND u.is_active = 1 AND u.must_change_password = 1
                  ORDER BY u.role_id'
            );
        } catch (\Throwable $e) {}
        View::render('auth/login', [
            'judul' => 'Masuk',
            'demo' => $demo,
            'tampilkan_demo' => count($demo) > 0,
        ], '');
    }

    public function login(): void
    {
        Csrf::verifyOrFail();
        $username = trim((string)Request::post('username', ''));
        $password = (string)Request::post('password', '');

        if ($username === '' || $password === '') {
            Flash::error('Nama pengguna dan kata sandi wajib diisi.');
            $this->redirect('/masuk');
        }

        $res = Auth::attempt($username, $password);
        if (!$res['sukses']) {
            Flash::error($res['pesan']);
            $this->redirect('/masuk');
        }

        Flash::success($res['pesan']);
        $intended = Session::get('_intended');
        Session::forget('_intended');
        if (Auth::mustChangePassword()) $this->redirect('/ganti-sandi');
        $this->redirect($intended && $intended !== '/masuk' ? $intended : '/');
    }

    public function logout(): void
    {
        if (Request::isPost()) Csrf::verifyOrFail();
        Auth::logout();
        Flash::info('Anda telah keluar dari sistem.');
        $this->redirect('/masuk');
    }

    public function showChangePassword(): void
    {
        if (!Auth::check()) $this->redirect('/masuk');
        View::render('auth/ganti_sandi', [
            'judul' => 'Ganti Kata Sandi',
            'wajib' => Auth::mustChangePassword(),
            'min'   => Settings::int('keamanan.panjang_sandi_minimal', 8),
        ], Auth::mustChangePassword() ? '' : 'layouts/app');
    }

    public function changePassword(): void
    {
        Csrf::verifyOrFail();
        if (!Auth::check()) $this->redirect('/masuk');

        $current = (string)Request::post('sandi_lama', '');
        $new     = (string)Request::post('sandi_baru', '');
        $confirm = (string)Request::post('sandi_konfirmasi', '');

        if ($new !== $confirm) {
            Flash::error('Konfirmasi kata sandi tidak cocok.');
            $this->redirect('/ganti-sandi');
        }
        $res = Auth::changePassword(Auth::id(), $new, true, $current);
        if (!$res['sukses']) {
            Flash::error($res['pesan']);
            $this->redirect('/ganti-sandi');
        }
        Flash::success($res['pesan']);
        $this->redirect('/');
    }

    public function profile(): void
    {
        $u = Auth::user();
        $stats = Database::i()->one(
            'SELECT (SELECT COUNT(*) FROM audit_logs WHERE user_id = :u1) AS aktivitas,
                    (SELECT COUNT(*) FROM invoices WHERE created_by = :u2 AND deleted_at IS NULL) AS invoice_dibuat,
                    (SELECT COUNT(*) FROM payments WHERE created_by = :u3 AND deleted_at IS NULL) AS pembayaran_dibuat',
            ['u1' => Auth::id(), 'u2' => Auth::id(), 'u3' => Auth::id()]
        );
        $recent = Database::i()->all(
            'SELECT * FROM audit_logs WHERE user_id = :u ORDER BY created_at DESC LIMIT 25', ['u' => Auth::id()]
        );
        $this->view('auth/profil', [
            'judul' => 'Profil Saya', 'u' => $u, 'stats' => $stats, 'recent' => $recent,
        ]);
    }

    public function updateProfile(): void
    {
        Csrf::verifyOrFail();
        $data = $this->validate([
            'name'  => 'required|maxlen:120',
            'email' => 'required|email|maxlen:150',
            'phone' => 'nullable|maxlen:40',
        ], ['name' => 'Nama', 'email' => 'Email', 'phone' => 'Telepon']);

        $exists = Database::i()->value('SELECT COUNT(*) FROM users WHERE email = :e AND id <> :id', ['e' => $data['email'], 'id' => Auth::id()]);
        if ((int)$exists > 0) {
            Flash::error('Alamat email tersebut sudah dipakai pengguna lain.');
            $this->redirect('/profil');
        }
        $before = Auth::user();
        Database::i()->update('users', [
            'name' => $data['name'], 'email' => $data['email'], 'phone' => $data['phone'] ?: null,
        ], 'id = :pk', ['pk' => Auth::id()]);
        Audit::logDiff('pengguna', 'update', 'user', Auth::id(), $before ?? [], $data, 'Profil diperbarui');
        Flash::success('Profil berhasil diperbarui.');
        $this->redirect('/profil');
    }
}
