<?php

namespace App\Http\Controllers\Admin\Manage;

use App\Constants\ItemMasks;
use App\Http\Controllers\Controller;
use App\Http\Requests\Character\BanCharacterRequest;
use App\Http\Requests\Character\CloneCharacterRequest;
use App\Http\Requests\Character\SendMailRequest;
use App\Http\Requests\Character\UpdateExpRequest;
use App\Http\Requests\Character\UpdateLevelRequest;
use App\Http\Requests\Character\UpdatePositionRequest;
use App\Http\Requests\Character\UpdateReputationRequest;
use App\Http\Requests\Character\UpdateStatusRequest;
use App\Services\Api\API;
use App\Services\Character\CharacterActionService;
use App\Services\Character\CharacterInventoryService;
use App\Services\Character\CharacterService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;

class CharacterController extends Controller
{
    protected API $api;

    protected CharacterService $characterService;

    protected CharacterInventoryService $inventoryService;

    protected CharacterActionService $actionService;

    public function __construct(
        API $api,
        CharacterService $characterService,
        CharacterInventoryService $inventoryService,
        CharacterActionService $actionService
    ) {
        $this->api = $api;
        $this->characterService = $characterService;
        $this->inventoryService = $inventoryService;
        $this->actionService = $actionService;
    }

    /**
     * Display character search page
     */
    public function index(Request $request)
    {
        $characters = [];
        $summary = null;
        $username = $request->input('username');
        $roleid = $request->input('roleid');
        $userid = $request->input('userid');

        $isServerOnline = $this->api->online;

        if ($username) {
            $user = \App\Models\User::where('name', $username)->first();
            if ($user) {
                $characters = $this->characterService->searchByUserId($user->ID);
                $cash = $isServerOnline ? $this->getCashSafely($user->ID) : 0;
                $summary = $this->buildSummary($characters, $user->ID, $cash);
            }
        } elseif ($roleid) {
            if (is_numeric($roleid)) {
                $roleData = $this->characterService->searchByRoleId((int) $roleid);
                if ($roleData) {
                    $characters = [$roleData];
                    $userId = $roleData['user_id'] ?? 0;
                    $cash = $isServerOnline ? $this->getCashSafely($userId) : 0;
                    $summary = $this->buildSummary($characters, $userId, $cash);
                    $username = \App\Models\User::where('ID', $userId)->value('name');
                }
            }
        } elseif ($userid) {
            if (is_numeric($userid)) {
                $characters = $this->characterService->searchByUserId((int) $userid);
                $cash = $isServerOnline ? $this->getCashSafely((int) $userid) : 0;
                $summary = $this->buildSummary($characters, (int) $userid, $cash);
            }
        }

        $characters = array_map(function ($char) use ($isServerOnline) {
            $char['cash'] = $isServerOnline ? $this->getCashSafely($char['user_id'] ?? 0) : 0;

            return $char;
        }, $characters);

        return Inertia::render('admin/manage/characters/index', [
            'characters' => $characters,
            'summary' => $summary,
            'filters' => array_merge($request->only(['username', 'roleid', 'userid']), ['username' => $username ?? null]),
            'itemMasks' => ItemMasks::getForSelect(),
        ]);
    }

    /**
     * Get all characters with pagination
     */
    public function getAllRoles(Request $request): JsonResponse
    {
        $page = $request->input('page', 1);
        $perPage = 50;

        $users = \App\Models\User::orderBy('ID', 'asc')
            ->skip(($page - 1) * $perPage)
            ->take($perPage)
            ->get();

        $totalUsers = \App\Models\User::count();
        $characters = [];
        $isServerOnline = $this->api->online;

        $userIdCache = [];
        foreach ($users as $user) {
            $userCharacters = $this->characterService->getAllCharactersForUser($user->ID);

            if ($isServerOnline && ! isset($userIdCache[$user->ID])) {
                $userIdCache[$user->ID] = $this->getCashSafely($user->ID);
            }
            $cash = $isServerOnline ? ($userIdCache[$user->ID] ?? 0) : 0;

            foreach ($userCharacters as &$char) {
                $char['cash'] = $cash;
            }
            unset($char);
            $characters = array_merge($characters, $userCharacters);
        }

        return response()->json([
            'characters' => $characters,
            'pagination' => [
                'current_page' => $page,
                'per_page' => $perPage,
                'total_users' => $totalUsers,
                'total_pages' => ceil($totalUsers / $perPage),
            ],
        ]);
    }

