<?php

declare(strict_types=1);

namespace App\Http\Controllers\UserManagement;

use App\Enums\UserActions;
use App\Http\Controllers\Helpers\Permissions\UserPermissions;
use Hypervel\Http\Request;
use App\Enums\UserTypes;
use Hypervel\Support\Facades\Hash;
use Hypervel\Support\Facades\Response;
use App\Models\User;

class CreateUserControllerUltimate
{

    public function listAllUserTypesforSelectHTML()
    {
        $currentUser = \Hypervel\Support\Facades\Auth::user();
        if (!$currentUser) {
            return Response::json([], 200);
        }

        if (!UserPermissions::isActionPermitted($currentUser->acct_type, UserActions::ViewAllUserTypes)) {
            return Response::json(['error' => 'Unauthorized'], 401);
        }

        $currentUserType = $currentUser->acct_type;
        $allowedTypes = \App\Http\Controllers\Helpers\Permissions\UserTypeService::getAllowedUserTypes($currentUserType);

        $formatted = [];
        foreach ($allowedTypes as $case) {
            $label = str_replace('_', ' ', ucwords(strtolower($case->name)));
            $formatted[] = [$case->value, $label];
        }

        return Response::json($formatted);
    }

    public static function listAllUsersforParentSelectHTML(Request $request, $dataResult = false)
    {
        $currentUser = \Hypervel\Support\Facades\Auth::user();

        if (!$currentUser) {
            return Response::json([], 200);
        }

        // Ultimate accounts can see all users
        if ($currentUser->acct_type === UserTypes::ULTIMATE) {
            $allowedIds = null;
        } else {
            // Only show current user and their descendants (direct or indirect children)
            try {
                $descendants = $currentUser->getAllDescendants();
                $allowedIds = $descendants->pluck('id')->toArray();
                $allowedIds[] = $currentUser->id;
            } catch (\Throwable $th) {
                return Response::json([], 200);
            }
        }

        $excludeUser = $request->input('exclude_user', null);
        $typeFilter = $request->input('type', null);

        $usersQuery = User::select(['id', 'username', 'name', 'fullname', 'mobile_number', 'hashkey', 'acct_type']);

        if ($allowedIds !== null) {
            $usersQuery = $usersQuery->whereIn('id', $allowedIds);
        }

        // Exclude the specified user if provided
        if ($excludeUser) {
            $usersQuery = $usersQuery->where('hashkey', '!=', $excludeUser);
        }

        if ($typeFilter) {
            $types = is_array($typeFilter) ? $typeFilter : [$typeFilter];
            $usersQuery = $usersQuery->whereIn('acct_type', $types);
        }

        $users = $usersQuery->get();

        if (!$dataResult) {
            return Response::json($users);
        } else {
            return $users;
        }
    }

