/*
 This file is part of GNU Taler
 (C) 2022 Taler Systems S.A.
 GNU Taler is free software; you can redistribute it and/or modify it under the
 terms of the GNU General Public License as published by the Free Software
 Foundation; either version 3, or (at your option) any later version.
 GNU Taler 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 General Public License for more details.
 You should have received a copy of the GNU General Public License along with
 GNU Taler; see the file COPYING.  If not, see ();
  const [showDetails, setShowDetails] = useState();
  const [showCashouts, setShowCashouts] = useState();
  const [updatePassword, setUpdatePassword] = useState();
  const [removeAccount, setRemoveAccount] = useState();
  const [showCashoutDetails, setShowCashoutDetails] = useState<
    string | undefined
  >();
  const [createAccount, setCreateAccount] = useState(false);
  const result = useBusinessAccounts({ account });
  const { i18n } = useTranslationContext();
  if (result.loading) return 
;
  if (!result.ok) {
    return handleNotOkResult(i18n, onRegister)(result);
  }
  const { customers } = result.data;
  if (showCashoutDetails) {
    return (
       {
          setShowCashoutDetails(undefined);
        }}
      />
    );
  }
  if (showCashouts) {
    return (
      
    );
  }
  if (showDetails) {
    return (
       {
          setUpdatePassword(showDetails);
          setShowDetails(undefined);
        }}
        onUpdateSuccess={() => {
          notifyInfo(i18n.str`Account updated`);
          setShowDetails(undefined);
        }}
        onClear={() => {
          setShowDetails(undefined);
        }}
      />
    );
  }
  if (removeAccount) {
    return (
       {
          notifyInfo(i18n.str`Account removed`);
          setRemoveAccount(undefined);
        }}
        onClear={() => {
          setRemoveAccount(undefined);
        }}
      />
    );
  }
  if (updatePassword) {
    return (
       {
          notifyInfo(i18n.str`Password changed`);
          setUpdatePassword(undefined);
        }}
        onClear={() => {
          setUpdatePassword(undefined);
        }}
      />
    );
  }
  if (createAccount) {
    return (
       setCreateAccount(false)}
        onCreateSuccess={(password) => {
          notifyInfo(
            i18n.str`Account created with password "${password}". The user must change the password on the next login.`,
          );
          setCreateAccount(false);
        }}
      />
    );
  }
  return (
    
      
        
          Admin panel 
         
                 
      
        
      
      
        {!customers.length ? (
          
        ) : (
          
            {i18n.str`Accounts:`} 
            
           
        )}
       
    
  );
}
function AdminAccount({ onRegister }: { onRegister: () => void }): VNode {
  const { i18n } = useTranslationContext();
  const r = useBackendContext();
  const account = r.state.status === "loggedIn" ? r.state.username : "admin";
  const result = useAccountDetails(account);
  if (!result.ok) {
    return handleNotOkResult(i18n, onRegister)(result);
  }
  const { data } = result;
  const balance = Amounts.parseOrThrow(data.balance.amount);
  const debitThreshold = Amounts.parseOrThrow(result.data.debitThreshold);
  const balanceIsDebit = result.data.balance.credit_debit_indicator == "debit";
  const limit = balanceIsDebit
    ? Amounts.sub(debitThreshold, balance).amount
    : Amounts.add(balance, debitThreshold).amount;
  if (!balance) return 
      
        
          {i18n.str`Bank account balance`} 
          {!balance ? (
            
              Waiting server response...
            
          ) : (
            
              {balanceIsDebit ? -  : null}
              {`${Amounts.stringifyValue(balance)}`} 
               
              {`${balance.currency}`} 
            
          )}
        
 
       
       {
          notifyInfo(i18n.str`Wire transfer created!`);
        }}
      />
      
  );
}
const IBAN_REGEX = /^[A-Z][A-Z0-9]*$/;
const EMAIL_REGEX =
  /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
const REGEX_JUST_NUMBERS_REGEX = /^\+[0-9 ]*$/;
function initializeFromTemplate(
  account: SandboxBackend.Circuit.CircuitAccountData | undefined,
): WithIntermediate {
  const emptyAccount = {
    cashout_address: undefined,
    iban: undefined,
    name: undefined,
    username: undefined,
    contact_data: undefined,
  };
  const emptyContact = {
    email: undefined,
    phone: undefined,
  };
  const initial: PartialButDefined =
    structuredClone(account) ?? emptyAccount;
  if (typeof initial.contact_data === "undefined") {
    initial.contact_data = emptyContact;
  }
  initial.contact_data.email;
  return initial as any;
}
export function UpdateAccountPassword({
  account,
  onClear,
  onUpdateSuccess,
  onLoadNotOk,
}: {
  onLoadNotOk: (
    error: HttpResponsePaginated,
  ) => VNode;
  onClear: () => void;
  onUpdateSuccess: () => void;
  account: string;
}): VNode {
  const { i18n } = useTranslationContext();
  const result = useBusinessAccountDetails(account);
  const { changePassword } = useAdminAccountAPI();
  const [password, setPassword] = useState();
  const [repeat, setRepeat] = useState();
  const [error, saveError] = useState();
  if (!result.ok) {
    if (result.loading || result.type === ErrorType.TIMEOUT) {
      return onLoadNotOk(result);
    }
    if (result.status === HttpStatusCode.NotFound) {
      return account not found
;
    }
    return onLoadNotOk(result);
  }
  const errors = undefinedIfEmpty({
    password: !password ? i18n.str`required` : undefined,
    repeat: !repeat
      ? i18n.str`required`
      : password !== repeat
      ? i18n.str`password doesn't match`
      : undefined,
  });
  return (
    
      
        
          Update password for {account} 
         
      
      {error && (
        
 saveError(undefined)} />
      )}
      
      
  );
}
function CreateNewAccount({
  onClose,
  onCreateSuccess,
}: {
  onClose: () => void;
  onCreateSuccess: (password: string) => void;
}): VNode {
  const { i18n } = useTranslationContext();
  const { createAccount } = useAdminAccountAPI();
  const [submitAccount, setSubmitAccount] = useState<
    SandboxBackend.Circuit.CircuitAccountData | undefined
  >();
  const [error, saveError] = useState();
  return (
    
      
        
          New account 
         
      
      {error && (
        
 saveError(undefined)} />
      )}
      
         {
            setSubmitAccount(a);
          }}
        />
        
          
            
              
            
              
           
        
        
      
  );
}
export function ShowAccountDetails({
  account,
  onClear,
  onUpdateSuccess,
  onLoadNotOk,
  onChangePassword,
}: {
  onLoadNotOk: (
    error: HttpResponsePaginated,
  ) => VNode;
  onClear?: () => void;
  onChangePassword: () => void;
  onUpdateSuccess: () => void;
  account: string;
}): VNode {
  const { i18n } = useTranslationContext();
  const result = useBusinessAccountDetails(account);
  const { updateAccount } = useAdminAccountAPI();
  const [update, setUpdate] = useState(false);
  const [submitAccount, setSubmitAccount] = useState<
    SandboxBackend.Circuit.CircuitAccountData | undefined
  >();
  const [error, saveError] = useState();
  if (!result.ok) {
    if (result.loading || result.type === ErrorType.TIMEOUT) {
      return onLoadNotOk(result);
    }
    if (result.status === HttpStatusCode.NotFound) {
      return account not found
;
    }
    return onLoadNotOk(result);
  }
  return (
    
      
        
          Business account details 
         
      
      {error && (
        
 saveError(undefined)} />
      )}
      
         setSubmitAccount(a)}
        />
        
          
            
              {onClear ? (
                
            
              
                
              
                
             
           
        
        
      
  );
}
function RemoveAccount({
  account,
  onClear,
  onUpdateSuccess,
  onLoadNotOk,
}: {
  onLoadNotOk: (
    error: HttpResponsePaginated,
  ) => VNode;
  onClear: () => void;
  onUpdateSuccess: () => void;
  account: string;
}): VNode {
  const { i18n } = useTranslationContext();
  const result = useAccountDetails(account);
  const { deleteAccount } = useAdminAccountAPI();
  const [error, saveError] = useState();
  if (!result.ok) {
    if (result.loading || result.type === ErrorType.TIMEOUT) {
      return onLoadNotOk(result);
    }
    if (result.status === HttpStatusCode.NotFound) {
      return account not found
;
    }
    return onLoadNotOk(result);
  }
  const balance = Amounts.parse(result.data.balance.amount);
  if (!balance) {
    return there was an error reading the balance
;
  }
  const isBalanceEmpty = Amounts.isZero(balance);
  return (
    
      
        
          Remove account: {account} 
         
      
      {!isBalanceEmpty && (
        
 saveError(undefined)}
        />
      )}
      {error && (
         saveError(undefined)} />
      )}
      
        
      
       
  );
}
/**
 * Create valid account object to update or create
 * Take template as initial values for the form
 * Purpose indicate if all field al read only (show), part of them (update)
 * or none (create)
 * @param param0
 * @returns
 */