    /**
     * Show character details
     */
    public function show(int $roleId)
    {
        try {
            $isServerOnline = $this->api->online;

            // Try to get character details, but allow access even if server is offline
            $character = $this->characterService->getCharacterDetails($roleId);

            if (! $character) {
                return redirect()->route('admin.manage-characters')
                    ->with('error', 'Character not found or data unavailable');
            }

            $isOnline = $isServerOnline ? $this->characterService->isCharacterOnline($roleId) : false;

            // Always set cash to 0 when server is offline
            $cash = $isServerOnline ? $this->getCashSafely($character['user_id'] ?? 0) : 0;

            // Get raw data for advanced editing - safely handle when server is offline
            $status = [];
            $pocket = [];
            $equipment = [];
            $storehouse = [];

            if ($isServerOnline) {
                try {
                    $status = $this->api->getRoleStatus($roleId) ?? [];
                    $pocket = $this->normalizePocketData($this->api->getRoleInventory($roleId) ?? []);
                    $equipment = $this->normalizeEquipmentData($this->api->getRoleEquipment($roleId) ?? []);
                    $storehouse = $this->normalizeStorehouseData($this->api->getRoleStorehouse($roleId) ?? []);
                } catch (\Exception $apiException) {
                    // If API calls fail, use empty arrays
                    \Log::warning('Failed to load character data from API', [
                        'role_id' => $roleId,
                        'error' => $apiException->getMessage(),
                    ]);
                }
            }

            return Inertia::render('admin/manage/characters/show', [
                'character' => $character,
                'is_online' => $isOnline,
                'cash' => $cash,
                'raw_data' => [
                    'status' => $status,
                    'pocket' => $pocket,
                    'equipment' => $equipment,
                    'storehouse' => $storehouse,
                ],
                'itemMasks' => ItemMasks::getForSelect(),
                'serverOnline' => $isServerOnline,
            ]);
        } catch (\Exception $e) {
            return redirect()->route('admin.manage-characters')
                ->with('error', 'Failed to load character: '.$e->getMessage());
        }
    }

    /**
     * Update character data
     */
    public function update(Request $request, int $roleId): JsonResponse
    {
        $validated = $request->validate([
            'section' => 'required|string|in:base,status,equipment,pocket',
            'data' => 'required|array',
        ]);

        try {
            $section = $validated['section'];

            // Handle inventory sections
            if (in_array($section, ['pocket', 'equipment'])) {
                $result = $this->inventoryService->updateInventorySection($roleId, $validated['data'], $section);

                if (! $result['success']) {
                    return response()->json(['error' => $result['message']], 400);
                }

                return response()->json(['message' => $result['message']]);
            }

            // Handle status updates
            if ($section === 'status') {
                $success = $this->characterService->updateCharacterStatus($roleId, $validated['data']);

                if (! $success) {
                    return response()->json(['error' => 'Failed to update status'], 400);
                }

                return response()->json(['message' => 'Status updated successfully']);
            }

            // Handle base updates
            if ($section === 'base') {
                $success = $this->characterService->updateCharacterBase($roleId, $validated['data']);

                if (! $success) {
                    return response()->json(['error' => 'Failed to update base'], 400);
                }

                return response()->json(['message' => 'Base updated successfully']);
            }

            return response()->json(['error' => 'Section not supported for update'], 400);
        } catch (\Exception $e) {
            return response()->json(['error' => 'Update failed: '.$e->getMessage()], 400);
        }
    }

    /**
     * Update character level
     */
    public function updateLevel(UpdateLevelRequest $request, int $roleId): JsonResponse
    {
        try {
            $success = $this->characterService->updateCharacterStatus($roleId, $request->validated());

            if (! $success) {
                return response()->json(['error' => 'Failed to update level'], 400);
            }

            return response()->json(['message' => 'Level updated successfully']);
        } catch (\Exception $e) {
            return response()->json(['error' => 'Update failed: '.$e->getMessage()], 400);
        }
    }

