<?php

namespace App\Http\Controllers\Admin;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Models\User;
use App\Services\ActivityLogger;

class UserController extends Controller
{
    public function index(Request $request, array $params = []): void
    {
        $users = User::allForAdmin();

        $this->renderAdmin('users/index', [
            'pageTitle' => __('admin.users.title'),
            'users'     => $users,
            'auth'      => $this->auth(),
            'csrf'      => $this->csrf(),
        ]);
    }

    public function create(Request $request, array $params = []): void
    {
        $this->renderAdmin('users/form', [
            'pageTitle'   => __('admin.users.create'),
            'user'        => null,
            'old'         => [],
            'errors'      => [],
            'isOnlyAdmin' => false,
            'auth'        => $this->auth(),
            'csrf'        => $this->csrf(),
        ]);
    }

    public function store(Request $request, array $params = []): void
    {
        $this->validateCsrf();

        $data   = $this->extractFormData($request);
        $errors = $this->validateUser($data, null);

        // Password is required for new users
        if (empty($data['password'])) {
            $errors['password'] = 'Password is required.';
        } elseif (strlen($data['password']) < \App\Core\Auth::MIN_PASSWORD_LENGTH) {
            $errors['password'] = 'Password must be at least ' . \App\Core\Auth::MIN_PASSWORD_LENGTH . ' characters.';
        }

        if (!empty($errors)) {
            $this->renderAdmin('users/form', [
                'pageTitle'   => __('admin.users.create'),
                'user'        => null,
                'old'         => $data,
                'errors'      => $errors,
                'isOnlyAdmin' => false,
                'auth'        => $this->auth(),
                'csrf'        => $this->csrf(),
            ]);
            return;
        }

        $userId = User::create([
            'username'      => $data['username'],
            'email'         => $data['email'],
            'password_hash' => password_hash($data['password'], PASSWORD_DEFAULT),
            'role'          => $data['role'],
            'is_active'     => (int) $data['is_active'],
            'created_at'    => date('Y-m-d H:i:s'),
            'updated_at'    => date('Y-m-d H:i:s'),
        ]);

        ActivityLogger::log('create', 'user', $userId, $data['username']);
        set_flash('success', __('messages.user_created', ['name' => $data['username']]));
        Response::redirect('/admin/users');
    }

    public function edit(Request $request, array $params = []): void
    {
        $id   = (int) ($params['id'] ?? 0);
        $user = User::find($id);

        if (!$user) {
            set_flash('error', __('messages.not_found', ['item' => 'User']));
            Response::redirect('/admin/users');
            return;
        }

        $isSelf = ((int) $user['id'] === $this->auth()->userId());

        $this->renderAdmin('users/form', [
            'pageTitle'   => __('admin.users.edit'),
            'user'        => $user,
            'old'         => $user,
            'errors'      => [],
            'isOnlyAdmin' => $isSelf && User::countAdmins() <= 1,
            'auth'        => $this->auth(),
            'csrf'        => $this->csrf(),
        ]);
    }

    public function update(Request $request, array $params = []): void
    {
        $this->validateCsrf();

        $id   = (int) ($params['id'] ?? 0);
        $user = User::find($id);

        if (!$user) {
            set_flash('error', __('messages.not_found', ['item' => 'User']));
            Response::redirect('/admin/users');
            return;
        }

        $data        = $this->extractFormData($request);
        $errors      = $this->validateUser($data, $id);
        $currentUser = $this->auth()->userId();

        // Password change is optional on edit; validate only if provided
        $newPassword = trim($request->input('password', ''));
        if (!empty($newPassword) && strlen($newPassword) < \App\Core\Auth::MIN_PASSWORD_LENGTH) {
            $errors['password'] = 'Password must be at least ' . \App\Core\Auth::MIN_PASSWORD_LENGTH . ' characters.';
        }

        // Protect: cannot deactivate yourself — force active if editing own account
        if ($id === $currentUser) {
            $data['is_active'] = 1;
        }

        // Protect: cannot demote yourself if you are the last admin
        if ($id === $currentUser && $data['role'] !== 'admin') {
            if (User::countAdmins() <= 1) {
                $errors['role'] = 'Cannot demote: you are the only active admin.';
            }
        }

        if (!empty($errors)) {
            $isSelf = ($id === $currentUser);
            $this->renderAdmin('users/form', [
                'pageTitle'   => __('admin.users.edit'),
                'user'        => $user,
                'old'         => $data,
                'errors'      => $errors,
                'isOnlyAdmin' => $isSelf && User::countAdmins() <= 1,
                'auth'        => $this->auth(),
                'csrf'        => $this->csrf(),
            ]);
            return;
        }

        $updateData = [
            'username'   => $data['username'],
            'email'      => $data['email'],
            'role'       => $data['role'],
            'is_active'  => (int) $data['is_active'],
            'updated_at' => date('Y-m-d H:i:s'),
        ];

        if (!empty($newPassword)) {
            $updateData['password_hash'] = password_hash($newPassword, PASSWORD_DEFAULT);
        }

        User::updateById($id, $updateData);
        ActivityLogger::log('update', 'user', $id, $user['username'] ?? '');
        set_flash('success', __('messages.user_updated', ['name' => $data['username']]));
        Response::redirect('/admin/users');
    }

