<?php
namespace App\Controllers\Settings;

use App\Controllers\BaseController;
use Config\Database;

class UserController extends BaseController
{
    public function index()
    {
        $db = Database::connect();
        $users = [];
        try {
            $users = $db->table('users')->select('users.*, ai_email.secret as email, ai_username.secret as uname, agu.group as group_name')
                ->join('auth_identities as ai_email', 'ai_email.user_id = users.id AND ai_email.type = "email_password"', 'left')
                ->join('auth_identities as ai_username', 'ai_username.user_id = users.id AND ai_username.type = "username"', 'left')
                ->join('auth_groups_users as agu', 'agu.user_id = users.id', 'left')
                ->orderBy('users.id', 'asc')
                ->get()->getResultArray();
        } catch (\Throwable $e) {
            $users = [];
        }

        // available groups from config
        $groups = array_keys(config('AuthGroups')->groups ?? []);

        return view('settings/users', [
            'title' => lang('App.user_management'),
            'users' => $users,
            'groups' => $groups,
        ]);
    }

    public function create()
    {
        $groups = array_keys(config('AuthGroups')->groups ?? []);
        return view('settings/users_form', [
            'title' => lang('App.user_management'),
            'user' => null,
            'groups' => $groups,
            'errors' => [],
        ]);
    }

    public function store()
    {
        $req = $this->request;
        $db = Database::connect();
        $passwords = service('passwords');

        $username = trim((string) $req->getPost('username'));
        $email = trim((string) $req->getPost('email'));
        $password = (string) $req->getPost('password');
        $group = trim((string) $req->getPost('group'));

        if ($username === '' || $email === '' || $password === '' || $group === '') {
            return redirect()->back()->with('error', 'All fields are required.');
        }

        try {
            // create user
            $db->table('users')->insert([
                'username' => $username,
                'status' => 'active',
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s'),
            ]);
            $userId = $db->insertID();

            // identities
            $db->table('auth_identities')->insert([
                'user_id' => $userId,
                'type' => 'email_password',
                'secret' => $email,
                'secret2' => $passwords->hash($password),
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s'),
            ]);
            $db->table('auth_identities')->insert([
                'user_id' => $userId,
                'type' => 'username',
                'secret' => $username,
                'secret2' => $passwords->hash($password),
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s'),
            ]);

            // group assignment
            $db->table('auth_groups_users')->insert([
                'user_id' => $userId,
                'group' => $group,
                'created_at' => date('Y-m-d H:i:s'),
            ]);

            return redirect()->to('/settings/users')->with('success', 'User created.');
        } catch (\Throwable $e) {
            return redirect()->back()->with('error', 'Failed to create user: ' . $e->getMessage());
        }
    }

    public function edit($id)
    {
        $db = Database::connect();
        $user = null; $email = ''; $group = '';
        try {
            $user = $db->table('users')->where('id', (int)$id)->get()->getRowArray();
            $iden = $db->table('auth_identities')->where('user_id', (int)$id)->get()->getResultArray();
            foreach ($iden as $i) {
                if ($i['type'] === 'email_password') { $email = (string) $i['secret']; }
            }
            $groupRow = $db->table('auth_groups_users')->where('user_id', (int)$id)->get()->getRowArray();
            $group = $groupRow['group'] ?? '';
        } catch (\Throwable $e) { $user = null; }
        $groups = array_keys(config('AuthGroups')->groups ?? []);
        return view('settings/users_form', [
            'title' => lang('App.user_management'),
            'user' => $user,
            'email' => $email,
            'groups' => $groups,
            'currentGroup' => $group,
            'errors' => [],
        ]);
    }

