<?php

namespace Modules\Auth\Controllers;

use App\Controllers\BaseController;
use Modules\Auth\Services\AuthService;
use Modules\Auth\Services\PasswordPolicyService;

class PasswordController extends BaseController
{
    protected PasswordPolicyService $policy;

    public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
    {
        parent::initController($request, $response, $logger);
        $this->policy = new PasswordPolicyService();
    }

    // --- Forgot password -------------------------------------------------

    public function forgotForm()
    {
        return view('Modules\Auth\Views\forgot_password', ['title' => 'Forgot Password']);
    }

    public function forgotSubmit()
    {
        if (! $this->validate(['identifier' => 'required'])) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        $identifier = trim($this->request->getPost('identifier'));
        $token      = $this->policy->createResetToken($identifier, $this->request->getIPAddress());

        // Always show the same generic message, whether or not the account
        // exists, to prevent user enumeration.
        if ($token !== null) {
            // In production this dispatches an email via the Email module/service.
            // Left as a TODO hook point — do not log the plaintext token.
            log_message('info', 'Password reset token generated for a user (delivery handled by Email service).');
        }

        return redirect()->to('/login')->with('success', 'If that account exists, password reset instructions have been sent.');
    }

    // --- Reset password (via emailed token link) --------------------------

    public function resetForm(string $token)
    {
        return view('Modules\Auth\Views\reset_password', ['title' => 'Reset Password', 'token' => $token]);
    }

    public function resetSubmit()
    {
        $rules = [
            'token'                 => 'required',
            'password'              => 'required|min_length[10]',
            'password_confirm'      => 'required|matches[password]',
        ];

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

        $strengthErrors = $this->policy->validateStrength($this->request->getPost('password'));
        if ($strengthErrors) {
            return redirect()->back()->withInput()->with('error', implode(' ', $strengthErrors));
        }

        $ok = $this->policy->consumeResetToken(
            $this->request->getPost('token'),
            $this->request->getPost('password')
        );

        if (! $ok) {
            return redirect()->back()->with('error', 'This reset link is invalid or has expired.');
        }

        return redirect()->to('/login')->with('success', 'Your password has been reset. Please sign in.');
    }

    // --- Change password (authenticated user) ------------------------------

    public function changeForm()
    {
        return view('Modules\Auth\Views\change_password', array_merge(
            $this->baseViewData(),
            [
                'title'       => 'Change Password',
                'breadcrumbs' => ['Dashboard' => base_url('dashboard'), 'Change Password'],
            ]
        ));
    }

    public function changeSubmit()
    {
        $rules = [
            'current_password' => 'required',
            'password'         => 'required|min_length[10]',
            'password_confirm' => 'required|matches[password]',
        ];

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

        $result = $this->policy->changePassword(
            (int) $this->session->get('user_id'),
            $this->request->getPost('current_password'),
            $this->request->getPost('password')
        );

        if (! $result['success']) {
            return redirect()->back()->with('error', $result['error']);
        }

        return redirect()->to(
            (new AuthService())->landingUrlForRole(
                $this->session->get('role_id') ? (int) $this->session->get('role_id') : null
            )
        )->with('success', 'Password updated successfully.');
    }
}
