<?php

namespace App\Services\Character;

use App\Services\Api\API;

class CharacterService
{
    protected API $api;
    // Class names are now in config/game.php

    public function __construct(API $api)
    {
        $this->api = $api;
    }

    /**
     * Get faction info for a role
     */
    public function getRoleFactionInfo(int $roleId): array
    {
        try {
            $userFaction = $this->api->getUserFaction($roleId);
            if (isset($userFaction['fid']) && $userFaction['fid'] > 0) {
                $factionInfo = $this->api->getFactionInfo($userFaction['fid']);

                return [
                    'faction_id' => $userFaction['fid'],
                    'faction_name' => $factionInfo['name'] ?? null,
                ];
            }
        } catch (\Exception $e) {
            // Ignore errors
        }

        return ['faction_id' => 0, 'faction_name' => null];
    }

    /**
     * Format character data for display
     */
    public function formatRoleData(array $role): array
    {
        $base = $role['base'] ?? [];
        $status = $role['status'] ?? [];

        return [
            'id' => $base['id'] ?? 0,
            'name' => $base['name'] ?? '',
            'user_id' => $base['userid'] ?? 0,
            'level' => $status['level'] ?? 0,
            'level2' => $status['level2'] ?? 0,
            'class' => $base['cls'] ?? 0,
            'class_name' => config('game.classes')[$base['cls'] ?? 0] ?? 'Unknown',
            'gender' => $base['gender'] ?? 0,
            'gender_name' => ($base['gender'] ?? 0) ? 'Female' : 'Male',
            'exp' => $status['exp'] ?? 0,
            'sp' => $status['sp'] ?? 0,
            'reputation' => $status['reputation'] ?? 0,
            'position' => [
                'x' => $status['posx'] ?? 0,
                'y' => $status['posy'] ?? 0,
                'z' => $status['posz'] ?? 0,
                'worldtag' => $status['worldtag'] ?? 0,
            ],
            'has_storehouse_password' => ! empty($status['storehousepasswd'] ?? ''),
            'inventory' => $role['pocket']['inv'] ?? [],
            'equipment' => $role['equipment']['eqp'] ?? [],
            'storehouse' => $role['storehouse']['store'] ?? [],
        ];
    }

    /**
     * Create character array with basic data
     */
    private function createCharacterArray(array $role, int $userId, array $factionInfo): array
    {
        return [
            'id' => $role['id'],
            'name' => $role['name'],
            'user_id' => $userId,
            'level' => 0,
            'level2' => 0,
            'class' => 0,
            'class_name' => 'Unknown',
            'gender' => 0,
            'faction_id' => $factionInfo['faction_id'],
            'faction_name' => $factionInfo['faction_name'],
        ];
    }

    /**
     * Create character array with detailed data
     */
    private function createDetailedCharacterArray(array $base, array $status, int $userId, array $factionInfo): array
    {
        return [
            'id' => $base['id'] ?? 0,
            'name' => $base['name'] ?? '',
            'user_id' => $userId,
            'level' => $status['level'] ?? 0,
            'level2' => $status['level2'] ?? 0,
            'class' => $base['cls'] ?? 0,
            'class_name' => config('game.classes')[$base['cls'] ?? 0] ?? 'Unknown',
            'gender' => $base['gender'] ?? 0,
            'faction_id' => $factionInfo['faction_id'],
            'faction_name' => $factionInfo['faction_name'],
        ];
    }

    /**
     * Get character base data with error handling
     */
    public function getCharacterBaseData(int $roleId): ?array
    {
        try {
            return $this->api->getRoleBase($roleId);
        } catch (\Exception $e) {
            return null;
        }
    }

    /**
     * Get character status data with error handling
     */
    public function getCharacterStatusData(int $roleId): ?array
    {
        try {
            return $this->api->getRoleStatus($roleId);
        } catch (\Exception $e) {
            return null;
        }
    }

