<?php

namespace App\Services\PwApi\Chat;

class ChatService extends \App\Services\PwApi\Core\PwApiService
{
    public function sendMail($receiver, $title, $context, $money, $item = [])
    {
        if ($item === []) {
            $item = [
                'id' => 0,
                'pos' => 0,
                'count' => 0,
                'max_count' => 0,
                'data' => '',
                'proctype' => 0,
                'expire_date' => 0,
                'guid1' => 0,
                'guid2' => 0,
                'mask' => 0,
            ];
        }

        $pack = pack('NNCN', 344, 1025, 3, $receiver).$this->gamed->packString($title).$this->gamed->packString($context);
        $pack .= $this->gamed->marshal($item, $this->data['role']['pocket']['inv']);
        $pack .= pack('N', $money);

        return $this->gamed->SendToDelivery($this->gamed->createHeader($this->data['code']['sendMail'], $pack));
    }

    public function WorldChat($role, $msg, $channel)
    {
        $pack = pack('CCN', $channel, 0, $role).$this->gamed->packString($msg).$this->gamed->packOctet('');

        return $this->gamed->SendToProvider($this->gamed->createHeader($this->data['code']['worldChat'], $pack));
    }

    public function PrivateChat($srcroleid, $dstroleid, $msg, $srcname = '', $dstname = '', $emote = 9, $channel = 14)
    {
        $pack = pack('C', $channel)
              .pack('C', $emote)
              .$this->gamed->packString($srcname)
              .pack('N', $srcroleid)
              .$this->gamed->packString($dstname)
              .pack('N', $dstroleid)
              .$this->gamed->packString($msg)
              .$this->gamed->packOctet('')
              .pack('N', 0);

        return $this->gamed->SendToProvider($this->gamed->createHeader(0x60, $pack));
    }

    public function broadcastMessage($message, $type = 0)
    {
        $command = '';

        switch ($type) {
            case 0:
                $command = "/notice {$message}";
                break;
            case 1:
                $command = "/world {$message}";
                break;
            case 2:
                $command = "/gmchat {$message}";
                break;
            default:
                $command = "/notice {$message}";
        }

        return $this->gmControlGame($command);
    }

    public function worldChatBroadcast($message, $channel = 9)
    {
        $result = $this->WorldChat(0, $message, $channel);

        if ($result) {
            return [
                'success' => true,
                'message' => 'World chat broadcast sent on channel '.$channel,
                'channel' => $channel,
                'content' => $message,
            ];
        } else {
            return [
                'success' => false,
                'message' => 'Failed to send world chat broadcast',
                'channel' => $channel,
            ];
        }
    }

    public function sendDiscordWebhook($message, $webhookUrl, $username = null, $avatarUrl = null)
    {
        if (empty($webhookUrl)) {
            return [
                'success' => false,
                'message' => 'Webhook URL is empty',
            ];
        }

        $payload = [
            'content' => $message,
        ];

        if ($username) {
            $payload['username'] = $username;
        }

        if ($avatarUrl) {
            $payload['avatar_url'] = $avatarUrl;
        }

        $ch = curl_init($webhookUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
        ]);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode >= 200 && $httpCode < 300) {
            return [
                'success' => true,
                'message' => 'Discord webhook sent successfully',
                'http_code' => $httpCode,
            ];
        } else {
            return [
                'success' => false,
                'message' => 'Failed to send Discord webhook',
                'http_code' => $httpCode,
                'response' => $response,
            ];
        }
    }

    private function gmControlGame($command, $worldtag = -1, $xid = 0)
    {
        $opcode = $this->data['code']['gmControlGame'] ?? 380;

        if ($xid == 0) {
            $xid = time() % 100000;
        }

        $pack = pack('NN', $xid, $worldtag).$this->gamed->packString($command);
        $data = $this->gamed->createHeader($opcode, $pack);

        $response = $this->gamed->SendToDelivery($data);

        if (! $response) {
            return [
                'success' => false,
                'message' => 'No response from server',
                'command' => $command,
            ];
        }

        $pos = 0;
        $respOpcode = $this->gamed->unpackCuint($response, $pos);
        $respLen = $this->gamed->unpackCuint($response, $pos);
        $respData = substr($response, $pos);

        if ($respOpcode != 381) {
            return [
                'success' => false,
                'message' => 'Unexpected response opcode: '.$respOpcode,
                'command' => $command,
            ];
        }

        $result = [
            'success' => false,
            'command' => $command,
            'xid' => 0,
            'retcode' => -1,
            'gs_results' => [],
        ];

        if (strlen($respData) >= 8) {
            $result['xid'] = unpack('N', substr($respData, 0, 4))[1];
            $result['retcode'] = unpack('N', substr($respData, 4, 4))[1];

            if ($result['retcode'] > 2147483647) {
                $result['retcode'] = $result['retcode'] - 4294967296;
            }

            $result['success'] = ($result['retcode'] == 0);

            if (strlen($respData) > 8) {
                $vectorPos = 8;
                $vectorData = substr($respData, 8);
                $vectorCount = $this->gamed->unpackCuint($vectorData, $tmp);
                $vectorData = substr($vectorData, $tmp);

                for ($i = 0; $i < $vectorCount && strlen($vectorData) >= 8; $i++) {
                    $gsid = unpack('N', substr($vectorData, 0, 4))[1];
                    $gsRetcode = unpack('N', substr($vectorData, 4, 4))[1];
                    if ($gsRetcode > 2147483647) {
                        $gsRetcode = $gsRetcode - 4294967296;
                    }
                    $result['gs_results'][] = [
                        'gsid' => $gsid,
                        'retcode' => $gsRetcode,
                    ];
                    $vectorData = substr($vectorData, 8);
                }
            }

            $result['message'] = $result['success']
                ? 'Command executed successfully'
                : 'Command failed (retcode: '.$result['retcode'].')';
        }

        return $result;
    }
}
