use std::io::*;
use std::str::FromStr;

//https://docs.rs/permutohedron/0.2.4/src/permutohedron/lexical.rs.html#23-30
pub trait LexicalPermutation {
    /// Return `true` if the slice was permuted, `false` if it is already
    /// at the last ordered permutation.
    fn next_permutation(&mut self) -> bool;
}
 
impl<T> LexicalPermutation for [T]
where
    T: Ord,
{
    /// Original author in Rust: Thomas Backman <serenity@exscape.org>
    fn next_permutation(&mut self) -> bool {
        // These cases only have 1 permutation each, so we can't do anything.
        if self.len() < 2 {
            return false;
        }
 
        // Step 1: Identify the longest, rightmost weakly decreasing part of the vector
        let mut i = self.len() - 1;
        while i > 0 && self[i - 1] >= self[i] {
            i -= 1;
        }
 
        // If that is the entire vector, this is the last-ordered permutation.
        if i == 0 {
            return false;
        }
 
        // Step 2: Find the rightmost element larger than the pivot (i-1)
        let mut j = self.len() - 1;
        //while j >= i && self[j] <= self[i - 1] {
        while self[j] <= self[i - 1] {
            j -= 1;
        }
 
        // Step 3: Swap that element with the pivot
        self.swap(i -1 , j);
 
        // Step 4: Reverse the (previously) weakly decreasing part
        self[i..].reverse();
 
        true
    }
}

//https://onlinejudge.u-aizu.ac.jp/solutions/problem/ALDS1_5_B/review/2709881/arsenic28/Rust
trait Joinable {
    fn join(self, sep: &str) -> String;
}

impl<U: ToString, T: Iterator<Item = U>> Joinable for T {
    fn join(self, sep: &str) -> String {
        self.map(|x| x.to_string()).collect::<Vec<_>>().join(sep)
    }
}

//https://qiita.com/tubo28/items/e6076e9040da57368845
fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

//https://atcoder.jp/contests/agc022/submissions/14854736
//https://iloveconviniboshi.hatenablog.com/entry/2019/11/19/013117
fn main() {
    let mut s: Vec<char> = read::<String>().chars().collect();

    //25字以下のとき
	//与えられた文字列 + ( a ~ zで入力に存在しない文字の最小の文字）
    if s.len() < 26 {
        //文字aからzまでの順番にsにその文字が使われているかチェック
        //未使用であるならばvecに追加していき、unuseに格納される。
        let unuse = (b'a'..=b'z').map(char::from).filter(|c| !s.contains(c)).collect::<Vec<_>>();
        s.push(unuse[0]);
        println!("{}",s.iter().join(""));
        return;
    }
    //26字のとき
    let mut next_s = s.clone();
    //辞書順で次の単語を得る
    let has_next = next_s.next_permutation();

    //終端の場合は-1
    if !has_next {
        println!("-1");
        return;
    }

    let mut ans:Vec<char> = Vec::new();

    //辞書順の次の単語と文字列sを比較して違う文字が出てくるところまでをansに追加する
    //zipで２つのiteratorをペアにして回す
    for (n, o) in next_s.iter().zip(s.iter()){
        ans.push(*n);
        if n != o {
            break;
        }
    }
    
    /*for i in 0..26{
        ans.push(next_s[i]);
        if next_s[i] != s[i] {
            break;
        }
    }*/
    println!("{}",ans.iter().join(""));


}


Measured memory_bytes: 2160