    /**
     * Update character exp/sp
     */
    public function updateExp(UpdateExpRequest $request, int $roleId): JsonResponse
    {
        try {
            $success = $this->characterService->updateCharacterStatus($roleId, $request->validated());

            if (! $success) {
                return response()->json(['error' => 'Failed to update exp/sp'], 400);
            }

            return response()->json(['message' => 'EXP/SP updated successfully']);
        } catch (\Exception $e) {
            return response()->json(['error' => 'Update failed: '.$e->getMessage()], 400);
        }
    }

    /**
     * Update character reputation
     */
    public function updateReputation(UpdateReputationRequest $request, int $roleId): JsonResponse
    {
        try {
            $success = $this->characterService->updateCharacterStatus($roleId, $request->validated());

            if (! $success) {
                return response()->json(['error' => 'Failed to update reputation'], 400);
            }

            return response()->json(['message' => 'Reputation updated successfully']);
        } catch (\Exception $e) {
            return response()->json(['error' => 'Update failed: '.$e->getMessage()], 400);
        }
    }

    /**
     * Update character position (teleport)
     */
    public function updatePosition(UpdatePositionRequest $request, int $roleId): JsonResponse
    {
        $result = $this->actionService->teleportCharacter($roleId, $request->validated());

        if (! $result['success']) {
            return response()->json(['error' => $result['message']], 400);
        }

        return response()->json(['message' => $result['message']]);
    }

    /**
     * Update character status field
     */
    public function updateStatus(UpdateStatusRequest $request, int $roleId): JsonResponse
    {
        try {
            $field = $request->input('field');
            $newValue = $request->input('value', '');

            // Get field type from protocol definition
            $statusDef = $this->api->data['role']['status'] ?? [];
            $fieldType = $statusDef[$field] ?? null;

            // For octets fields with empty value, use resetOctetsField method
            if ($fieldType === 'octets' && empty($newValue)) {
                $result = $this->api->resetOctetsField($roleId, $field);

                if (! $result['success']) {
                    return response()->json(['error' => $result['message']], 400);
                }

                return response()->json([
                    'message' => ucfirst(str_replace('_', ' ', $field)).' reset successfully',
                ]);
            }

            // For octets fields with non-empty value, use updateStatusField
            if ($fieldType === 'octets') {
                $result = $this->characterService->updateStatusField($roleId, $field, $newValue);

                if (! $result['success']) {
                    return response()->json(['error' => $result['message']], 400);
                }

                return response()->json([
                    'message' => ucfirst(str_replace('_', ' ', $field)).' updated successfully',
                ]);
            }

            // For non-octets fields, use standard update
            $success = $this->characterService->updateCharacterStatus($roleId, [$field => $newValue]);

            if (! $success) {
                return response()->json(['error' => 'Failed to update status'], 400);
            }

            return response()->json([
                'message' => ucfirst(str_replace('_', ' ', $field)).' updated successfully',
            ]);
        } catch (\Exception $e) {
            return response()->json(['error' => 'Update failed: '.$e->getMessage()], 400);
        }
    }

    /**
     * Remove storehouse password
     */
    public function removeStorehousePassword(Request $request, int $roleId): JsonResponse
    {
        $result = $this->api->clearStorehousePassword($roleId);

        if (! $result['success']) {
            return response()->json(['error' => $result['message']], 400);
        }

        return response()->json(['message' => 'Storehouse password removed successfully']);
    }

    /**
     * Remove specific items from inventory
     */
    public function removeItems(Request $request, int $roleId): JsonResponse
    {
        $validated = $request->validate([
            'items' => 'required|array',
            'items.*.pos' => 'required|integer',
            'items.*.location' => 'required|string|in:pocket,storehouse,equipment',
        ]);

        $deletedCount = 0;
        $errors = [];

        foreach ($validated['items'] as $item) {
            $pos = $item['pos'];
            $location = $item['location'];

            try {
                $result = $this->api->deleteItem($roleId, $pos, $location);

                if ($result['success']) {
                    $deletedCount++;
                } else {
                    $errors[] = "Failed to delete item at position {$pos} in {$location}";
                }
            } catch (\Exception $e) {
                $errors[] = "Error deleting item at position {$pos}: ".$e->getMessage();
            }
        }

        if (! empty($errors)) {
            return response()->json([
                'message' => "{$deletedCount} items deleted with some errors",
                'deleted' => $deletedCount,
                'errors' => $errors,
            ], 207); // 207 Multi-Status
        }

        return response()->json([
            'message' => "{$deletedCount} items deleted successfully",
            'deleted' => $deletedCount,
        ]);
    }

