<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Models\RiderModel;
use Core\Request;
use Core\Auth;

final class RiderController extends BaseController
{
    private RiderModel $model;

    public function __construct()
    {
        parent::__construct();
        $this->model = new RiderModel();
    }

    // ── List ─────────────────────────────────────────────────────────────────────

    public function index(): void
    {
        $this->requirePermission('rider.view');
        $page   = max(1, (int) ($_GET['page'] ?? 1));
        $search = trim($_GET['search'] ?? '');

        $riders = $this->model->all($page, ITEMS_PER_PAGE, $search);
        $total  = $this->model->count($search);

        $this->view('riders.index', [
            'riders'  => $riders,
            'total'   => $total,
            'page'    => $page,
            'search'  => $search,
            'pages'   => (int) ceil($total / ITEMS_PER_PAGE),
        ]);
    }

    // ── Create ───────────────────────────────────────────────────────────────────

    public function create(): void
    {
        $this->requirePermission('rider.create');
        $this->view('riders.create', ['errors' => [], 'old' => []]);
    }

    public function store(): void
    {
        $this->requirePermission('rider.create');
        Request::verifyCsrf();

        $data   = $this->collectForm();
        $errors = $this->validate($data);

        if ($this->model->emailExists($data['email'])) {
            $errors['email'] = 'Email already in use.';
        }

        if ($errors) {
            $this->view('riders.create', ['errors' => $errors, 'old' => $data]);
            return;
        }

        $data['role_id']       = $this->model->riderRoleId();
        $data['password_hash'] = password_hash($data['password'], PASSWORD_BCRYPT, ['cost' => BCRYPT_COST]);
        $data['is_active']     = 1;
        $data['created_at']    = date('Y-m-d H:i:s');
        unset($data['password'], $data['password_confirm']);

        $id = $this->model->create($data);
        $this->flash('success', 'Rider added successfully.');
        $this->redirect('/riders/' . $id);
    }

    // ── Show ─────────────────────────────────────────────────────────────────────

    public function show(array $params): void
    {
        $this->requirePermission('rider.view');
        $rider   = $this->findOrFail((int) $params['id']);
        $page    = max(1, (int) ($_GET['page'] ?? 1));
        $history = $this->model->deliveryHistory($rider['id'], $page);
        $total   = $this->model->deliveryHistoryCount($rider['id']);

        $this->view('riders.show', [
            'rider'   => $rider,
            'history' => $history,
            'total'   => $total,
            'page'    => $page,
            'pages'   => (int) ceil($total / 15),
        ]);
    }

    // ── Edit ─────────────────────────────────────────────────────────────────────

    public function edit(array $params): void
    {
        $this->requirePermission('rider.edit');
        $rider = $this->findOrFail((int) $params['id']);
        $this->view('riders.edit', ['rider' => $rider, 'errors' => [], 'old' => $rider]);
    }

    public function update(array $params): void
    {
        $this->requirePermission('rider.edit');
        Request::verifyCsrf();

        $rider  = $this->findOrFail((int) $params['id']);
        $data   = $this->collectForm(false);
        $errors = $this->validate($data, false);

        if ($this->model->emailExists($data['email'], $rider['id'])) {
            $errors['email'] = 'Email already in use.';
        }

        if ($errors) {
            $this->view('riders.edit', ['rider' => $rider, 'errors' => $errors, 'old' => $data]);
            return;
        }

        if (!empty($data['password'])) {
            $data['password_hash'] = password_hash($data['password'], PASSWORD_BCRYPT, ['cost' => BCRYPT_COST]);
        }
        unset($data['password'], $data['password_confirm']);

        $this->model->update($rider['id'], $data);
        $this->flash('success', 'Rider updated successfully.');
        $this->redirect('/riders/' . $rider['id']);
    }

    // ── Delete ───────────────────────────────────────────────────────────────────

    public function delete(array $params): void
    {
        $this->requirePermission('rider.delete');
        Request::verifyCsrf();
        $rider = $this->findOrFail((int) $params['id']);
        $this->model->delete($rider['id']);
        $this->flash('success', 'Rider deleted.');
        $this->redirect('/riders');
    }

    // ── Toggle active ────────────────────────────────────────────────────────────

    public function toggle(array $params): void
    {
        $this->requirePermission('rider.edit');
        Request::verifyCsrf();
        $rider  = $this->findOrFail((int) $params['id']);
        $active = $this->model->toggle($rider['id']);
        $this->flash('success', 'Rider ' . ($active ? 'activated' : 'deactivated') . '.');
        $this->redirect('/riders');
    }

    // ── Helpers ──────────────────────────────────────────────────────────────────

    private function findOrFail(int $id): array
    {
        $rider = $this->model->find($id);
        if (!$rider) {
            $this->flash('error', 'Rider not found.');
            $this->redirect('/riders');
        }
        return $rider;
    }

    private function collectForm(bool $withPassword = true): array
    {
        $data = [
            'name'  => trim(Request::str('name')),
            'email' => trim(Request::str('email')),
            'phone' => trim(Request::str('phone')),
            'vehicle_number' => trim(Request::str('vehicle_number')),
            'vehicle_type'   => trim(Request::str('vehicle_type')),
        ];
        if ($withPassword) {
            $data['password']         = Request::str('password');
            $data['password_confirm'] = Request::str('password_confirm');
        } else {
            $data['password']         = Request::str('password');
            $data['password_confirm'] = Request::str('password_confirm');
        }
        return $data;
    }

    private function validate(array $data, bool $passwordRequired = true): array
    {
        $errors = [];
        if (empty($data['name']))  $errors['name']  = 'Name is required.';
        if (empty($data['email'])) $errors['email'] = 'Email is required.';
        elseif (!filter_var($data['email'], FILTER_VALIDATE_EMAIL))
            $errors['email'] = 'Invalid email address.';
        if (empty($data['phone'])) $errors['phone'] = 'Phone is required.';

        if ($passwordRequired && empty($data['password'])) {
            $errors['password'] = 'Password is required.';
        }
        if (!empty($data['password']) && strlen($data['password']) < 6) {
            $errors['password'] = 'Password must be at least 6 characters.';
        }
        if (!empty($data['password']) && $data['password'] !== $data['password_confirm']) {
            $errors['password_confirm'] = 'Passwords do not match.';
        }
        return $errors;
    }
}