    /**
     * Build character data array safely
     */
    public function buildCharacterData(?array $base, ?array $status, array $role, int $userId): array
    {
        $factionInfo = $this->getRoleFactionInfo($role['id']);

        if ($base && $status) {
            return $this->createDetailedCharacterArray($base, $status, $userId, $factionInfo);
        }

        return $this->createCharacterArray($role, $userId, $factionInfo);
    }

    /**
     * Check if character is online
     */
    public function isCharacterOnline(int $roleId): bool
    {
        $onlineList = $this->api->getOnlineList();

        return collect($onlineList)->contains('roleid', $roleId);
    }

    /**
     * Get class name by ID
     */
    public function getClassName(int $classId): string
    {
        return config('game.classes')[$classId] ?? 'Unknown';
    }

    /**
     * Search for characters by user ID
     */
    public function searchByUserId(int $userId): array
    {
        try {
            $rolesData = $this->api->getRoles($userId);
            $characters = [];

            foreach ($rolesData['roles'] ?? [] as $role) {
                try {
                    $base = $this->getCharacterBaseData($role['id']);
                    $status = $this->getCharacterStatusData($role['id']);

                    if ($base) {
                        $factionInfo = $this->getRoleFactionInfo($role['id']);
                        $characters[] = [
                            'id' => $role['id'],
                            'name' => $role['name'],
                            'user_id' => $userId,
                            'level' => $status['level'] ?? 0,
                            'level2' => $status['level2'] ?? 0,
                            'class' => $base['cls'] ?? 0,
                            'class_name' => config('game.classes')[$base['cls'] ?? 0] ?? 'Unknown',
                            'gender' => $base['gender'] ?? 0,
                            'faction_id' => $factionInfo['faction_id'],
                            'faction_name' => $factionInfo['faction_name'],
                        ];
                    } else {
                        // If base data fails, still show the character with basic info
                        $factionInfo = $this->getRoleFactionInfo($role['id']);
                        $characters[] = [
                            'id' => $role['id'],
                            'name' => $role['name'],
                            'user_id' => $userId,
                            'level' => 0,
                            'level2' => 0,
                            'class' => 0,
                            'class_name' => 'Unknown',
                            'gender' => 0,
                            'faction_id' => $factionInfo['faction_id'],
                            'faction_name' => $factionInfo['faction_name'],
                        ];
                    }
                } catch (\Exception $e) {
                    // If any error occurs, still show the character with minimal info
                    $characters[] = [
                        'id' => $role['id'],
                        'name' => $role['name'],
                        'user_id' => $userId,
                        'level' => 0,
                        'level2' => 0,
                        'class' => 0,
                        'class_name' => 'Unknown',
                        'gender' => 0,
                        'faction_id' => 0,
                        'faction_name' => null,
                    ];
                }
            }

            return $characters;
        } catch (\Exception $e) {
            return [];
        }
    }

    /**
     * Search for characters by role ID
     */
    public function searchByRoleId(int $roleId): ?array
    {
        $base = $this->getCharacterBaseData($roleId);
        $status = $this->getCharacterStatusData($roleId);

        if (! $base) {
            return null;
        }

        $factionInfo = $this->getRoleFactionInfo($roleId);

        return $this->createDetailedCharacterArray($base, $status, $base['userid'] ?? 0, $factionInfo);
    }

    /**
     * Search for characters by name
     */
    public function searchByName(string $name): ?array
    {
        $roleId = $this->api->getRoleid($name);
        if (! $roleId || $roleId <= 0) {
            return null;
        }

        return $this->searchByRoleId($roleId);
    }