    /**
     * Get faction info for character
     */
    public function getFactionInfo(int $roleId): JsonResponse
    {
        $factionData = $this->characterService->getFactionInfo($roleId);

        return response()->json($factionData);
    }

    /**
     * Ban or mute character
     */
    public function ban(BanCharacterRequest $request, int $roleId): JsonResponse
    {
        $result = $this->actionService->punishCharacter($roleId, $request->validated());

        return response()->json($result);
    }

    /**
     * Send mail to character
     */
    public function sendMail(SendMailRequest $request, int $roleId): JsonResponse
    {
        $result = $this->actionService->sendMail($roleId, $request->validated());

        if (! $result['success']) {
            return response()->json(['error' => $result['message']], 400);
        }

        return response()->json(['message' => $result['message']]);
    }

    /**
     * Get online characters
     */
    public function getOnlineCharacters(): JsonResponse
    {
        $result = $this->actionService->getOnlineCharacters();

        return response()->json($result);
    }

    /**
     * Check if character is online
     */
    public function isOnline(int $roleId): JsonResponse
    {
        $isOnline = $this->characterService->isCharacterOnline($roleId);

        return response()->json(['is_online' => $isOnline]);
    }

    /**
     * Get character inventory
     */
    public function getInventory(int $roleId): JsonResponse
    {
        $inventory = $this->inventoryService->getInventory($roleId);

        return response()->json($inventory);
    }

    /**
     * Get character equipment
     */
    public function getEquipment(int $roleId): JsonResponse
    {
        $equipment = $this->inventoryService->getEquipment($roleId);

        return response()->json($equipment);
    }

    /**
     * Get character storehouse
     */
    public function getStorehouse(int $roleId): JsonResponse
    {
        $storehouse = $this->inventoryService->getStorehouse($roleId);

        return response()->json($storehouse);
    }

    /**
     * Search for a role by name
     */
    public function searchRoleByName(Request $request): JsonResponse
    {
        $name = $request->input('name');

        if (empty($name) || strlen($name) < 2) {
            return response()->json(['error' => 'Name must be at least 2 characters'], 400);
        }

        $roleData = $this->characterService->searchByName($name);

        if (! $roleData) {
            return response()->json(['error' => 'Role not found', 'found' => false], 404);
        }

        return response()->json([
            'found' => true,
            'role' => [
                'id' => $roleData['id'],
                'name' => $roleData['name'],
                'level' => $roleData['level'] ?? null,
                'class' => $roleData['class'] ?? null,
            ],
        ]);
    }

    /**
     * Clone character data
     */
    public function cloneRole(CloneCharacterRequest $request): JsonResponse
    {
        $result = $this->actionService->cloneCharacter(
            $request->input('source_role_id'),
            $request->input('target_role_id'),
            $request->input('sections')
        );

        if (! $result['success']) {
            return response()->json(['error' => $result['message'] ?? 'Clone failed'], 400);
        }

        return response()->json($result);
    }

