/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/


let faviconUrls = {};

// Helper functions
function arrayBufferToBase64(buffer) {
    let binary = '';
    const bytes = new Uint8Array(buffer);
    bytes.forEach(b => (binary += String.fromCharCode(b)));
    return btoa(binary);
}

function base64ToArrayBuffer(base64) {
    const binary = atob(base64);
    const len = binary.length;
    const bytes = new Uint8Array(len);
    for (let i = 0; i < len; i++) {
        bytes[i] = binary.charCodeAt(i);
    }
    return bytes.buffer;
}

function uint8ArrayToBase64(uint8Array) {
    return arrayBufferToBase64(uint8Array.buffer);
}

function base64ToUint8Array(base64) {
    const arrayBuffer = base64ToArrayBuffer(base64);
    return new Uint8Array(arrayBuffer);
}

async function encryptData(data, key) {
    const iv = crypto.getRandomValues(new Uint8Array(12));
    const encoded = new TextEncoder().encode(data);
    const encrypted = await crypto.subtle.encrypt(
        {
            name: 'AES-GCM',
            iv: iv,
        },
        key,
        encoded
    );

    // Convert encrypted data and iv to Base64 strings
    const ciphertextBase64 = arrayBufferToBase64(encrypted);
    const ivBase64 = uint8ArrayToBase64(iv);

    return { ciphertext: ciphertextBase64, iv: ivBase64 };
}

async function decryptData(ciphertextBase64, ivBase64, key) {
    const ciphertext = base64ToArrayBuffer(ciphertextBase64);
    const iv = base64ToUint8Array(ivBase64);

    const decrypted = await crypto.subtle.decrypt(
        {
            name: 'AES-GCM',
            iv: iv,
        },
        key,
        ciphertext
    );
    const dec = new TextDecoder();
    return dec.decode(decrypted);
}

// Function to get full hostname from URL
function getBaseDomain(url) {
    try {
        const urlObj = new URL(url);
        return urlObj.hostname;
    } catch (error) {
        console.error('Invalid URL:', url);
        return '';
    }
}

// Function to escape special characters in GraphQL strings (useful for text fields)
function escapeGraphQLString(str) {
    if (typeof str !== 'string') {
        return '';
    }
    return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
}

// Function to get the favicon URL when a tab is updated
function updateFaviconUrl(tabId, changeInfo, tab) {
    if (changeInfo.status === 'complete' && tab.url) {
        const domain = getBaseDomain(tab.url);
        if (domain && tab.favIconUrl) {
            faviconUrls[domain] = tab.favIconUrl;

            // Also store in chrome.storage.local
            chrome.storage.local.get(['faviconUrls'], (result) => {
                let storedFavicons = result.faviconUrls || {};
                storedFavicons[domain] = tab.favIconUrl;
                chrome.storage.local.set({ faviconUrls: storedFavicons });
            });
        }
    }
}

// Add the listener for tab updates
chrome.tabs.onUpdated.addListener(updateFaviconUrl);

