const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const { ethers } = require("ethers");
require("dotenv").config();

const app = express();

// Middleware
app.use(cors());
app.use(bodyParser.json());

// Logging middleware
app.use((req, res, next) => {
    console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
    console.log('Request Headers:', req.headers);
    console.log('Request Body:', req.body);
    next();
});

// Contract configuration
const RELAYER_PRIVATE_KEY = process.env.RELAYER_PRIVATE_KEY;
const RPC_URL = process.env.RPC_URL;
const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS;

// Initialize provider and wallet
const provider = new ethers.JsonRpcProvider(RPC_URL);
const relayerWallet = new ethers.Wallet(RELAYER_PRIVATE_KEY, provider);

// Contract ABI
const gaslessNFTAbi = [
    {
        "inputs": [
            {"internalType": "address","name": "user","type": "address"},
            {"internalType": "uint256","name": "tokenId","type": "uint256"},
            {"internalType": "bytes32","name": "sigR","type": "bytes32"},
            {"internalType": "bytes32","name": "sigS","type": "bytes32"},
            {"internalType": "uint8","name": "sigV","type": "uint8"}
        ],
        "name": "mintNFT",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    }
];

// Initialize contract instance
const gaslessNFTContract = new ethers.Contract(
    CONTRACT_ADDRESS,
    gaslessNFTAbi,
    relayerWallet
);

// Verify environment variables
if (!RELAYER_PRIVATE_KEY || !RPC_URL || !CONTRACT_ADDRESS) {
    console.error("Missing required environment variables!");
    process.exit(1);
}

// Health check endpoint
app.get("/health", (req, res) => {
    res.json({ status: "ok" });
});

// Relay endpoint
app.post("/relay", async (req, res) => {
    console.log("Received relay request:", req.body);
    const { user, tokenId, sigR, sigS, sigV } = req.body;

    try {
        // Input validation
        if (!user || !tokenId || !sigR || !sigS || typeof sigV === 'undefined') {
            console.error("Missing required parameters");
            return res.status(400).json({
                success: false,
                error: "Missing required parameters",
                received: { user, tokenId, sigR, sigS, sigV }
            });
        }

        console.log("Submitting transaction with parameters:", {
            user,
            tokenId,
            sigR,
            sigS,
            sigV
        });

        // Submit the transaction
        const tx = await gaslessNFTContract.mintNFT(
            user,
            tokenId,
            sigR,
            sigS,
            sigV,
            {
                gasLimit: 300000 // Adjust as needed
            }
        );
        
        console.log("Transaction submitted:", tx.hash);
        
        // Wait for transaction to be mined
        const receipt = await tx.wait();
        console.log("Transaction mined:", receipt);

        res.status(200).json({
            success: true,
            txHash: tx.hash
        });
    } catch (error) {
        console.error("Relayer error:", error);
        res.status(500).json({
            success: false,
            error: error.message,
            details: {
                name: error.name,
                code: error.code,
                stack: error.stack
            }
        });
    }
});

// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Relayer running on http://localhost:${PORT}`);
    console.log("Contract Address:", CONTRACT_ADDRESS);
    console.log("RPC URL:", RPC_URL);
    console.log("Relayer Address:", relayerWallet.address);
});