    public function update($id)
    {
        $req = $this->request;
        $db = Database::connect();
        $passwords = service('passwords');

        $username = trim((string) $req->getPost('username'));
        $email = trim((string) $req->getPost('email'));
        $group = trim((string) $req->getPost('group'));
        $password = (string) ($req->getPost('password') ?? '');

        if ($username === '' || $email === '' || $group === '') {
            return redirect()->back()->with('error', 'Username, Email and Group are required.');
        }

        try {
            $db->table('users')->where('id', (int)$id)->update([
                'username' => $username,
                'updated_at' => date('Y-m-d H:i:s'),
            ]);

            // update identities
            $db->table('auth_identities')->where(['user_id' => (int)$id, 'type' => 'email_password'])->update([
                'secret' => $email,
                'updated_at' => date('Y-m-d H:i:s'),
            ]);
            $db->table('auth_identities')->where(['user_id' => (int)$id, 'type' => 'username'])->update([
                'secret' => $username,
                'updated_at' => date('Y-m-d H:i:s'),
            ]);
            if ($password !== '') {
                $hash = $passwords->hash($password);
                $db->table('auth_identities')->where(['user_id' => (int)$id, 'type' => 'email_password'])->update(['secret2' => $hash]);
                $db->table('auth_identities')->where(['user_id' => (int)$id, 'type' => 'username'])->update(['secret2' => $hash]);
            }

            // update group
            $row = $db->table('auth_groups_users')->where('user_id', (int)$id)->get()->getRowArray();
            if ($row) {
                $db->table('auth_groups_users')->where('user_id', (int)$id)->update(['group' => $group]);
            } else {
                $db->table('auth_groups_users')->insert(['user_id' => (int)$id, 'group' => $group, 'created_at' => date('Y-m-d H:i:s')]);
            }

            return redirect()->to('/settings/users')->with('success', 'User updated.');
        } catch (\Throwable $e) {
            return redirect()->back()->with('error', 'Failed to update user: ' . $e->getMessage());
        }
    }

    public function deactivate($id)
    {
        $db = Database::connect();
        try {
            $db->table('users')->where('id', (int)$id)->update(['status' => 'inactive', 'updated_at' => date('Y-m-d H:i:s')]);
            return redirect()->to('/settings/users')->with('success', 'User deactivated.');
        } catch (\Throwable $e) {
            return redirect()->back()->with('error', 'Failed to deactivate user: ' . $e->getMessage());
        }
    }

    // Permissions management
    public function permissions($id)
    {
        $db = Database::connect();
        $user = $db->table('users')->where('id', (int)$id)->get()->getRowArray();
        if (! $user) {
            return redirect()->to('/settings/users')->with('error', 'User not found.');
        }
        $permissionsMap = config('AuthGroups')->permissions ?? [];
        $allPermissions = array_keys($permissionsMap);
        $assignedRows = $db->table('auth_permissions_users')->where('user_id', (int)$id)->get()->getResultArray();
        $assigned = array_map(static fn($r) => $r['permission'], $assignedRows);
        return view('settings/users_permissions', [
            'title' => 'User Permissions',
            'user' => $user,
            'allPermissions' => $allPermissions,
            'permissionsMap' => $permissionsMap,
            'assigned' => $assigned,
        ]);
    }

    public function savePermissions($id)
    {
        $req = $this->request;
        $db = Database::connect();
        $user = $db->table('users')->where('id', (int)$id)->get()->getRowArray();
        if (! $user) {
            return redirect()->to('/settings/users')->with('error', 'User not found.');
        }
        $selected = (array) ($req->getPost('permissions') ?? []);
        // normalize to strings
        $selected = array_values(array_filter(array_map('strval', $selected)));
        try {
            // clear existing
            $db->table('auth_permissions_users')->where('user_id', (int)$id)->delete();
            // insert selected
            foreach ($selected as $perm) {
                $db->table('auth_permissions_users')->insert([
                    'user_id' => (int)$id,
                    'permission' => $perm,
                    'created_at' => date('Y-m-d H:i:s'),
                ]);
            }
            return redirect()->to('/settings/users/permissions/' . (int)$id)->with('success', 'Permissions updated.');
        } catch (\Throwable $e) {
            return redirect()->back()->with('error', 'Failed to update permissions: ' . $e->getMessage());
        }
    }
    public function resetPassword($id)
    {
        $req = $this->request;
        $password = (string) $req->getPost('password');
        if ($password === '') {
            return redirect()->back()->with('error', 'Password is required.');
        }
        $db = Database::connect();
        $hash = service('passwords')->hash($password);
        try {
            $db->table('auth_identities')->where(['user_id' => (int)$id, 'type' => 'email_password'])->update(['secret2' => $hash, 'updated_at' => date('Y-m-d H:i:s')]);
            $db->table('auth_identities')->where(['user_id' => (int)$id, 'type' => 'username'])->update(['secret2' => $hash, 'updated_at' => date('Y-m-d H:i:s')]);
            return redirect()->to('/settings/users')->with('success', 'Password reset.');
        } catch (\Throwable $e) {
            return redirect()->back()->with('error', 'Failed to reset password: ' . $e->getMessage());
        }
    }
}