// Function to generate UUID v4
function generateUUID() {
    // Public Domain/MIT
    return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
        (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)
    );
}

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
    if (request.action === 'storeKeys') {
        (async function () {
            try {
                // Generate new key material and encrypt the new keys
                const keyMaterial = await crypto.subtle.generateKey(
                    { name: 'AES-GCM', length: 256 },
                    true,
                    ['encrypt', 'decrypt']
                );

                const encryptedPublicKey = await encryptData(request.publicKey, keyMaterial);
                const encryptedPrivateKey = await encryptData(request.privateKey, keyMaterial);
                const encryptedUrl = await encryptData(request.url, keyMaterial);

                // Export the key material to JWK format
                const exportedKey = await crypto.subtle.exportKey('jwk', keyMaterial);

                // Store the encrypted keys per domain and net
                chrome.storage.local.get(['keys', 'connectedNets'], (result) => {
                    let keys = result.keys || {};
                    let connectedNets = result.connectedNets || {};

                    if (!keys[request.domain]) {
                        keys[request.domain] = {};
                    }

                    keys[request.domain][request.net] = {
                        publicKey: encryptedPublicKey,
                        privateKey: encryptedPrivateKey,
                        url: encryptedUrl,
                        exportedKey: exportedKey, // Store the exported key
                    };

                    connectedNets[request.domain] = request.net;

                    console.log('Storing keys for domain:', request.domain);
                    console.log('Storing net:', request.net);
                    console.log('ConnectedNets after storing:', connectedNets);

                    chrome.storage.local.set({ keys, connectedNets }, () => {
                        console.log('Keys stored for domain:', request.domain, 'and net:', request.net);
                        sendResponse({ success: true });
                    });
                });
            } catch (error) {
                console.error('Error in storeKeys:', error);
                sendResponse({ success: false, error: error.message });
            }
        })();

        return true; // Keep the message channel open for async sendResponse
    } else if (request.action === 'disconnectKeys') {
        (async function () {
            // Remove the keys for the domain and net
            chrome.storage.local.get(['keys', 'connectedNets'], (result) => {
                let keys = result.keys || {};
                let connectedNets = result.connectedNets || {};
                if (keys[request.domain] && keys[request.domain][request.net]) {
                    delete keys[request.domain][request.net];
                    if (Object.keys(keys[request.domain]).length === 0) {
                        delete keys[request.domain];
                    }
                    if (connectedNets[request.domain] === request.net) {
                        delete connectedNets[request.domain];
                    }
                    chrome.storage.local.set({ keys, connectedNets }, () => {
                        console.log('Keys disconnected for domain:', request.domain, 'and net:', request.net);
                        console.log('ConnectedNets after disconnecting:', connectedNets);
                        sendResponse({ success: true });
                    });
                } else {
                    sendResponse({ success: false, error: 'No keys found to disconnect' });
                }
            });
        })();

        return true; // Keep the message channel open for async sendResponse
    } else if (request.action === 'requestData') {
        (async function () {
            chrome.storage.local.get(['keys', 'faviconUrls'], async function (result) {
                const keys = result.keys || {};
                const storedFavicons = result.faviconUrls || {};
                const faviconUrlForDomain = storedFavicons[request.domain] || '';

                if (keys[request.domain] && keys[request.domain][request.net]) {
                    const { publicKey, privateKey, url, exportedKey } = keys[request.domain][request.net];

                    try {
                        // Import the key material from JWK format
                        const keyMaterial = await crypto.subtle.importKey(
                            'jwk',
                            exportedKey,
                            { name: 'AES-GCM' },
                            true,
                            ['encrypt', 'decrypt']
                        );

                        const decryptedPublicKey = await decryptData(publicKey.ciphertext, publicKey.iv, keyMaterial);
                        const decryptedPrivateKey = await decryptData(privateKey.ciphertext, privateKey.iv, keyMaterial);
                        const decryptedUrl = await decryptData(url.ciphertext, url.iv, keyMaterial);

                        sendResponse({
                            publicKey: decryptedPublicKey,
                            privateKey: decryptedPrivateKey,
                            url: decryptedUrl,
                            faviconUrl: faviconUrlForDomain,
                        });
                    } catch (error) {
                        console.error('Error decrypting data:', error);
                        sendResponse({ error: 'Failed to decrypt data', faviconUrl: faviconUrlForDomain });
                    }
                } else {
                    sendResponse({ error: 'No keys found for domain and net', faviconUrl: faviconUrlForDomain });
                }
            });
        })();

        return true; // Keep the message channel open for async sendResponse
    } else if (request.action === 'getConnectedNet') {
        (async function () {
            chrome.storage.local.get(['connectedNets'], function (result) {
                const connectedNets = result.connectedNets || {};
                const net = connectedNets[request.domain];
                if (net) {
                    sendResponse({ net: net });
                } else {
                    sendResponse({ error: 'No connected net for domain' });
                }
            });
        })();

        return true; // Keep the message channel open for async sendResponse
    }

    // ------------------------------------------------
    // Below: Example: Using GraphQL variables for postTransaction
    // ------------------------------------------------

    else if (request.action === 'submitTransactionFromDashboard') {
        (async function () {
            // Retrieve the necessary data
            const transactionData = request.transactionData;
            const domain = request.domain;
            const net = request.net;

            // Validate transactionData
            if (!transactionData || !transactionData.asset || !transactionData.recipientAddress || !transactionData.amount) {
                sendResponse({ success: false, error: 'Invalid transaction data.' });
                return;
            }

            // Retrieve the signer's keys and URL from storage
            chrome.storage.local.get(['keys', 'connectedNets'], async function (result) {
                const keys = result.keys || {};
                const connectedNets = result.connectedNets || {};

                if (!connectedNets[domain] || connectedNets[domain] !== net) {
                    sendResponse({ success: false, error: 'Not connected to the specified net for this domain.' });
                    return;
                }

                if (!keys[domain] || !keys[domain][net]) {
                    sendResponse({ success: false, error: 'Keys not found for the specified domain and net.' });
                    return;
                }

                const { publicKey, privateKey, url, exportedKey } = keys[domain][net];

                try {
                    // Import the key material from JWK format
                    const keyMaterial = await crypto.subtle.importKey(
                        'jwk',
                        exportedKey,
                        { name: 'AES-GCM' },
                        true,
                        ['encrypt', 'decrypt']
                    );

                    const decryptedPublicKey = await decryptData(publicKey.ciphertext, publicKey.iv, keyMaterial);
                    const decryptedPrivateKey = await decryptData(privateKey.ciphertext, privateKey.iv, keyMaterial);
                    const decryptedUrl = await decryptData(url.ciphertext, url.iv, keyMaterial);

                    // Build the GraphQL mutation with variables
                    const mutation = `
                      mutation postTransaction(
                        $operation: String!,
                        $amount: Int!,
                        $signerPublicKey: String!,
                        $signerPrivateKey: String!,
                        $recipientPublicKey: String!,
                        $asset: JSONScalar!
                      ) {
                        postTransaction(
                          data: {
                            operation: $operation,
                            amount: $amount,
                            signerPublicKey: $signerPublicKey,
                            signerPrivateKey: $signerPrivateKey,
                            recipientPublicKey: $recipientPublicKey,
                            asset: $asset
                          }
                        ) {
                          id
                        }
                      }
                    `;

                    const variables = {
                        operation: 'CREATE',
                        amount: parseInt(transactionData.amount),
                        signerPublicKey: decryptedPublicKey,
                        signerPrivateKey: decryptedPrivateKey,
                        recipientPublicKey: transactionData.recipientAddress,
                        asset: transactionData.asset, // pass JS object
                    };

                    // Send the mutation with variables
                    const response = await fetch(decryptedUrl, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                        },
                        body: JSON.stringify({ query: mutation, variables }),
                    });

                    if (!response.ok) {
                        throw new Error(`Network response was not ok: ${response.statusText}`);
                    }

                    const resultData = await response.json();
                    if (resultData.errors) {
                        console.error('GraphQL errors:', resultData.errors);
                        sendResponse({
                            success: false,
                            error: 'GraphQL errors occurred.',
                            errors: resultData.errors,
                        });
                    } else {
                        console.log('Transaction submitted successfully:', resultData.data);
                        sendResponse({ success: true, data: resultData.data });
                    }
                } catch (error) {
                    console.error('Error submitting transaction:', error);
                    sendResponse({ success: false, error: error.message });
                }
            });
        })();

        return true; // Keep the message channel open for async sendResponse
    }

    else if (request.action === 'submitTransaction') {
        (async function () {
            console.log('Handling submitTransaction action');
            console.log('Sender:', sender);
            let senderUrl = null;
            if (sender.tab && sender.tab.url) {
                senderUrl = sender.tab.url;
            } else if (sender.url) {
                senderUrl = sender.url;
            } else if (sender.origin) {
                senderUrl = sender.origin;
            } else {
                console.error('Sender URL is undefined');
                sendResponse({ success: false, error: 'Cannot determine sender URL' });
                return;
            }
            console.log('Sender URL:', senderUrl);

            const domain = getBaseDomain(senderUrl);
            console.log('Domain:', domain);

            chrome.storage.local.get(['keys', 'connectedNets'], async function (result) {
                const keys = result.keys || {};
                const connectedNets = result.connectedNets || {};
                console.log('ConnectedNets:', connectedNets);
                const net = connectedNets[domain];
                console.log('Net for domain:', domain, 'is', net);

                if (keys[domain] && keys[domain][net]) {
                    const { publicKey, privateKey, url, exportedKey } = keys[domain][net];

                    try {
                        // Import the key material from JWK format
                        const keyMaterial = await crypto.subtle.importKey(
                            'jwk',
                            exportedKey,
                            { name: 'AES-GCM' },
                            true,
                            ['encrypt', 'decrypt']
                        );

                        const decryptedPublicKey = await decryptData(publicKey.ciphertext, publicKey.iv, keyMaterial);
                        const decryptedPrivateKey = await decryptData(privateKey.ciphertext, privateKey.iv, keyMaterial);
                        const decryptedUrl = await decryptData(url.ciphertext, url.iv, keyMaterial);

                        // Check if required fields are defined
                        if (!decryptedPublicKey || !decryptedPrivateKey || !request.recipient) {
                            console.error('Missing required fields for transaction submission');
                            sendResponse({
                                success: false,
                                error: 'Missing required fields for transaction',
                            });
                            return;
                        }

                        // Prepare data for GraphQL mutation
                        const mutation = `
                          mutation postTransaction(
                            $operation: String!,
                            $amount: Int!,
                            $signerPublicKey: String!,
                            $signerPrivateKey: String!,
                            $recipientPublicKey: String!,
                            $asset: JSONScalar!
                          ) {
                            postTransaction(
                              data: {
                                operation: $operation,
                                amount: $amount,
                                signerPublicKey: $signerPublicKey,
                                signerPrivateKey: $signerPrivateKey,
                                recipientPublicKey: $recipientPublicKey,
                                asset: $asset
                              }
                            ) {
                              id
                            }
                          }
                        `;

                        const variables = {
                            operation: 'CREATE',
                            amount: parseInt(request.amount),
                            signerPublicKey: decryptedPublicKey,
                            signerPrivateKey: decryptedPrivateKey,
                            recipientPublicKey: request.recipient,
                            asset: {
                                data: request.data || {},
                            },
                        };

                        const response = await fetch(decryptedUrl, {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json',
                            },
                            body: JSON.stringify({
                                query: mutation,
                                variables,
                            }),
                        });

                        if (!response.ok) {
                            throw new Error(`Network response was not ok: ${response.statusText}`);
                        }

                        const resultData = await response.json();
                        if (resultData.errors) {
                            console.error('GraphQL errors:', resultData.errors);
                            sendResponse({ success: false, errors: resultData.errors });
                        } else {
                            console.log('Transaction submitted successfully:', resultData.data);
                            sendResponse({ success: true, data: resultData.data });
                        }
                    } catch (error) {
                        console.error('Error submitting transaction:', error);
                        sendResponse({ success: false, error: error.message });
                    }
                } else {
                    console.error('No keys found for domain:', domain, 'and net:', net);
                    console.log('Available keys:', keys);
                    sendResponse({ error: 'No keys found for domain and net' });
                }
            });
        })();

        return true; // Keep the message channel open for async sendResponse
    }

    else if (request.action === 'submitLoginTransaction') {
        (async function () {
            console.log('Handling submitLoginTransaction action');
            console.log('Sender:', sender);
            let senderUrl = null;
            if (sender.tab && sender.tab.url) {
                senderUrl = sender.tab.url;
            } else if (sender.url) {
                senderUrl = sender.url;
            } else if (sender.origin) {
                senderUrl = sender.origin;
            } else {
                console.error('Sender URL is undefined');
                sendResponse({ success: false, error: 'Cannot determine sender URL' });
                return;
            }
            console.log('Sender URL:', senderUrl);

            const domain = getBaseDomain(senderUrl);
            console.log('Domain:', domain);

            chrome.storage.local.get(['keys', 'connectedNets'], async function (result) {
                const keys = result.keys || {};
                const connectedNets = result.connectedNets || {};
                console.log('ConnectedNets:', connectedNets);
                const net = connectedNets[domain];
                console.log('Net for domain:', domain, 'is', net);

                if (keys[domain] && keys[domain][net]) {
                    const { publicKey, privateKey, url, exportedKey } = keys[domain][net];

                    try {
                        // Import the key material from JWK format
                        const keyMaterial = await crypto.subtle.importKey(
                            'jwk',
                            exportedKey,
                            { name: 'AES-GCM' },
                            true,
                            ['encrypt', 'decrypt']
                        );

                        const decryptedPublicKey = await decryptData(publicKey.ciphertext, publicKey.iv, keyMaterial);
                        const decryptedPrivateKey = await decryptData(privateKey.ciphertext, privateKey.iv, keyMaterial);
                        const decryptedUrl = await decryptData(url.ciphertext, url.iv, keyMaterial);

                        // Prepare asset data with current timestamp and unique login_transaction_id
                        const currentTimestamp = Math.floor(Date.now() / 1000);
                        let loginTransactionId = '';
                        if (crypto.randomUUID) {
                            loginTransactionId = crypto.randomUUID().replace(/[^a-zA-Z0-9]/g, '');
                        } else {
                            loginTransactionId = generateUUID().replace(/[^a-zA-Z0-9]/g, '');
                        }

                        // Build variables
                        const mutation = `
                          mutation postTransaction(
                            $operation: String!,
                            $amount: Int!,
                            $signerPublicKey: String!,
                            $signerPrivateKey: String!,
                            $recipientPublicKey: String!,
                            $asset: JSONScalar!
                          ) {
                            postTransaction(
                              data: {
                                operation: $operation,
                                amount: $amount,
                                signerPublicKey: $signerPublicKey,
                                signerPrivateKey: $signerPrivateKey,
                                recipientPublicKey: $recipientPublicKey,
                                asset: $asset
                              }
                            ) {
                              id
                            }
                          }
                        `;

                        const variables = {
                            operation: 'CREATE',
                            amount: 1,
                            signerPublicKey: decryptedPublicKey,
                            signerPrivateKey: decryptedPrivateKey,
                            recipientPublicKey: decryptedPublicKey, // self
                            asset: {
                                data: {
                                    login_timestamp: currentTimestamp,
                                    login_transaction_id: loginTransactionId,
                                },
                            },
                        };

                        const response = await fetch(decryptedUrl, {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json',
                            },
                            body: JSON.stringify({ query: mutation, variables }),
                        });

                        if (!response.ok) {
                            throw new Error(`Network response was not ok: ${response.statusText}`);
                        }

                        const resultData = await response.json();
                        if (resultData.errors) {
                            console.error('GraphQL errors:', resultData.errors);
                            sendResponse({ success: false, errors: resultData.errors });
                        } else {
                            console.log('Login transaction submitted successfully:', resultData.data);
                            sendResponse({ success: true, data: resultData.data });
                        }
                    } catch (error) {
                        console.error('Error submitting login transaction:', error);
                        sendResponse({ success: false, error: error.message });
                    }
                } else {
                    console.error('No keys found for domain:', domain, 'and net:', net);
                    console.log('Available keys:', keys);
                    sendResponse({ error: 'No keys found for domain and net' });
                }
            });
        })();

        return true; // Keep the message channel open for async sendResponse
    }

    // The rest (deployContractChain, etc.) can remain the same or be adapted similarly to use variables.
    else if (request.action === 'deployContractChain') {
        // Handler for deploying contract chain
        (async function () {
            const domain = request.domain;
            const net = request.net;
            const ownerAddress = request.ownerAddress;
            const soliditySource = request.soliditySource;
            const deployConfig = request.deployConfig; // Contains arguments and contract_name

            // Retrieve the signer's keys and URL from storage
            chrome.storage.local.get(['keys', 'connectedNets'], async function (result) {
                const keys = result.keys || {};
                const connectedNets = result.connectedNets || {};

                if (!connectedNets[domain] || connectedNets[domain] !== net) {
                    sendResponse({ success: false, error: 'Not connected to the specified net for this domain.' });
                    return;
                }

                if (!keys[domain] || !keys[domain][net]) {
                    sendResponse({ success: false, error: 'Keys not found for the specified domain and net.' });
                    return;
                }

                const { url, exportedKey } = keys[domain][net];

                try {
                    // Import the key material from JWK format
                    const keyMaterial = await crypto.subtle.importKey(
                        'jwk',
                        exportedKey,
                        { name: 'AES-GCM' },
                        true,
                        ['encrypt', 'decrypt']
                    );

                    const decryptedUrl = await decryptData(url.ciphertext, url.iv, keyMaterial);

                    // 1. Perform addAddress mutation
                    const addAddressMutation = `
                    mutation {
                      addAddress(
                        config: "5 127.0.0.1 10005",
                        address: "${escapeGraphQLString(ownerAddress)}",
                        type: "data"
                      )
                    }
                    `;

                    const addAddressResponse = await fetch(decryptedUrl, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                        },
                        body: JSON.stringify({ query: addAddressMutation }),
                    });

                    if (!addAddressResponse.ok) {
                        throw new Error(`Network response was not ok: ${addAddressResponse.statusText}`);
                    }

                    const addAddressResult = await addAddressResponse.json();
                    if (addAddressResult.errors) {
                        console.error('GraphQL errors in addAddress:', addAddressResult.errors);
                        sendResponse({
                            success: false,
                            error: 'Error in addAddress mutation.',
                            errors: addAddressResult.errors,
                        });
                        return;
                    }

                    // Check if addAddress was successful
                    if (
                        addAddressResult.data &&
                        addAddressResult.data.addAddress === 'Address added successfully'
                    ) {
                        // 2. Perform compileContract mutation
                        const escapedSoliditySource = escapeGraphQLString(soliditySource);

                        const compileContractMutation = `
                        mutation {
                          compileContract(
                            source: """${escapedSoliditySource}""",
                            type: "data"
                        )
                        }
                        `;

                        const compileContractResponse = await fetch(decryptedUrl, {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json',
                            },
                            body: JSON.stringify({ query: compileContractMutation }),
                        });

                        if (!compileContractResponse.ok) {
                            throw new Error(`Network response was not ok: ${compileContractResponse.statusText}`);
                        }

                        const compileContractResult = await compileContractResponse.json();
                        if (compileContractResult.errors) {
                            console.error('GraphQL errors in compileContract:', compileContractResult.errors);
                            sendResponse({
                                success: false,
                                error: 'Error in compileContract mutation.',
                                errors: compileContractResult.errors,
                            });
                            return;
                        }

                        // Extract the contract filename
                        const contractFilename = compileContractResult.data.compileContract;
                        if (!contractFilename) {
                            sendResponse({
                                success: false,
                                error: 'Failed to compile contract.',
                            });
                            return;
                        }

                        // 3. Perform deployContract mutation
                        const { arguments: args, contract_name } = deployConfig;
                        const deployContractMutation = `
                        mutation {
                          deployContract(
                            config: "5 127.0.0.1 10005",
                            contract: "${escapeGraphQLString(contractFilename)}",
                            name: "/tmp/${escapeGraphQLString(
                                contractFilename.replace('.json', '.sol')
                            )}:${escapeGraphQLString(contract_name)}",
                            arguments: "${escapeGraphQLString(args)}",
                            owner: "${escapeGraphQLString(ownerAddress)}",
                            type: "data"
                          ){
                            ownerAddress
                            contractAddress
                            contractName
                          }
                        }
                        `;

                        const deployContractResponse = await fetch(decryptedUrl, {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json',
                            },
                            body: JSON.stringify({ query: deployContractMutation }),
                        });

                        if (!deployContractResponse.ok) {
                            throw new Error(
                                `Network response was not ok: ${deployContractResponse.statusText}`
                            );
                        }

                        const deployContractResult = await deployContractResponse.json();
                        if (deployContractResult.errors) {
                            console.error('GraphQL errors in deployContract:', deployContractResult.errors);
                            sendResponse({
                                success: false,
                                error: 'Error in deployContract mutation.',
                                errors: deployContractResult.errors,
                            });
                            return;
                        }

                        // Extract the contract address and return success
                        if (
                            deployContractResult.data &&
                            deployContractResult.data.deployContract &&
                            deployContractResult.data.deployContract.contractAddress
                        ) {
                            const contractAddress =
                                deployContractResult.data.deployContract.contractAddress;
                            sendResponse({ success: true, contractAddress: contractAddress });
                            return;
                        } else {
                            sendResponse({
                                success: false,
                                error: 'Failed to deploy contract.',
                            });
                            return;
                        }
                    } else {
                        sendResponse({ success: false, error: 'Failed to add address.' });
                        return;
                    }
                } catch (error) {
                    console.error('Error deploying contract chain:', error);
                    sendResponse({ success: false, error: error.message });
                }
            });
        })();

        return true; // Keep the message channel open for async sendResponse
    }
});
