<?php
namespace EasyChat\Library\Messenger;








final class MaxConversationIdentity {
    public const VERSION = 3;
    public const OWNER_USER = 'user';
    public const OWNER_CHAT = 'chat';

    public static function fromContact(array $contact): array {
        $metadata = json_decode((string)($contact['metadata_json'] ?? ''), true);
        $metadata = is_array($metadata) ? $metadata : [];

        return self::resolve(
            $metadata,
            (string)($contact['external_chat_id'] ?? ''),
            (string)($contact['external_user_id'] ?? ''),
            (string)($metadata['account_id'] ?? '')
        );
    }

    public static function resolve(
        array $metadata,
        string $external_chat_id = '',
        string $external_user_id = '',
        string $account_id = ''
    ): array {
        $chat_type = self::chatTypeFromMetadata($metadata);
        $chat_id = self::normalizeChatId((string)($metadata['chat_id'] ?? $external_chat_id));
        if ($chat_id === '' && in_array($chat_type, ['CHAT', 'CHANNEL'], true)) {
             
            $chat_id = self::normalizeChatId($external_user_id);
        }

        $account_id = self::normalizeUserId($account_id !== '' ? $account_id : (string)($metadata['account_id'] ?? ''));
        $stored_owner_id = (string)($metadata['identity_owner_type'] ?? '') === self::OWNER_USER
            ? (string)($metadata['identity_owner_id'] ?? '')
            : '';
        $peer_user_id = self::firstCounterpartyUserId([
            $metadata['counterparty_sender_id'] ?? '',
            $stored_owner_id,
            $metadata['sender_id'] ?? '',
        ], $account_id, [$chat_id]);

        $owner_type = '';
        $owner_id = '';
        if ($chat_type === 'DIALOG' && $peer_user_id !== '') {
            $owner_type = self::OWNER_USER;
            $owner_id = $peer_user_id;
        } elseif (in_array($chat_type, ['CHAT', 'CHANNEL'], true) && $chat_id !== '') {
            $owner_type = self::OWNER_CHAT;
            $owner_id = $chat_id;
        }

        $fingerprint = '';
        if ($owner_type !== '' && $owner_id !== '') {
            $fingerprint = hash('sha256', implode('|', [
                'max',
                (string)self::VERSION,
                $chat_type,
                $owner_type,
                $owner_id,
            ]));
        }

        return [
            'version' => self::VERSION,
            'chat_type' => $chat_type,
            'chat_id' => $chat_id,
            'peer_user_id' => $peer_user_id,
            'owner_type' => $owner_type,
            'owner_id' => $owner_id,
            'fingerprint' => $fingerprint,
            'resolved' => $fingerprint !== '',
        ];
    }

    



    public static function profileKey(array $identity): string {
        $owner_type = (string)($identity['owner_type'] ?? '');
        $owner_id = (string)($identity['owner_id'] ?? '');
        if (!in_array($owner_type, [self::OWNER_USER, self::OWNER_CHAT], true) || $owner_id === '') {
            return '';
        }
        return $owner_type . ':' . $owner_id;
    }

    public static function enrichMetadata(
        array $metadata,
        string $external_chat_id = '',
        string $external_user_id = '',
        string $account_id = ''
    ): array {
        $identity = self::resolve($metadata, $external_chat_id, $external_user_id, $account_id);
        $metadata['chat_type'] = $identity['chat_type'];
        if ($identity['chat_id'] !== '') {
            $metadata['chat_id'] = $identity['chat_id'];
        }
        if ($identity['chat_type'] === 'DIALOG' && $identity['peer_user_id'] !== '') {
            $metadata['counterparty_sender_id'] = $identity['peer_user_id'];
        }

        if ($identity['resolved']) {
            $metadata['identity_version'] = self::VERSION;
            $metadata['identity_owner_type'] = $identity['owner_type'];
            $metadata['identity_owner_id'] = $identity['owner_id'];
            $metadata['identity_fingerprint'] = $identity['fingerprint'];
        } else {
             
             
            unset(
                $metadata['identity_owner_type'],
                $metadata['identity_owner_id'],
                $metadata['identity_fingerprint']
            );
            if ((int)($metadata['identity_version'] ?? 0) >= self::VERSION) {
                unset($metadata['identity_version']);
            }
        }

        return $metadata;
    }

    








    public static function outboundDialogMetadata(
        array $metadata,
        string $external_chat_id,
        string $external_user_id,
        string $account_id
    ): array {
        $metadata['chat_type'] = 'DIALOG';
        $metadata['chat_id'] = self::normalizeChatId($external_chat_id);
        $metadata['account_id'] = self::normalizeUserId($account_id);
        $metadata['sender_id'] = self::normalizeUserId($external_user_id);
        $metadata['counterparty_sender_id'] = self::normalizeUserId($external_user_id);
        $metadata = array_merge($metadata, ReplyCapability::metadataForMaxChatType('DIALOG'));

        return self::enrichMetadata(
            $metadata,
            $external_chat_id,
            $external_user_id,
            $account_id
        );
    }

    public static function normalizeChatType(string $chat_type): string {
        $chat_type = strtoupper(trim($chat_type));
        if ($chat_type === 'GROUP') {
            return 'CHAT';
        }
        return in_array($chat_type, ['DIALOG', 'CHAT', 'CHANNEL'], true) ? $chat_type : 'unknown';
    }

    






    public static function firstKnownChatType(array $candidates): string {
        foreach ($candidates as $candidate) {
            $chat_type = self::normalizeChatType((string)$candidate);
            if ($chat_type !== 'unknown') {
                return $chat_type;
            }
        }
        return 'unknown';
    }

    



    public static function chatTypeFromMetadata(array $metadata): string {
        return self::firstKnownChatType([
            $metadata['chat_type'] ?? '',
            $metadata['max_chat_type'] ?? '',
        ]);
    }

    







    public static function resolveTransportChatType(array $candidates, string $chat_id = '', string $sender_id = ''): string {
        $chat_type = self::firstKnownChatType($candidates);
        if ($chat_type !== 'unknown') {
            return $chat_type;
        }

        $chat_id = self::normalizeChatId($chat_id);
        $sender_id = self::normalizeUserId($sender_id);
        if ($chat_id !== '' && strpos($chat_id, '-') === 0 && $sender_id === '') {
            return 'CHANNEL';
        }

        return 'unknown';
    }

    public static function normalizeUserId(string $value): string {
        $value = trim($value);
        return preg_match('/^\d+$/', $value) === 1 ? $value : '';
    }

    public static function normalizeChatId(string $value): string {
        $value = trim($value);
        return preg_match('/^-?\d+$/', $value) === 1 ? $value : '';
    }

    


    public static function firstCounterpartyUserId(array $candidates, string $account_id = '', array $excluded_ids = []): string {
        $account_id = self::normalizeUserId($account_id);
        $excluded = [];
        foreach ($excluded_ids as $excluded_id) {
            $excluded_id = self::normalizeUserId((string)$excluded_id);
            if ($excluded_id !== '') {
                $excluded[$excluded_id] = true;
            }
        }
        foreach ($candidates as $candidate) {
            $candidate = self::normalizeUserId((string)$candidate);
            if ($candidate !== ''
                && !isset($excluded[$candidate])
                && ($account_id === '' || !hash_equals($account_id, $candidate))
            ) {
                return $candidate;
            }
        }
        return '';
    }
}