    public function CreateUser(Request $request)
    {
        $usertypeString = $request->input('type');

        if (!is_string($usertypeString) || empty($usertypeString)) {
            return Response::json(['error' => 'User type is required'], 400);
        }

        $usertypeEnum = UserTypes::tryFrom($usertypeString);
        if (!$usertypeEnum) {
            return Response::json(['error' => 'Invalid User Type'], 400);
        }

        // Map UserTypes to specialized CreateUser UserActions
        $action = match ($usertypeEnum) {
            UserTypes::ULTIMATE => UserActions::CreateUserUltimate,
            UserTypes::SUPER_OPERATOR => UserActions::CreateUserSuperOperator,
            UserTypes::OPERATOR => UserActions::CreateUserOperator,
            UserTypes::COORDINATOR => UserActions::CreateUserCoordinator,
            UserTypes::SUPPLIER_OVERSEER => UserActions::CreateUserSupplierOverseer,
            UserTypes::WHOLESALE_BUYER => UserActions::CreateUserWholesaleBuyer,
            UserTypes::SUPPLIER => UserActions::CreateUserSupplier,
            UserTypes::STORE_OWNER => UserActions::CreateUserStoreOwner,
            UserTypes::STORE_MANAGER => UserActions::CreateUserStoreManager,
            UserTypes::USER => UserActions::CreateUserUser,
            UserTypes::RIDER => UserActions::CreateUserRider,
            UserTypes::POS_TERMINAL => UserActions::CreateUserPOSTerminal,
            UserTypes::AUDIT => UserActions::CreateUserAudit,
            default => UserActions::CreateUser,
        };

        $currentUser = \Hypervel\Support\Facades\Auth::user();
        $targetParentHash = $request->input('parent');

        if (!$currentUser) {
            return Response::json(['error' => 'Unauthorized'], 401);
        }

        $currentUserType = $currentUser->acct_type;
        if (!($currentUserType instanceof UserTypes)) {
            $currentUserType = UserTypes::tryFrom($currentUserType) ?? UserTypes::PUBLIC;
        }

        if ($currentUserType !== UserTypes::ULTIMATE) {
            // Check the new user's type is in the allowed list for this creator
            $allowedTypes = \App\Http\Controllers\Helpers\Permissions\UserTypeService::getAllowedUserTypes($currentUserType);
            if (!in_array($usertypeEnum, $allowedTypes)) {
                return Response::json(['error' => 'You are not allowed to create this user type.'], 401);
            }

            // Check that the chosen parent is the current user or a descendant
            if ($targetParentHash) {
                $isParentSelfOrDescendant = ($currentUser->hashkey === $targetParentHash)
                    || UserPermissions::isDescendantOfCurrentUser($targetParentHash);
                if (!$isParentSelfOrDescendant) {
                    return Response::json(['error' => 'Parent user is not in your hierarchy.'], 401);
                }
            }
        }



        $mobileRules = ['required', 'string', 'max:20', 'unique:users,mobile_number'];
        if (!UserPermissions::isActionPermitted($currentUser->acct_type, UserActions::BypassMobileNumberFormat)) {
            $mobileRules[] = 'regex:/^(09|\+639)\d{9}$/';
        }

        try {
            $validated = $request->validate([
                'username' => 'required|string|max:255|unique:users,username',
                'name' => 'required|string|max:255',
                'fullname' => 'nullable|string|max:255',
                'mobile_number' => $mobileRules,
                'password' => 'required|string|min:6',
                'nickname' => 'nullable|string|max:255',
                'parent' => 'required|string',
                'type' => 'required|string',
            ]);
        } catch (\Hypervel\Validation\ValidationException $e) {
            return Response::json(['errors' => $e->errors()], 422);
        }

        $parentUser = User::where('hashkey', $validated['parent'])->first();

        if (!$parentUser) {
            return Response::json(['error' => 'Parent user not found'], 404);
        }

        $parent = $parentUser->id;


        $user = new User();
        $user->username = $validated['username'];
        $user->name = $validated['name'];
        $user->fullname = $validated['fullname'] ?? null;
        $user->mobile_number = $validated['mobile_number'];
        $user->password = Hash::make($validated['password']);
        $user->nickname = $validated['nickname'] ?? null;
        $user->parentuid = $parent;
        $user->acct_type = $validated['type'];
        $user->active = true;
        $user->save();

        return Response::json(['success' => true, 'hashkey' => $user->hashkey, 'message' => 'User created successfully'], 201);


    }


    public function checkIfUserMobileNumberExists(Request $request)
    {
        $request->validate([
            'mobile_number' => 'required|string',
        ]);
        $mobileNumber = $request->input('mobile_number');
        $userExists = User::where('mobile_number', $mobileNumber)->exists();
        return Response::json(['exists' => $userExists]);
    }

    public function checkIfUsernameExists(Request $request)
    {
        $request->validate([
            'username' => 'required|string',
        ]);
        $username = $request->input('username');
        $userExists = User::where('username', $username)->exists();
        return Response::json(['exists' => $userExists]);
    }

    public function publicRegisterUser(Request $request)
    {
        try {
            $validated = $request->validate([
                'name' => 'required|string|max:255',
                'mobile_number' => 'required|string|max:20|unique:users,mobile_number|regex:/^(09|\+639)\d{9}$/',
                'password' => 'required|string|min:6',
                'nickname' => 'nullable|string|max:255',
            ]);
        } catch (\Hypervel\Validation\ValidationException $e) {
            return Response::json(['success' => false, 'errors' => $e->errors()], 422);
        }

        $parent = User::where('acct_type', UserTypes::ULTIMATE->value)->orderBy('id')->first();

        if (!$parent) {
            $parent = User::where('acct_type', UserTypes::COORDINATOR->value)->orderBy('id')->first();
        }

        if (!$parent) {
            $parent = User::orderBy('id')->first();
        }

        if (!$parent) {
            return Response::json(['success' => false, 'message' => 'No valid parent user found'], 500);
        }

        $user = new User();
        $user->name = $validated['name'];
        $user->mobile_number = $validated['mobile_number'];
        $user->password = Hash::make($validated['password']);
        $user->nickname = $validated['nickname'] ?? null;
        $user->parentuid = $parent->id;
        $user->acct_type = 'user';
        $user->active = true;
        $user->save();

        return Response::json(['success' => true, 'hashkey' => $user->hashkey, 'message' => 'Account created successfully. Please log in.'], 201);
    }

    public function publicCheckMobileNumber(Request $request)
    {
        $request->validate([
            'mobile_number' => 'required|string',
        ]);

        return Response::json(['exists' => User::where('mobile_number', $request->input('mobile_number'))->exists()]);
    }



}