    /**
     * Decode item hex data using PwHexParser
     */
    public function decodeItem(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'item_id' => 'required|integer',
            'data' => 'required|string',
            'mask' => 'nullable|integer',
        ]);

        $itemId = $validated['item_id'];
        $hexData = $validated['data'];
        $mask = $validated['mask'] ?? null;

        // If mask is not provided or is 0, try to lookup from RAE table
        if (empty($mask) && $itemId > 0) {
            $mask = $this->getItemMaskFromRAE($itemId);
        }

        // If hex data is empty or too short, return empty result
        if (strlen($hexData) < 8) {
            return response()->json([
                'success' => false,
                'error' => 'Hex data too short',
                'decoded' => null,
            ]);
        }

        try {
            $decodeService = new \App\Services\ItemDecodeService;
            // Use 0 as default itemId if not provided, just for decoding structure it might not matter much
            // but for specific overrides it might. The mask is handled inside usage of service if we pass it?
            // ItemDecodeService::decode($hexString, $itemId, $mask)

            $result = $decodeService->decode($hexData, $itemId, $mask);

            if (! $result['success']) {
                return response()->json($result);
            }

            return response()->json($result);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'error' => 'Decode failed: '.$e->getMessage(),
                'decoded' => null,
            ]);
        }
    }

    /**
     * Get item mask from RAE_Exported_Table.tab
     */
    private function getItemMaskFromRAE(int $itemId): ?int
    {
        $cacheKey = "rae_item_mask_{$itemId}";

        return \Illuminate\Support\Facades\Cache::remember($cacheKey, 3600, function () use ($itemId) {
            $filePath = public_path('img/RAE_Exported_Table.tab');
            if (! file_exists($filePath)) {
                return null;
            }

            $handle = fopen($filePath, 'r');
            if (! $handle) {
                return null;
            }

            try {
                while (($line = fgets($handle)) !== false) {
                    $line = trim($line);
                    if (empty($line)) {
                        continue;
                    }

                    // Split by tab character
                    $parts = explode("\t", $line);

                    // Ensure we have at least ID column
                    if (count($parts) >= 1) {
                        $id = (int) trim($parts[0]);

                        if ($id === $itemId) {
                            // RAE table format varies, mask can be in different columns
                            // Scan all columns from index 4 onwards for valid mask values
                            // Prefer the rightmost valid mask (often the last column)
                            $foundMask = null;
                            for ($i = 4; $i < count($parts); $i++) {
                                if (isset($parts[$i])) {
                                    $potentialMask = (int) trim($parts[$i]);
                                    // Valid masks: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, etc.
                                    // They should be powers of 2 or certain combinations
                                    if ($potentialMask > 0 && $potentialMask < 100000000) {
                                        $foundMask = $potentialMask;
                                    }
                                }
                            }

                            return $foundMask;
                        }
                    }
                }
            } finally {
                fclose($handle);
            }

            return null;
        });
    }

    /**
     * Get addons map from RAE_Addons.tab
     */
    private function getAddonsMap(): array
    {
        return \Illuminate\Support\Facades\Cache::remember('rae_addons_map', 3600, function () {
            $filePath = public_path('img/RAE_Addons.tab');
            if (! file_exists($filePath)) {
                return [];
            }

            $addons = [];
            $content = file_get_contents($filePath);

            $lines = explode("\n", $content);
            foreach ($lines as $line) {
                $line = trim($line);
                if (empty($line)) {
                    continue;
                }

                // Format: ID;ParamCount;Type;Description
                $parts = explode(';', $line);
                if (count($parts) >= 4) {
                    $id = (int) $parts[0];
                    $type = (int) $parts[2];
                    $desc = trim($parts[3]);
                    $addons[$id] = [
                        'desc' => $desc,
                        'type' => $type,
                    ];
                }
            }

            return $addons;
        });
    }

    /**
     * Get skill description from skillstr.txt file
     *
     * @param  int  $skillId  The skill ID to look up
     * @return string|null The skill description or null if not found
     */
    private function getSkillDescription(int $skillId): ?string
    {
        try {
            $filePath = public_path('img/skillstr.txt');

            if (! file_exists($filePath)) {
                return null;
            }

            // Use cache to avoid reading file on every request
            $cacheKey = "skill_desc_{$skillId}";

            return \Illuminate\Support\Facades\Cache::remember($cacheKey, 3600, function () use ($filePath, $skillId) {
                // Read file content and detect encoding
                $content = file_get_contents($filePath);
                if ($content === false) {
                    return null;
                }

                // Check if file is UTF-16 (BOM: FF FE)
                if (substr($content, 0, 2) === "\xFF\xFE") {
                    // Convert UTF-16 LE to UTF-8
                    $content = mb_convert_encoding($content, 'UTF-8', 'UTF-16LE');
                } elseif (substr($content, 0, 2) === "\xFE\xFF") {
                    // Convert UTF-16 BE to UTF-8
                    $content = mb_convert_encoding($content, 'UTF-8', 'UTF-16BE');
                }

                // Split content into lines
                $lines = explode("\n", $content);

                $found = false;
                $description = '';

                foreach ($lines as $line) {
                    // If we found the skill ID, collect description lines
                    if ($found) {
                        // Check if this line starts with a new ID (number followed by tab)
                        if (preg_match('/^\d+\t/', trim($line))) {
                            break;
                        }

                        // Append line to description
                        $lineContent = rtrim($line, "\r\n");
                        $description .= $lineContent.' ';

                        // Check if description ends with closing quote
                        $trimmed = trim($description);
                        if (substr($trimmed, -1) === '"') {
                            $description = str_replace('"', '', $description);
                            $description = preg_replace('/\s+/', ' ', $description);

                            return trim($description);
                        }

                        continue;
                    }

                    // Skip empty lines
                    $trimmedLine = trim($line);
                    if (empty($trimmedLine)) {
                        continue;
                    }

                    // Split by tab character (limit to 2 parts)
                    $parts = explode("\t", $trimmedLine, 2);

                    // Ensure we have at least 2 columns (ID, description)
                    if (count($parts) >= 2) {
                        $id = (int) trim($parts[0]);

                        if ($id === $skillId) {
                            $found = true;
                            // Start with the description part
                            $description = $parts[1];

                            // If description already ends with closing quote on same line
                            $trimmed = rtrim($description);
                            if (substr($trimmed, -1) === '"') {
                                $description = str_replace('"', '', $description);
                                $description = preg_replace('/\s+/', ' ', $description);

                                return trim($description);
                            }
                        }
                    }
                }

                // If we found the skill but description wasn't closed, return what we have
                if ($found && ! empty($description)) {
                    $description = str_replace('"', '', $description);
                    $description = preg_replace('/\s+/', ' ', $description);

                    return trim($description);
                }

                return null;
            });
        } catch (\Exception $e) {
            return null;
        }
    }

    /**
     * Set meridian level (1-80) with auto-generated hex data using putRole API
     */
    public function setMeridianLevel(Request $request, int $roleId): JsonResponse
    {
        $validated = $request->validate([
            'level' => 'required|integer|min:1|max:80',
        ]);

        $level = $validated['level'];

        // Use setMeridianLevelWithPutRole for online character support
        $result = $this->api->setMeridianLevelWithPutRole($roleId, $level);

        if (! $result['success']) {
            return response()->json(['error' => $result['message']], 400);
        }

        return response()->json([
            'message' => "Meridian level set to {$level} successfully",
            'level' => $level,
            'hex_data' => $result['new_meridian'],
        ]);
    }

    private function getCashSafely(int $userId): int
    {
        try {
            return $this->api->getCurrentCash($userId);
        } catch (\Exception $e) {
            return 0;
        }
    }

    private function buildSummary(array $characters, int $userId, int $cash): array
    {
        $totalPlaytime = 0;
        $lastChar = '';
        $leaderCount = 0;

        foreach ($characters as $char) {
            $totalPlaytime += ($char['time_used'] ?? 0) / 3600;
            $leaderCount++;
            if (empty($lastChar) || ($char['level'] ?? 0) > 0) {
                $lastChar = $char['name'] ?? '';
            }
        }

        return [
            'playtime' => round($totalPlaytime, 1),
            'roles_count' => count($characters),
            'current_cash' => $cash,
            'last_char' => $lastChar,
            'leader_roles_count' => $leaderCount,
        ];
    }

    private function normalizePocketData(array $pocket): array
    {
        return array_merge([
            'icapacity' => 0,
            'timestamp' => 0,
            'money' => 0,
            'inv' => [],
            'reserved6' => 0,
            'reserved7' => 0,
        ], $pocket, [
            'inv' => $pocket['inv'] ?? [],
        ]);
    }

    private function normalizeEquipmentData(array $equipment): array
    {
        return array_merge([
            'eqp' => [],
        ], $equipment, [
            'eqp' => $equipment['eqp'] ?? [],
        ]);
    }

    private function normalizeStorehouseData(array $storehouse): array
    {
        return array_merge([
            'capacity' => 0,
            'money' => 0,
            'store' => [],
            'size1' => 0,
            'size2' => 0,
            'dress' => [],
            'material' => [],
            'size3' => 0,
            'generalcard' => [],
            'reserved' => 0,
        ], $storehouse, [
            'store' => $storehouse['store'] ?? [],
            'dress' => $storehouse['dress'] ?? [],
            'material' => $storehouse['material'] ?? [],
            'generalcard' => $storehouse['generalcard'] ?? [],
        ]);
    }
}