    /**
     * Get full character details with all data
     */
    public function getCharacterDetails(int $roleId): ?array
    {
        try {
            $base = $this->getCharacterBaseData($roleId);
            if (! $base) {
                return null;
            }

            $status = $this->getCharacterStatusData($roleId) ?? [];
            $pocket = [];
            $equipment = [];
            $storehouse = [];

            // Only try to get inventory data if server is online
            try {
                $pocket = $this->api->getRoleInventory($roleId) ?? [];
                $equipment = $this->api->getRoleEquipment($roleId) ?? [];
                $storehouse = $this->api->getRoleStorehouse($roleId) ?? [];
            } catch (\Exception $e) {
                // Inventory data not available when server is offline
            }

            $roleData = [
                'base' => $base,
                'status' => $status,
                'pocket' => $pocket,
                'equipment' => $equipment,
                'storehouse' => $storehouse,
            ];

            return $this->formatRoleData($roleData);
        } catch (\Exception $e) {
            return null;
        }
    }

    /**
     * Update character status fields
     */
    public function updateCharacterStatus(int $roleId, array $data): bool
    {
        try {
            $result = $this->api->updateStatusFields($roleId, $data);

            return $result['success'];
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * Update character base fields
     */
    public function updateCharacterBase(int $roleId, array $data): bool
    {
        try {
            $base = $this->api->getRoleBase($roleId);
            if (! $base) {
                return false;
            }

            foreach ($data as $key => $value) {
                $base[$key] = $value;
            }

            $gamed = $this->api->gamed;
            $pack = pack('N*', -1, $roleId).$gamed->marshal($base, $this->api->data['role']['base']);
            $gamed->SendToGamedBD($gamed->createHeader($this->api->data['code']['putRoleBase'], $pack));

            return true;
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * Update a single status field (for octets fields)
     */
    public function updateStatusField(int $roleId, string $field, $value): array
    {
        return $this->api->updateStatusField($roleId, $field, $value);
    }

    /**
     * Get all characters for pagination
     */
    public function getAllCharactersForUser(int $userId): array
    {
        try {
            $rolesData = $this->api->getRoles($userId);
            $characters = [];

            foreach ($rolesData['roles'] ?? [] as $role) {
                try {
                    $base = $this->getCharacterBaseData($role['id']);
                    $status = $this->getCharacterStatusData($role['id']);

                    if ($base) {
                        $factionInfo = $this->getRoleFactionInfo($role['id']);
                        $characters[] = [
                            'id' => $role['id'],
                            'name' => $role['name'],
                            'user_id' => $userId,
                            'level' => $status['level'] ?? 0,
                            'level2' => $status['level2'] ?? 0,
                            'class' => $base['cls'] ?? 0,
                            'class_name' => config('game.classes')[$base['cls'] ?? 0] ?? 'Unknown',
                            'gender' => $base['gender'] ?? 0,
                            'faction_id' => $factionInfo['faction_id'],
                            'faction_name' => $factionInfo['faction_name'],
                        ];
                    } else {
                        $factionInfo = $this->getRoleFactionInfo($role['id']);
                        $characters[] = [
                            'id' => $role['id'],
                            'name' => $role['name'],
                            'user_id' => $userId,
                            'level' => 0,
                            'level2' => 0,
                            'class' => 0,
                            'class_name' => 'Unknown',
                            'gender' => 0,
                            'faction_id' => $factionInfo['faction_id'],
                            'faction_name' => $factionInfo['faction_name'],
                        ];
                    }
                } catch (\Exception $e) {
                    $characters[] = [
                        'id' => $role['id'],
                        'name' => $role['name'],
                        'user_id' => $userId,
                        'level' => 0,
                        'level2' => 0,
                        'class' => 0,
                        'class_name' => 'Unknown',
                        'gender' => 0,
                        'faction_id' => 0,
                        'faction_name' => null,
                    ];
                }
            }

            return $characters;
        } catch (\Exception $e) {
            return [];
        }
    }

    /**
     * Get faction info for a character
     */
    public function getFactionInfo(int $roleId): array
    {
        $factionInfo = $this->api->getUserFaction($roleId);

        $factionDetails = null;
        if (isset($factionInfo['fid']) && $factionInfo['fid'] > 0) {
            $factionDetails = $this->api->getFactionInfo($factionInfo['fid']);
        }

        return [
            'member_info' => $factionInfo,
            'faction' => $factionDetails,
        ];
    }
}
