/*
 This file is part of GNU Anastasis
 (C) 2021-2022 Anastasis SARL
 GNU Anastasis is free software; you can redistribute it and/or modify it under the
 terms of the GNU Affero General Public License as published by the Free Software
 Foundation; either version 3, or (at your option) any later version.
 GNU Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.
 You should have received a copy of the GNU Affero General Public License along with
 GNU Anastasis; see the file COPYING.  If not, see 
 */
import {
  ChallengeFeedback,
  ChallengeFeedbackStatus,
} from "@gnu-taler/anastasis-core";
import { h, VNode } from "preact";
import { AsyncButton } from "../../components/AsyncButton.js";
import { useAnastasisContext } from "../../context/anastasis.js";
import { authMethods, KnownAuthMethods } from "./authMethod/index.js";
import { AnastasisClientFrame } from "./index.js";
function OverviewFeedbackDisplay(props: { feedback?: ChallengeFeedback }) {
  const { feedback } = props;
  if (!feedback) {
    return null;
  }
  switch (feedback.state) {
    case ChallengeFeedbackStatus.Solved:
      return 
;
    case ChallengeFeedbackStatus.IbanInstructions:
      return null;
    case ChallengeFeedbackStatus.ServerFailure:
      return Server error.
;
    case ChallengeFeedbackStatus.RateLimitExceeded:
      return (
        
          There were to many failed attempts.
        
      );
    case ChallengeFeedbackStatus.Unsupported:
      return (
        
          This client doesn't support solving this type of challenge. Use
          another version or contact the provider.
        
      );
    case ChallengeFeedbackStatus.TruthUnknown:
      return (
        
          Provider doesn't recognize the challenge of the policy. Contact
          the provider for further information.
        
      );
    default:
      return ;
  }
}
export function ChallengeOverviewScreen(): VNode {
  const reducer = useAnastasisContext();
  if (!reducer) {
    return no reducer in context
;
  }
  if (reducer.currentReducerState?.reducer_type !== "recovery") {
    return invalid state
;
  }
  const policies =
    reducer.currentReducerState.recovery_information?.policies ?? [];
  const knownChallengesArray =
    reducer.currentReducerState.recovery_information?.challenges ?? [];
  const challengeFeedback =
    reducer.currentReducerState?.challenge_feedback ?? {};
  const knownChallengesMap: {
    [uuid: string]: {
      type: string;
      instructions: string;
      feedback: ChallengeFeedback | undefined;
    };
  } = {};
  for (const ch of knownChallengesArray) {
    knownChallengesMap[ch.uuid] = {
      type: ch.type,
      instructions: ch.instructions,
      feedback: challengeFeedback[ch.uuid],
    };
  }
  const policiesWithInfo = policies
    .map((row) => {
      let isPolicySolved = true;
      const challenges = row
        .map(({ uuid }) => {
          const info = knownChallengesMap[uuid];
          const isChallengeSolved = info?.feedback?.state === "solved";
          isPolicySolved = isPolicySolved && isChallengeSolved;
          return { info, uuid, isChallengeSolved };
        })
        .filter((ch) => ch.info !== undefined);
      return {
        isPolicySolved,
        challenges,
        corrupted: row.length > challenges.length,
      };
    })
    .filter((p) => !p.corrupted);
  const atLeastThereIsOnePolicySolved =
    policiesWithInfo.find((p) => p.isPolicySolved) !== undefined;
  const errors = !atLeastThereIsOnePolicySolved
    ? "Solve one policy before proceeding"
    : undefined;
  return (
    
      {!policiesWithInfo.length ? (
        
          No policies found, try with another version of the secret
        
      ) : policiesWithInfo.length === 1 ? (
        
          One policy found for this secret. You need to solve all the challenges
          in order to recover your secret.
        
      ) : (
        
          We have found {policiesWithInfo.length} polices. You need to solve all
          the challenges from one policy in order to recover your secret.
        
      )}
      {policiesWithInfo.map((policy, policy_index) => {
        const tableBody = policy.challenges.map(({ info, uuid }) => {
          const method = authMethods[info.type as KnownAuthMethods];
          if (!method) {
            return (
              
            );
          }
          function ChallengeButton({
            id,
            feedback,
          }: {
            id: string;
            feedback?: ChallengeFeedback;
          }): VNode {
            async function selectChallenge(): Promise {
              if (reducer) {
                return reducer.transition("select_challenge", { uuid: id });
              }
            }
            if (!feedback) {
              return (
                
              );
            }
            switch (feedback.state) {
              case ChallengeFeedbackStatus.ServerFailure:
              case ChallengeFeedbackStatus.Unsupported:
              case ChallengeFeedbackStatus.TruthUnknown:
              case ChallengeFeedbackStatus.RateLimitExceeded:
                return ;
              case ChallengeFeedbackStatus.IbanInstructions:
              case ChallengeFeedbackStatus.TalerPayment:
                return (
                  
                );
              case ChallengeFeedbackStatus.Solved:
                return (
                  
                );
              default:
                return (
                  
                );
            }
          }
          return (
            
              
                
                  {method?.icon}
                  {info.instructions}
                
                
               
              
             
          );
        });
        const policyName = policy.challenges
          .map((x) => x.info.type)
          .join(" + ");
        const opa = !atLeastThereIsOnePolicySolved
          ? undefined
          : policy.isPolicySolved
          ? undefined
          : "0.6";
        return (
          
            
              Policy #{policy_index + 1}: {policyName}
            
            {policy.challenges.length === 0 && (
              
This policy doesn't have any challenges.
            )}
            {policy.challenges.length === 1 && (
              
This policy has one challenge.
            )}
            {policy.challenges.length > 1 && (
              
This policy has {policy.challenges.length} challenges.
            )}
            {tableBody}
          
 
        );
      })}
    
  );
}