function AccountForm({
  template,
  purpose,
  onChange,
}: {
  template: SandboxBackend.Circuit.CircuitAccountData | undefined;
  onChange: (a: SandboxBackend.Circuit.CircuitAccountData | undefined) => void;
  purpose: "create" | "update" | "show";
}): VNode {
  const initial = initializeFromTemplate(template);
  const [form, setForm] = useState(initial);
  const [errors, setErrors] = useState<
    RecursivePartial | undefined
  >(undefined);
  const { i18n } = useTranslationContext();
  function updateForm(newForm: typeof initial): void {
    const parsed = !newForm.cashout_address
      ? undefined
      : parsePaytoUri(newForm.cashout_address);
    const errors = undefinedIfEmpty>({
      cashout_address: !newForm.cashout_address
        ? i18n.str`required`
        : !parsed
        ? i18n.str`does not follow the pattern`
        : !parsed.isKnown || parsed.targetType !== "iban"
        ? i18n.str`only "IBAN" target are supported`
        : !IBAN_REGEX.test(parsed.iban)
        ? i18n.str`IBAN should have just uppercased letters and numbers`
        : validateIBAN(parsed.iban, i18n),
      contact_data: undefinedIfEmpty({
        email: !newForm.contact_data?.email
          ? i18n.str`required`
          : !EMAIL_REGEX.test(newForm.contact_data.email)
          ? i18n.str`it should be an email`
          : undefined,
        phone: !newForm.contact_data?.phone
          ? i18n.str`required`
          : !newForm.contact_data.phone.startsWith("+")
          ? i18n.str`should start with +`
          : !REGEX_JUST_NUMBERS_REGEX.test(newForm.contact_data.phone)
          ? i18n.str`phone number can't have other than numbers`
          : undefined,
      }),
      iban: !newForm.iban
        ? undefined //optional field
        : !IBAN_REGEX.test(newForm.iban)
        ? i18n.str`IBAN should have just uppercased letters and numbers`
        : validateIBAN(newForm.iban, i18n),
      name: !newForm.name ? i18n.str`required` : undefined,
      username: !newForm.username ? i18n.str`required` : undefined,
    });
    setErrors(errors);
    setForm(newForm);
    onChange(errors === undefined ? (newForm as any) : undefined);
  }
  return (
    
  );
}