import { useMemo } from "react";
import { type Address, keccak256, stringToBytes } from "viem";
import { useReadContract } from "wagmi";

const ERC1271_ABI = [
	{
		inputs: [
			{ name: "_hash", type: "bytes32" },
			{ name: "_signature", type: "bytes" },
		],
		name: "isValidSignature",
		outputs: [{ name: "", type: "bytes4" }],
		stateMutability: "view",
		type: "function",
	},
] as const;

/**
 * Hook to check if an address supports ERC-1271 signature verification
 * ERC-1271 allows smart contracts to verify signatures, which is required for permit2
 * @param address - The address to check
 * @param chainId - The chain ID to check on
 * @returns Object with supportsERC1271 boolean and isLoading boolean
 */
export const useSupportsERC1271 = (
	address?: string,
	chainId?: number,
): { supportsERC1271: boolean; isLoading: boolean } => {
	// Generate test hash and signature once (memoized)
	const testHash = useMemo(
		() => keccak256(stringToBytes("test-signature")),
		[],
	);
	const dummySignature = useMemo(
		() => `0x${"11".repeat(65)}` as `0x${string}`,
		[],
	);

	const { data, isLoading, error } = useReadContract({
		abi: ERC1271_ABI,
		address: address as Address,
		functionName: "isValidSignature",
		args: [testHash, dummySignature],
		chainId,
		query: {
			enabled: Boolean(address && chainId),
			retry: false,
			staleTime: Number.POSITIVE_INFINITY, // Cache the result since ERC-1271 support doesn't change
		},
	});

	// If data exists (even if 0x00000000 for invalid signature), the function exists and ERC1271 is supported
	// If error contains "reverted" or is a ContractFunctionRevertedError, the function exists but reverted
	// A revert (e.g., InvalidSignature error with signature 0xf645eedf) means the function exists
	// If error doesn't indicate a revert, the function likely doesn't exist
	// The magic value check is only relevant when validating actual signatures, not for detecting support
	const supportsERC1271 = useMemo(() => {
		// If we got data back, the function exists and contract supports ERC-1271
		if (data !== undefined && data !== null) return true;

		// If there's an error, check if it's a revert (function exists) vs function doesn't exist
		if (error) {
			const errorMessage = error.message || "";
			const errorName = error.name || "";

			// Check for error data in a type-safe way
			const errorObj = error as {
				data?: unknown;
				cause?: { data?: unknown; name?: string };
				name?: string;
			};
			const errorData = errorObj?.data || errorObj?.cause?.data;
			const causeName = errorObj?.cause?.name || "";

			// If the error mentions "reverted", is a ContractFunctionRevertedError,
			// or has error data (like error signature 0xf645eedf), the function exists
			// A revert means the function was called but reverted (e.g., InvalidSignature error)
			const isRevertError =
				errorMessage.includes("reverted") ||
				errorName.includes("Reverted") ||
				causeName.includes("Reverted") ||
				errorData !== undefined;

			if (isRevertError) {
				return true;
			}

			// Otherwise, the function likely doesn't exist
			return false;
		}

		return false;
	}, [data, error]);

	return {
		supportsERC1271,
		isLoading,
	};
};