    public function delete(Request $request, array $params = []): void
    {
        $this->validateCsrf();

        $id   = (int) ($params['id'] ?? 0);
        $user = User::find($id);

        if (!$user) {
            set_flash('error', __('messages.not_found', ['item' => 'User']));
            Response::redirect('/admin/users');
            return;
        }

        // Cannot delete yourself
        if ($id === $this->auth()->userId()) {
            set_flash('error', __('messages.cannot_delete_self'));
            Response::redirect('/admin/users');
            return;
        }

        // Cannot delete the last active admin
        if ($user['role'] === 'admin' && User::countAdmins() <= 1) {
            set_flash('error', __('messages.error.last_admin'));
            Response::redirect('/admin/users');
            return;
        }

        User::deleteById($id);
        ActivityLogger::log('delete', 'user', $id, $user['username'] ?? '');
        set_flash('success', __('messages.user_deleted'));
        Response::redirect('/admin/users');
    }

    public function bulk(Request $request, array $params = []): void
    {
        $this->validateCsrf();
        $ids    = array_map('intval', $request->input('ids', []));
        $action = $request->input('bulk_action', '');
        $myId   = $this->auth()->userId();

        if (empty($ids)) {
            Response::redirect('/admin/users');
            return;
        }

        $count = 0;
        foreach ($ids as $id) {
            if ($id === $myId) continue; // Never modify yourself
            $user = User::find($id);
            if (!$user) continue;

            if ($action === 'delete') {
                if ($user['role'] === 'admin' && User::countAdmins() <= 1) continue;
                User::deleteById($id);
                $count++;
            } elseif ($action === 'activate') {
                User::updateById($id, ['status' => 'active']);
                $count++;
            } elseif ($action === 'deactivate') {
                User::updateById($id, ['status' => 'inactive']);
                $count++;
            }
        }

        set_flash('success', __('messages.bulk_action_done', ['count' => $count]));
        Response::redirect('/admin/users');
    }

    // ─────────────────────────────────────────────────────────
    // Private helpers
    // ─────────────────────────────────────────────────────────

    private function extractFormData(Request $request): array
    {
        return [
            'username'  => trim($request->input('username', '')),
            'email'     => trim($request->input('email', '')),
            'password'  => trim($request->input('password', '')),
            'role'      => $request->input('role', 'editor'),
            'is_active' => $request->input('is_active', '0') === '1' ? 1 : 0,
        ];
    }

    private function validateUser(array $data, ?int $currentId): array
    {
        $errors = [];

        // Username
        if (empty($data['username'])) {
            $errors['username'] = 'Username is required.';
        } elseif (strlen($data['username']) < 3) {
            $errors['username'] = 'Username must be at least 3 characters.';
        } elseif (!preg_match('/^[a-zA-Z0-9_\-]+$/', $data['username'])) {
            $errors['username'] = 'Username may only contain letters, numbers, underscores and hyphens.';
        } else {
            $existing = User::findWhere(['username' => $data['username']]);
            if ($existing && (int) $existing['id'] !== $currentId) {
                $errors['username'] = 'Username already taken.';
            }
        }

        // Email
        if (empty($data['email'])) {
            $errors['email'] = 'Email address is required.';
        } elseif (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
            $errors['email'] = 'Email address is not valid.';
        } else {
            $existing = User::findWhere(['email' => $data['email']]);
            if ($existing && (int) $existing['id'] !== $currentId) {
                $errors['email'] = 'Email address already in use.';
            }
        }

        // Role
        if (!in_array($data['role'], ['admin', 'editor'], true)) {
            $errors['role'] = 'Invalid role selected.';
        }

        return $errors;
    }
}
