<?php

declare(strict_types=1);

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Helpers\ResponseHelper;
use App\Models\Market\PosAccessKey;
use App\Models\Market\Store;
use App\Models\User;
use Hypervel\Http\Request;
use Hypervel\Support\Facades\Auth;
use Hyperf\Stringable\Str;
use App\Http\Controllers\Helpers\Permissions\UserPermissions;
use App\Enums\UserActions;

class PosAccessKeyController
{
    /**
     * List POS access keys. Auto-expires any past-due keys first.
     * - Ultimate/super operator/operator: see all keys
     * - Store owner/manager: see keys for stores they own or manage
     */
    public function index(Request $request)
    {
        if (!UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::ViewPosAccessKeys)) {
            return ResponseHelper::returnUnauthorized();
        }

        // Auto-deactivate any expired keys
        PosAccessKey::autoExpire();

        $user = Auth::user();
        $acctType = $user->acct_type->value ?? $user->acct_type ?? '';

        // Ultimate, Super Operator, and Operator see everything
        if (in_array($acctType, ['ult', 'super operator', 'operator'])) {
            $query = PosAccessKey::with(['store:id,name,hashkey,owner_id', 'store.owner:id,name,nickname,hashkey'])
                ->orderBy('id', 'desc');
        } else {
            // Non-ultimate users see their own and their descendants' stores' keys
            $descendants = $user->getAllDescendants();
            $descendantIds = $descendants->pluck('id')->push($user->id)->toArray();

            $storeIds = Store::whereIn('owner_id', $descendantIds)
                ->orWhereIn('manager_id', $descendantIds)
                ->pluck('id')
                ->toArray();

            $query = PosAccessKey::with(['store:id,name,hashkey,owner_id', 'store.owner:id,name,nickname,hashkey'])
                ->whereIn('store_id', $storeIds)
                ->orderBy('id', 'desc');
        }

        $keys = $query->get();

        return ResponseHelper::returnSuccessResponse($keys, 'pos_access_keys');
    }

    public function store(Request $request)
    {
        if (!UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::CreatePosAccessKey)) {
            return ResponseHelper::returnUnauthorized();
        }

        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'store_hash' => 'required|string',
            'expires_at' => 'nullable|string',
        ]);

        $store = Store::where('hashkey', $validated['store_hash'])->first();
        if (!$store) {
            return ResponseHelper::returnError('Store not found', 404);
        }

        $user = Auth::user();
        $acctType = $user->acct_type->value ?? $user->acct_type ?? '';
        if (!in_array($acctType, ['ult', 'super operator', 'operator'])) {
            $descendants = $user->getAllDescendants();
            $allowedIds = $descendants->pluck('id')->push($user->id)->toArray();
            if (!in_array($store->owner_id, $allowedIds) && !in_array($store->manager_id, $allowedIds)) {
                return ResponseHelper::returnError('Unauthorized to create keys for this store', 403);
            }
        }

        $data = [
            'access_key' => 'PK-' . Str::upper(Str::random(16)),
            'store_id' => $store->id,
            'name' => $validated['name'],
            'created_by' => Auth::id(),
            'status' => 'active',
        ];

        // Set expiry if provided
        if (!empty($validated['expires_at'])) {
            $data['expires_at'] = $validated['expires_at'];
        }

        $key = PosAccessKey::create($data);

        return ResponseHelper::returnSuccessResponse($key, $key->hashkey, 'POS Access Key created');
    }

    public function destroy(Request $request)
    {
        if (!UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::DeletePosAccessKey)) {
            return ResponseHelper::returnUnauthorized();
        }

        $hashkey = $request->input('target');
        $key = PosAccessKey::with('store')->where('hashkey', $hashkey)->first();

        if (!$key) {
            return ResponseHelper::returnError('Key not found', 404);
        }

        if (!$this->userOwnsKeyStore($key)) {
            return ResponseHelper::returnError('Unauthorized to delete this key', 403);
        }

        $key->delete();
        return ResponseHelper::returnSuccessResponse([], $hashkey, 'Key deleted');
    }

    public function toggleStatus(Request $request)
    {
        if (!UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::TogglePosAccessKey)) {
            return ResponseHelper::returnUnauthorized();
        }

        $hashkey = $request->input('target');
        $key = PosAccessKey::with('store')->where('hashkey', $hashkey)->first();

        if (!$key) {
            return ResponseHelper::returnError('Key not found', 404);
        }

        if (!$this->userOwnsKeyStore($key)) {
            return ResponseHelper::returnError('Unauthorized to modify this key', 403);
        }

        $key->status = $key->status === 'active' ? 'inactive' : 'active';
        $key->save();
        return ResponseHelper::returnSuccessResponse($key, $hashkey, 'Status updated');
    }

    /**
     * Ownership gate shared by destroy/toggleStatus: Big 3 always pass;
     * everyone else must own or manage (directly or via descendants) the
     * store the key belongs to.
     */
    private function userOwnsKeyStore(PosAccessKey $key): bool
    {
        $user = Auth::user();
        if (!$user) {
            return false;
        }

        $acctType = $user->acct_type->value ?? $user->acct_type ?? '';
        if (in_array($acctType, ['ult', 'super operator', 'operator'])) {
            return true;
        }

        $store = $key->store;
        if (!$store) {
            return false;
        }

        $allowedIds = $user->getAllDescendants()->pluck('id')->push($user->id)->toArray();
        return in_array($store->owner_id, $allowedIds) || in_array($store->manager_id, $allowedIds);
    }
}

