<?php

namespace App\Controllers\Api;

use App\Libraries\AuditLogger;
use App\Libraries\ResponseHelper;
use App\Libraries\UuidHelper;
use App\Models\PermissionModel;
use App\Models\RoleModel;
use App\Models\UserCustomPermissionModel;
use App\Models\UserModel;

class UserController extends BaseApiController
{
    private UserModel $model;

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

    public function index()
    {
        if ($err = $this->requirePermission('manage_users')) return $err;

        $roleFilter = $this->request->getGet('role_id');
        if ($roleFilter) {
            $this->model->where('role_id', $roleFilter);
        }

        $perPage = $this->getPerPage();
        $result  = $this->model->scopedPaginate($perPage);
        $result['data'] = array_map([$this, 'format'], $result['data']);

        return ResponseHelper::paginated($result);
    }

    public function create()
    {
        if ($err = $this->requirePermission('manage_users')) return $err;

        $data = $this->getJson();
        $v    = service('validation');
        $v->setRules([
            'name'     => 'required|min_length[2]|max_length[255]',
            'email'    => 'required|valid_email',
            'role_id'  => 'required|integer',
            'password' => 'required|min_length[8]',
        ]);

        if (!$v->run($data)) {
            return ResponseHelper::validationError($v->getErrors());
        }

        // Check unique email within church
        $existing = $this->model->where('email', $data['email'])->first();
        if ($existing) {
            return ResponseHelper::error('A user with this email already exists', 422);
        }

        $uuid = UuidHelper::generate();
        $this->model->insert([
            'uuid'          => $uuid,
            'church_id'     => $this->churchId(),
            'role_id'       => $data['role_id'],
            'name'          => $data['name'],
            'email'         => $data['email'],
            'phone'         => $data['phone'] ?? null,
            'password_hash' => password_hash($data['password'], PASSWORD_DEFAULT),
            'is_active'     => 1,
        ]);

        $user = $this->model->findByUuid($uuid);
        AuditLogger::log('user.created', 'users', $uuid, null, $user);

        return ResponseHelper::created($this->format($user));
    }

    public function show(string $uuid)
    {
        if ($err = $this->requirePermission('manage_users')) return $err;

        $user = $this->model->findByUuid($uuid);
        if (!$user) return ResponseHelper::notFound();

        return ResponseHelper::success($this->formatFull($user));
    }

    public function update(string $uuid)
    {
        if ($err = $this->requirePermission('manage_users')) return $err;

        $user = $this->model->findByUuid($uuid);
        if (!$user) return ResponseHelper::notFound();

        $data    = $this->getJson();
        $allowed = ['name', 'email', 'phone', 'role_id', 'is_active'];
        $update  = array_intersect_key($data, array_flip($allowed));

        if (empty($update)) {
            return ResponseHelper::error('No valid fields provided', 422);
        }

        $old = $user;
        $this->model->update($user['id'], $update);
        $new = $this->model->findByUuid($uuid);

        AuditLogger::log('user.updated', 'users', $uuid, $old, $new);

        return ResponseHelper::success($this->format($new));
    }

    public function delete(string $uuid)
    {
        if ($err = $this->requirePermission('manage_users')) return $err;

        $user = $this->model->findByUuid($uuid);
        if (!$user) return ResponseHelper::notFound();

        $this->model->delete($user['id']);
        AuditLogger::log('user.deleted', 'users', $uuid, $user, null);

        return ResponseHelper::success(null);
    }

    public function setPermissions(string $uuid)
    {
        if ($err = $this->requirePermission('manage_users')) return $err;

        $user = $this->model->findByUuid($uuid);
        if (!$user) return ResponseHelper::notFound();

        $data        = $this->getJson();
        $permissions = $data['permissions'] ?? [];

        $ucpModel    = new UserCustomPermissionModel();
        $permModel   = new PermissionModel();

        // Delete existing overrides
        $ucpModel->where('user_id', $user['id'])->delete();

        foreach ($permissions as $perm) {
            $permRow = $permModel->where('name', $perm['name'])->first();
            if (!$permRow) continue;

            $ucpModel->insert([
                'user_id'       => $user['id'],
                'permission_id' => $permRow['id'],
                'granted'       => (int) ($perm['granted'] ?? 1),
            ]);
        }

        AuditLogger::log('user.permissions_updated', 'user_custom_permissions', $uuid, null, $permissions);

        return ResponseHelper::success(null);
    }

    public function resetPassword(string $uuid)
    {
        if ($err = $this->requirePermission('manage_users')) return $err;

        $user = $this->model->findByUuid($uuid);
        if (!$user) return ResponseHelper::notFound();

        $data = $this->getJson();
        if (empty($data['password']) || strlen($data['password']) < 8) {
            return ResponseHelper::validationError(['password' => 'Password must be at least 8 characters']);
        }

        $this->model->update($user['id'], [
            'password_hash' => password_hash($data['password'], PASSWORD_DEFAULT),
        ]);

        AuditLogger::log('user.password_reset', 'users', $uuid, null, null);

        return ResponseHelper::success(null);
    }

    // ----------------------------------------------------------------

    private function format(array $u): array
    {
        return [
            'uuid'       => $u['uuid'],
            'name'       => $u['name'],
            'email'      => $u['email'],
            'phone'      => $u['phone'],
            'is_active'  => (bool) $u['is_active'],
            'role_id'    => $u['role_id'],
            'created_at' => $u['created_at'],
        ];
    }

    private function formatFull(array $u): array
    {
        $base = $this->format($u);

        $ucpModel  = new UserCustomPermissionModel();
        $permModel = new PermissionModel();
        $overrides = $ucpModel->where('user_id', $u['id'])->findAll();
        $customs   = [];

        foreach ($overrides as $o) {
            $perm = $permModel->find($o['permission_id']);
            if ($perm) {
                $customs[] = ['name' => $perm['name'], 'granted' => (bool) $o['granted']];
            }
        }

        $base['custom_permissions'] = $customs;
        return $base;
    }
}
