import React, { useState, useEffect, useCallback } from 'react';
import { ethers } from 'ethers';
import { connectWallet as connectWalletUtil } from './utils/contract';

import Header from './components/Header';
import ConnectWallet from './components/ConnectWallet';
import WorkflowStatus from './components/WorkflowStatus';
import VoterManagement from './components/VoterManagement';
import ProposalManagement from './components/ProposalManagement';
import VotingSession from './components/VotingSession';

function App() {
  const [account, setAccount] = useState(null);
  const [contract, setContract] = useState(null);
  const [isOwner, setIsOwner] = useState(false);
  const [isVoter, setIsVoter] = useState(false);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  const [currentStatus, setCurrentStatus] = useState(0);
  const [proposals, setProposals] = useState([]);
  const [voterInfo, setVoterInfo] = useState({ isRegistered: false, hasVoted: false, votedProposalId: 0 });

  // Connexion au portefeuille Ethereum
  const connectWalletHandler = async () => {
    try {
      setLoading(true);
      setError(null);
      const { accounts, contract: votingContract } = await connectWalletUtil();
      
      setAccount(accounts[0]);
      setContract(votingContract);
      
      // Vérification si l'utilisateur est le propriétaire du contrat
      const contractOwner = await votingContract.owner();
      setIsOwner(accounts[0].toLowerCase() === contractOwner.toLowerCase());
      
      // Récupération du statut actuel du workflow
      const status = await votingContract.workflowStatus();
      setCurrentStatus(status.toString());
      
      // Vérification si l'utilisateur est un électeur inscrit
      try {
        const voter = await votingContract.getVoter(accounts[0]);
        setIsVoter(voter.isRegistered);
        setVoterInfo({
          isRegistered: voter.isRegistered,
          hasVoted: voter.hasVoted,
          votedProposalId: voter.votedProposalId.toString()
        });
      } catch (error) {
        // Si l'utilisateur n'est pas un électeur, une erreur est générée
        setIsVoter(false);
      }
      
      setLoading(false);
    } catch (error) {
      console.error("Erreur lors de la connexion:", error);
      setError("Impossible de se connecter au portefeuille. Assurez-vous que MetaMask est installé et connecté.");
      setLoading(false);
    }
  };

  // Mise à jour du statut du workflow
  const updateWorkflowStatus = useCallback(async () => {
    if (!contract) return;
    
    try {
      const status = await contract.workflowStatus();
      setCurrentStatus(status.toString());
    } catch (error) {
      console.error("Erreur lors de la récupération du statut:", error);
    }
  }, [contract]);

  // Actions liées au workflow
  const handleWorkflowAction = async (action, duration = 60) => {
    if (!contract) return;
    
    try {
      setLoading(true);
      let tx;
      
      switch (action) {
        case 'startProposalsRegistration':
          tx = await contract.startProposalsRegistration(duration);
          break;
        case 'endProposalsRegistration':
          tx = await contract.endProposalsRegistration();
          break;
        case 'startVotingSession':
          tx = await contract.startVotingSession(duration);
          break;
        case 'endVotingSession':
          tx = await contract.endVotingSession();
          break;
        case 'tallyVotes':
          tx = await contract.tallyVotes();
          break;
        default:
          throw new Error("Action non reconnue");
      }
      
      await tx.wait();
      await updateWorkflowStatus();
      
      // Si nous passons à la phase de vote ou de résultats, récupérons les propositions
      if (action === 'startVotingSession' || action === 'tallyVotes') {
        await fetchProposals();
      }
      
      setLoading(false);
    } catch (error) {
      console.error(`Erreur lors de l'action ${action}:`, error);
      setError(`Erreur lors de l'action: ${error.message}`);
      setLoading(false);
    }
  };

  // Ajout d'un électeur
  const addVoter = async (voterAddress) => {
    if (!contract) return;
    
    try {
      setLoading(true);
      const tx = await contract.registerVoter(voterAddress);
      await tx.wait();
      setLoading(false);
    } catch (error) {
      console.error("Erreur lors de l'ajout de l'électeur:", error);
      setError(`Erreur: ${error.message}`);
      setLoading(false);
    }
  };

  // Récupération des informations de l'électeur
  const fetchVoterInfo = useCallback(async () => {
    if (!contract || !account || !isVoter) return;
    
    try {
      const voter = await contract.getVoter(account);
      setVoterInfo({
        isRegistered: voter.isRegistered,
        hasVoted: voter.hasVoted,
        votedProposalId: voter.votedProposalId.toString()
      });
    } catch (error) {
      console.error("Erreur lors de la récupération des infos de l'électeur:", error);
    }
  }, [contract, account, isVoter]);

  // Soumission d'une proposition
  const submitProposal = async (description) => {
    if (!contract) return;
    
    try {
      setLoading(true);
      const tx = await contract.registerProposal(description);
      await tx.wait();
      await fetchProposals();
      setLoading(false);
    } catch (error) {
      console.error("Erreur lors de la soumission de la proposition:", error);
      setError(`Erreur: ${error.message}`);
      setLoading(false);
    }
  };

  // Récupération des propositions
  const fetchProposals = useCallback(async () => {
    if (!contract || !isVoter) return;
    
    try {
      const proposalsCount = await contract.getProposalsCount();
      const proposalsList = [];
      
      for (let i = 0; i < proposalsCount; i++) {
        const proposal = await contract.getProposal(i);
        proposalsList.push({
          description: proposal.description,
          voteCount: proposal.voteCount.toString()
        });
      }
      
      setProposals(proposalsList);
    } catch (error) {
      console.error("Erreur lors de la récupération des propositions:", error);
    }
  }, [contract, isVoter]);

  // Soumission d'un vote
  const submitVote = async (proposalId) => {
    if (!contract) return;
    
    try {
      setLoading(true);
      const tx = await contract.vote(proposalId);
      await tx.wait();
      await fetchVoterInfo();
      setLoading(false);
    } catch (error) {
      console.error("Erreur lors du vote:", error);
      setError(`Erreur: ${error.message}`);
      setLoading(false);
    }
  };

  // Délégation de vote
  const delegateVote = async (delegateAddress) => {
    if (!contract) return;
    
    try {
      setLoading(true);
      const tx = await contract.delegateVoteTo(delegateAddress);
      await tx.wait();
      await fetchVoterInfo();
      setLoading(false);
    } catch (error) {
      console.error("Erreur lors de la délégation du vote:", error);
      setError(`Erreur: ${error.message}`);
      setLoading(false);
    }
  };

  // Détection des changements de compte
  useEffect(() => {
    if (window.ethereum) {
      window.ethereum.on('accountsChanged', (accounts) => {
        window.location.reload();
      });
    }
  }, []);

  // Mise à jour automatique des données
  useEffect(() => {
    const interval = setInterval(() => {
      if (contract) {
        updateWorkflowStatus();
        if (isVoter) {
          fetchVoterInfo();
          fetchProposals();
        }
      }
    }, 10000); // Mettre à jour toutes les 10 secondes
    
    return () => clearInterval(interval);
  }, [contract, isVoter, updateWorkflowStatus, fetchVoterInfo, fetchProposals]);

  return (
    <div className="App">
      <Header account={account} isOwner={isOwner} />
      
      <div className="container">
        {error && (
          <div className="status error">
            {error}
            <button className="close-button" onClick={() => setError(null)}>×</button>
          </div>
        )}
        
        {!account ? (
          <ConnectWallet connectWallet={connectWalletHandler} loading={loading} />
        ) : (
          <>
            <WorkflowStatus 
              status={currentStatus} 
              isOwner={isOwner} 
              onAction={handleWorkflowAction}
              loading={loading}
            />
            
            <VoterManagement 
              isOwner={isOwner} 
              addVoter={addVoter} 
              loading={loading}
              isVoter={isVoter}
              currentStatus={currentStatus}
            />
            
            <ProposalManagement 
              isVoter={isVoter}
              submitProposal={submitProposal}
              fetchProposals={fetchProposals}
              currentStatus={currentStatus}
              proposals={proposals}
              loading={loading}
            />
            
            <VotingSession 
              isVoter={isVoter}
              submitVote={submitVote}
              delegateVote={delegateVote}
              fetchVoterInfo={fetchVoterInfo}
              fetchProposals={fetchProposals}
              currentStatus={currentStatus}
              proposals={proposals}
              loading={loading}
              voterInfo={voterInfo}
            />
          </>
        )}
      </div>
    </div>
  );
}

export default App;