<?php

namespace App\Controllers;

use App\Models\UserModel;

/**
 * Self-service "My Profile" — the one place ANY logged-in staff member
 * (any role) can view/edit their own name/email/phone/photo and change
 * their own password, without needing a manager. Distinct from
 * UserController, which is manager-only administration of OTHER staff's
 * accounts (see its class doc comment) — every action here only ever
 * touches session('userId')'s own row, and it lives in the top-level
 * 'auth' route group rather than any role-gated group, since every role
 * needs this. Identification/banking fields (employee_id, SSNIT, Ghana
 * Card, bank details) and role stay manager-controlled on purpose —
 * those are HR record-keeping, not something a user should be able to
 * change about themselves.
 */
class ProfileController extends BaseController
{
    public function index()
    {
        $user = (new UserModel())->find($this->currentUserId());

        if ($user === null) {
            return redirect()->to('logout');
        }

        return view('profile/index', [
            'pageTitle' => 'My Profile',
            'user'      => $user,
        ]);
    }

    public function update()
    {
        $model = new UserModel();
        $id    = $this->currentUserId();

        $data = [
            'full_name' => $this->request->getPost('full_name'),
            'email'     => $this->request->getPost('email'),
            'phone'     => $this->request->getPost('phone') ?: null,
        ];

        // UserModel's email rule is tenant_unique[users.email,id,{id}] —
        // the {id} placeholder only resolves against whatever's in the
        // array actually passed to validate(), and Model::update($id,
        // $row) never merges $id into $row itself (confirmed against
        // CI4's BaseModel::update() — validation runs on $row exactly as
        // given, before doProtectFields() would strip a non-allowed
        // field like 'id' back out). Without this, saving your own
        // unchanged email fails as a false "already taken" collision
        // against your own row — caught via a real test through this
        // form, not by inspection; nothing before this controller ever
        // updated an existing user's email, so the bug was latent.
        if (! $model->update($id, $data + ['id' => $id])) {
            return $this->redirectWithModelErrors($model);
        }

        // Keep the session in sync immediately — the topbar/sidebar read
        // session('userName')/userEmail directly (see AuthController::
        // attemptLogin(), which is the only other place that sets them),
        // so without this a saved name/email change wouldn't show until
        // the next login.
        session()->set(['userName' => $data['full_name'], 'userEmail' => $data['email']]);

        $this->logActivity('profile', 'Updated their own profile details.');

        return redirect()->to('profile')->with('success', 'Profile updated.');
    }

    /**
     * Same handle_image_upload()/public uploads/ serving path
     * UserController::uploadPhoto() uses for a manager updating someone
     * else's photo — a self-service headshot upload isn't more sensitive
     * than that.
     */
    public function uploadPhoto()
    {
        $id    = $this->currentUserId();
        $model = new UserModel();

        $upload = handle_image_upload($this->request->getFile('photo'), 'staff-photos');

        if ($upload['error']) {
            return redirect()->to('profile')->with('error', $upload['error']);
        }

        if ($upload['path'] === null) {
            return redirect()->to('profile')->with('error', 'Choose a photo to upload.');
        }

        $model->update($id, ['photo_path' => $upload['path']]);
        $this->logActivity('profile', 'Updated their own profile photo.');

        return redirect()->to('profile')->with('success', 'Photo updated.');
    }

    /**
     * Requires the real current password, not an SMS code — the user is
     * already logged in, so this is the standard "prove you still know
     * it" check. ForgotPasswordController's SMS-code flow stays the path
     * for someone who's actually locked out and can't log in at all.
     */
    public function changePassword()
    {
        $id    = $this->currentUserId();
        $model = new UserModel();
        $user  = $model->find($id);

        $current = (string) $this->request->getPost('current_password');
        $new     = (string) $this->request->getPost('new_password');
        $confirm = (string) $this->request->getPost('confirm_password');

        if ($user === null || ! password_verify($current, $user->password_hash)) {
            return redirect()->to('profile')->with('error', 'Your current password is incorrect.');
        }

        if (strlen($new) < 8) {
            return redirect()->to('profile')->with('error', 'New password must be at least 8 characters.');
        }

        if ($new !== $confirm) {
            return redirect()->to('profile')->with('error', 'New password and confirmation do not match.');
        }

        $model->update($id, ['password_hash' => password_hash($new, PASSWORD_DEFAULT)]);
        $this->logActivity('profile', 'Changed their own password.');

        return redirect()->to('profile')->with('success', 'Password changed.');
    }
}
