<?php

namespace App\Http\Controllers\Menu;

use App\Http\Controllers\ApiController;
use App\Http\Requests\MenuGroup\IndexMenuGroupRequest;
use App\Http\Requests\MenuGroup\StoreMenuGroupRequest;
use App\Http\Requests\MenuGroup\SyncMenuGroupMenusRequest;
use App\Http\Requests\MenuGroup\SyncUserMenuGroupsRequest;
use App\Http\Requests\MenuGroup\UpdateMenuGroupRequest;
use App\Http\Resources\MenuGroup\MenuGroupResource;
use App\Models\MenuGroup;
use App\Models\User;
use App\Services\Access\AccessService;
use App\Services\Menu\MenuGroupService;

class MenuGroupController extends ApiController
{
    public function __construct(
        protected MenuGroupService $service,
        protected AccessService $access
    ) {}

    public function index(IndexMenuGroupRequest $request)
    {
        $data = $this->service->list(
            $request->validated(),
            $request->user(),
            $request->attributes->get('tenant_id')
        );

        return $this->successPaginated(
            $data,
            MenuGroupResource::class,
            'Data Menu Group berhasil diambil'
        );
    }

    public function store(StoreMenuGroupRequest $request)
    {
        $data = $this->service->create(
            $request->validated(),
            $request->user(),
            $request->attributes->get('tenant_id')
        );

        return $this->created(
            new MenuGroupResource($data),
            'Menu Group berhasil dibuat'
        );
    }

    public function show(MenuGroup $menu_group)
    {
        $this->authorizeGroup($menu_group, false);

        return $this->success(
            new MenuGroupResource($menu_group->load('tenant')),
            'Detail Menu Group berhasil diambil'
        );
    }

    public function update(
        UpdateMenuGroupRequest $request,
        MenuGroup $menu_group
    ) {
        $this->authorizeGroup($menu_group, true);
        $data = $this->service->update(
            $menu_group,
            $request->validated(),
            $request->user(),
            $request->attributes->get('tenant_id')
        );

        return $this->updated(
            new MenuGroupResource($data),
            'Menu Group berhasil diupdate'
        );
    }

    public function destroy(MenuGroup $menu_group)
    {
        $this->authorizeGroup($menu_group, true);
        $this->service->delete($menu_group);

        return $this->deleted(
            'Menu Group berhasil dihapus'
        );
    }

    public function menus(MenuGroup $menu_group)
    {
        $this->authorizeGroup($menu_group, false);
        $data = $this->service->listMenus($menu_group);

        return $this->success(
            [
                'menu_group_id' => $menu_group->id,
                'menu_group' => new MenuGroupResource($menu_group),
                'menus' => $data,
            ],
            'Mapping menu group berhasil diambil'
        );
    }

    public function availableMenus(MenuGroup $menu_group)
    {
        $this->authorizeGroup($menu_group, false);
        $user = auth()->user();

        if (! $user) {
            return $this->error('Unauthenticated', 401);
        }

        $data = $this->service->listAvailableMenusForGroup(
            $menu_group,
            $user
        );

        return $this->success(
            [
                'menu_group_id' => $menu_group->id,
                'menu_group' => new MenuGroupResource($menu_group),
                'menus' => $data,
            ],
            'Daftar menu tersedia berdasarkan akses user berhasil diambil'
        );
    }

    public function syncMenus(
        SyncMenuGroupMenusRequest $request,
        MenuGroup $menu_group
    ) {
        $this->authorizeGroup($menu_group, true);
        $user = auth()->user();

        if (! $user) {
            return $this->error('Unauthenticated', 401);
        }

        $this->service->syncMenus(
            $menu_group,
            $request->validated('menus'),
            $user
        );

        return $this->success(
            [
                'menu_group_id' => $menu_group->id,
                'menu_group' => new MenuGroupResource($menu_group->fresh('tenant')),
                'menus' => $this->service->listMenus($menu_group),
            ],
            'Mapping menu group berhasil disimpan'
        );
    }

    public function userAssignments(User $user)
    {
        $tenantId = request()->attributes->get('tenant_id');
        abort_unless($this->access->canManageUser(auth()->user(), $user, $tenantId), 403);

        return $this->success(
            [
                'user_id' => $user->id,
                'assignments' => $this->service->listUserAssignments($user, $tenantId),
            ],
            'Assignment user menu group berhasil diambil'
        );
    }

    public function syncUserAssignments(
        SyncUserMenuGroupsRequest $request,
        User $user
    ) {
        $tenantId = $request->attributes->get('tenant_id');
        abort_unless($this->access->canManageUser($request->user(), $user, $tenantId), 403);

        $this->service->syncUserAssignments(
            $user,
            $request->validated('assignments'),
            $tenantId
        );

        return $this->success(
            [
                'user_id' => $user->id,
                'assignments' => $this->service->listUserAssignments($user, $tenantId),
            ],
            'Assignment user menu group berhasil disimpan'
        );
    }

    private function authorizeGroup(MenuGroup $menuGroup, bool $write): void
    {
        $user = auth()->user();
        $tenantId = request()->attributes->get('tenant_id');

        if ($user->isMasterAdmin()) {
            return;
        }

        $allowed = (int) $menuGroup->tenant_id === (int) $tenantId;

        abort_unless($allowed, 403);
    }
}
