import React, { useState, useEffect } from 'react';
import { useAccount, useSignMessage, useEnsName } from 'wagmi';
import type { LightNode } from '@waku/interfaces';
import { useWaku } from '@waku/react';
import { createMessage, encoder, BlockPayload } from '@/lib/waku';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Loader2 } from "lucide-react";
import QRCode from '@/components/QRCode';
import { useWalletPrompt } from '@/hooks/useWalletPrompt';
import { v4 as uuidv4 } from 'uuid';
import { fromLightPush, Telemetry } from '@/lib/telemetry';

interface SignChainProps {
  block: BlockPayload;
  chainsData: BlockPayload[];
  onSuccess: (newBlock: BlockPayload) => void;
}

const SignChain: React.FC<SignChainProps> = ({ block, chainsData, onSuccess }) => {
  const [isOpen, setIsOpen] = useState(false);
  const [isSigning, setIsSigning] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [alreadySigned, setAlreadySigned] = useState(false);
  const [isWalletPrompt, setIsWalletPrompt] = useState(false);

  const { address } = useAccount();
  const { data: ensName } = useEnsName({ address });
  const { node } = useWaku<LightNode>();
  const { ensureWalletConnected } = useWalletPrompt();

  const checkSignatures = (blockToCheck: BlockPayload, visitedBlocks: Set<string>): boolean => {
    if (visitedBlocks.has(blockToCheck.blockUUID)) return false;
    visitedBlocks.add(blockToCheck.blockUUID);

    // Check current block signatures
    if (blockToCheck.signatures?.some(sig => sig?.address?.toLowerCase() === address?.toLowerCase())) {
      return true;
    }

    // Check parent block
    const parentBlock = chainsData.find(b => b.blockUUID === blockToCheck.parentBlockUUID);
    if (parentBlock && checkSignatures(parentBlock, visitedBlocks)) {
      return true;
    }

    // Check immediate child blocks
    return chainsData
      .filter(b => b.parentBlockUUID === blockToCheck.blockUUID)
      .some(childBlock => checkSignatures(childBlock, visitedBlocks));
  };

  useEffect(() => {
    if (!address) return;

    try {
      const visitedBlocks = new Set<string>();
      setAlreadySigned(checkSignatures(block, visitedBlocks));
    } catch (error) {
      console.error('Error in signature check:', error);
      setAlreadySigned(false);
    }
  }, [address, block, chainsData]);

  const { signMessage } = useSignMessage({
    mutation: {
      onMutate() {
        setError(null);
        setIsSigning(true);
      },
      async onSuccess(signature) {
        if (!address || !node) return;
        
        try {
          if (block.signatures.some(sig => sig.address.toLowerCase() === address.toLowerCase())) {
            setError('You have already signed this chain.');
            return;
          }

          const timestamp = Date.now();
          const newBlock: BlockPayload = {
            chainUUID: block.chainUUID,
            blockUUID: uuidv4(),
            title: block.title,
            description: block.description,
            signedMessage: signature,
            timestamp,
            signatures: [{ address, signature }],
            parentBlockUUID: block.blockUUID
          };

          const wakuMessage = createMessage(newBlock);
          const result = await node.lightPush.send(encoder, wakuMessage);

          Telemetry.push(fromLightPush({
            result,
            node,
            encoder,
            timestamp,
            bookId: block.chainUUID,
            wallet: address,
          }));

          const { failures, successes } = result;
          
          if (failures.length > 0 || successes.length === 0) {
            throw new Error('Failed to send message to Waku network');
          }

          onSuccess(newBlock);
          setIsOpen(false);
        } catch (error) {
          console.error('Error creating new block:', error);
          setError('Failed to create new block. Please try again.');
        }
      },
      onError(error) {
        console.error('Error signing message:', error);
        setError('Error signing message. Please try again. If using a mobile wallet, please ensure your wallet app is open.');
      },
      onSettled() {
        setIsSigning(false);
      }
    }
  });

  const handleSign = async () => {
    try {
      if (!address) {
        setIsWalletPrompt(true);
        const connected = await ensureWalletConnected();
        if (!connected) {
          setError('Please ensure your wallet is connected and the app is open.');
          return;
        }
      }
      
      if (alreadySigned) {
        setError('You have already signed this chain.');
        return;
      }

      const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
      if (isMobile && typeof window.ethereum === 'undefined') {
        setError('Please ensure your wallet app is installed and open before signing.');
        window.location.href = 'metamask:///';
        return;
      }

      const message = [
        'Sign Block:',
        `Chain UUID: ${block.chainUUID}`,
        `Block UUID: ${block.blockUUID}`,
        `Title: ${block.title}`,
        `Description: ${block.description}`,
        `Timestamp: ${new Date().getTime()}`,
        `Parent Block UUID: ${block.parentBlockUUID}`,
        `Signed by: ${ensName || address}`
      ].join('\n');

      signMessage({ message });
    } catch (error) {
      console.error('Error in sign flow:', error);
      setError('Failed to initiate signing. Please ensure your wallet app is open and try again.');
      setIsSigning(false);
    } finally {
      setIsWalletPrompt(false);
    }
  };

  const getButtonText = () => {
    if (isSigning) return 'Signing...';
    if (isWalletPrompt) return 'Connecting...';
    if (alreadySigned) return 'Already Signed';
    if (!address) return 'Connect Wallet';
    return 'Sign';
  };

  const showLoadingSpinner = isSigning || isWalletPrompt;

  return (
    <>
      <Button onClick={() => setIsOpen(true)} disabled={alreadySigned}>
        {alreadySigned ? 'Already Signed' : !address ? 'Connect Wallet' : 'Sign Book'}
      </Button>
      <Dialog open={isOpen} onOpenChange={setIsOpen}>
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>Sign Book</DialogTitle>
            <DialogDescription>
              {alreadySigned 
                ? 'You have already signed this book.'
                : 'Review the block details and sign to add your signature to the book.'}
            </DialogDescription>
          </DialogHeader>
          <div className="flex flex-col space-y-4">
            <div className="space-y-2">
              <h4 className="font-medium">Block Details</h4>
              <p className="text-sm text-muted-foreground">{block.title}</p>
              <p className="text-sm text-muted-foreground">{block.description}</p>
            </div>
            <QRCode text={`${window.location.origin}/sign/${block.chainUUID}/${block.blockUUID}`} />
          </div>
          {(error || isWalletPrompt) && (
            <div className="space-y-2">
              {error && <p className="text-sm text-destructive">{error}</p>}
              {isWalletPrompt && (
                <div className="rounded-md bg-blue-50 p-4">
                  <p className="text-sm text-blue-700">Attempting to connect to your wallet...</p>
                  <p className="text-xs text-blue-600 mt-1">
                    If your wallet doesn't open automatically, please open it manually to approve the connection.
                  </p>
                </div>
              )}
            </div>
          )}
          <DialogFooter>
            <Button variant="secondary" onClick={() => setIsOpen(false)}>Cancel</Button>
            <Button 
              onClick={handleSign} 
              disabled={isSigning || alreadySigned || isWalletPrompt}
            >
              {showLoadingSpinner && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
              {getButtonText()}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  );
};

export default SignChain;
