<?php

namespace Modules\Tpin\Controllers;

use App\Controllers\BaseController;
use Modules\Auth\Models\UserModel;
use Modules\Tpin\Services\TpinService;

class TpinController extends BaseController
{
    protected TpinService $tpin;
    protected UserModel $users;

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

    // --- Own profile: manage TPIN -------------------------------------------

    public function manageForm()
    {
        $userId = (int) $this->session->get('user_id');
        $status = $this->tpin->statusFor($userId);

        return view('Modules\Tpin\Views\manage', array_merge($this->baseViewData(), [
            'title'       => 'Manage TPIN',
            'breadcrumbs' => [
                'Dashboard' => base_url('dashboard'),
                'Profile'   => base_url('profile'),
                'TPIN',
            ],
            'status' => $status,
        ]));
    }

    public function setSubmit()
    {
        $userId = (int) $this->session->get('user_id');
        $status = $this->tpin->statusFor($userId);

        if ($status['has_tpin']) {
            return redirect()->back()->with('error', 'TPIN already set. Use Change TPIN instead.');
        }

        $rules = [
            'tpin'             => 'required|min_length[4]|max_length[6]',
            'tpin_confirm'     => 'required|matches[tpin]',
            'current_password' => 'required',
        ];

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

        $result = $this->tpin->setTpin(
            $userId,
            (string) $this->request->getPost('tpin'),
            (string) $this->request->getPost('tpin_confirm'),
            (string) $this->request->getPost('current_password')
        );

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

        return redirect()->to('/profile/tpin')->with('success', 'TPIN set successfully.');
    }

    public function changeSubmit()
    {
        $userId = (int) $this->session->get('user_id');
        $status = $this->tpin->statusFor($userId);

        if (! $status['has_tpin']) {
            return redirect()->back()->with('error', 'No TPIN set yet. Create one first.');
        }

        $rules = [
            'current_tpin'    => 'required|min_length[4]|max_length[6]',
            'tpin'            => 'required|min_length[4]|max_length[6]',
            'tpin_confirm'    => 'required|matches[tpin]',
        ];

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

        $result = $this->tpin->changeTpin(
            $userId,
            (string) $this->request->getPost('current_tpin'),
            (string) $this->request->getPost('tpin'),
            (string) $this->request->getPost('tpin_confirm')
        );

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

        return redirect()->to('/profile/tpin')->with('success', 'TPIN updated successfully.');
    }

    public function clearOwnSubmit()
    {
        $userId = (int) $this->session->get('user_id');

        $rules = ['current_tpin' => 'required|min_length[4]|max_length[6]'];
        if (! $this->validate($rules)) {
            return redirect()->back()->with('errors', $this->validator->getErrors());
        }

        $result = $this->tpin->clearOwnTpin($userId, (string) $this->request->getPost('current_tpin'));

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

        return redirect()->to('/profile/tpin')->with('success', 'TPIN removed.');
    }

    // --- Reusable verify endpoint -------------------------------------------

    /**
     * POST /tpin/verify — JSON step-up check used before protected actions.
     */
    public function verify()
    {
        $userId = (int) $this->session->get('user_id');
        $tpin   = (string) $this->request->getPost('tpin');

        if ($tpin === '') {
            return $this->response->setStatusCode(422)->setJSON([
                'success' => false,
                'error'   => 'TPIN is required.',
            ]);
        }

        $result = $this->tpin->verify($userId, $tpin);
        $result['csrf_hash'] = csrf_hash();

        return $this->response
            ->setStatusCode($result['success'] ? 200 : 422)
            ->setJSON($result);
    }

    /**
     * GET /tpin/status — whether the current user must confirm.
     */
    public function status()
    {
        $userId = (int) $this->session->get('user_id');
        $status = $this->tpin->statusFor($userId);

        return $this->response->setJSON([
            'success'       => true,
            'must_confirm'  => $this->tpin->userMustConfirm($userId),
            'status'        => $status,
        ]);
    }

    // --- Admin: assign / clear ----------------------------------------------

    public function assignRequired(int $id)
    {
        $user = $this->users->find($id);
        if (! $user) {
            return redirect()->to('/users')->with('error', 'User not found.');
        }

        $required = (bool) $this->request->getPost('tpin_required');
        $this->tpin->setRequired($id, $required, (int) $this->session->get('user_id'));

        $msg = $required
            ? 'TPIN requirement enabled for this user.'
            : 'TPIN requirement disabled for this user.';

        return redirect()->back()->with('success', $msg);
    }

    public function adminClear(int $id)
    {
        $user = $this->users->find($id);
        if (! $user) {
            return redirect()->to('/users')->with('error', 'User not found.');
        }

        if (! $this->tpin->hasTpin($id)) {
            return redirect()->back()->with('error', 'This user has no TPIN set.');
        }

        $this->tpin->adminClearTpin($id, (int) $this->session->get('user_id'));

        return redirect()->back()->with('success', 'User TPIN cleared. They can set a new one from their profile.');
    }
}
