use blizz::SelectEnum;

#[derive(SelectEnum, Debug, PartialEq)]
enum BasicChoice {
  Yes,
  No,
}

#[test]
fn default_labels_are_variant_names() {
  let opts = BasicChoice::options();
  assert_eq!(opts[0].label, "Yes");
  assert_eq!(opts[1].label, "No");
}

#[test]
fn default_values_are_snake_case() {
  let opts = BasicChoice::options();
  assert_eq!(opts[0].value, "yes");
  assert_eq!(opts[1].value, "no");
}

#[test]
fn from_value_round_trips() {
  assert_eq!(BasicChoice::from_value("yes"), Some(BasicChoice::Yes));
  assert_eq!(BasicChoice::from_value("no"), Some(BasicChoice::No));
  assert_eq!(BasicChoice::from_value("maybe"), None);
}

#[test]
fn options_count_matches_variants() {
  assert_eq!(BasicChoice::options().len(), 2);
}

#[derive(SelectEnum, Debug, PartialEq)]
enum WithLabels {
  #[select(label = "Install it")]
  Install,
  #[select(label = "Skip for now")]
  Skip,
}

#[test]
fn label_attribute_overrides_default() {
  let opts = WithLabels::options();
  assert_eq!(opts[0].label, "Install it");
  assert_eq!(opts[1].label, "Skip for now");
}

#[test]
fn label_override_keeps_default_value() {
  let opts = WithLabels::options();
  assert_eq!(opts[0].value, "install");
  assert_eq!(opts[1].value, "skip");
}

#[derive(SelectEnum, Debug, PartialEq)]
enum WithValues {
  #[select(value = "y")]
  Yes,
  #[select(value = "n")]
  No,
}

#[test]
fn value_attribute_overrides_default() {
  let opts = WithValues::options();
  assert_eq!(opts[0].value, "y");
  assert_eq!(opts[1].value, "n");
}

#[test]
fn from_value_uses_overridden_values() {
  assert_eq!(WithValues::from_value("y"), Some(WithValues::Yes));
  assert_eq!(WithValues::from_value("n"), Some(WithValues::No));
  assert_eq!(WithValues::from_value("yes"), None);
}

#[derive(SelectEnum, Debug, PartialEq)]
enum BothOverrides {
  #[select(label = "Absolutely", value = "sure")]
  Yes,
  #[select(label = "No way", value = "nope")]
  No,
}

#[test]
fn both_label_and_value_can_be_overridden() {
  let opts = BothOverrides::options();
  assert_eq!(opts[0].label, "Absolutely");
  assert_eq!(opts[0].value, "sure");
  assert_eq!(opts[1].label, "No way");
  assert_eq!(opts[1].value, "nope");
  assert_eq!(BothOverrides::from_value("sure"), Some(BothOverrides::Yes));
  assert_eq!(BothOverrides::from_value("nope"), Some(BothOverrides::No));
}

#[derive(SelectEnum, Debug, PartialEq)]
enum CamelCase {
  FirstOption,
  SecondOption,
  ThirdOne,
}

#[test]
fn camel_case_variants_become_snake_case_values() {
  let opts = CamelCase::options();
  assert_eq!(opts[0].value, "first_option");
  assert_eq!(opts[1].value, "second_option");
  assert_eq!(opts[2].value, "third_one");
}

#[test]
fn camel_case_from_value_round_trips() {
  assert_eq!(
    CamelCase::from_value("first_option"),
    Some(CamelCase::FirstOption)
  );
  assert_eq!(
    CamelCase::from_value("third_one"),
    Some(CamelCase::ThirdOne)
  );
}

#[derive(SelectEnum, Debug, PartialEq)]
enum Single {
  Only,
}

#[test]
fn single_variant_enum_works() {
  assert_eq!(Single::options().len(), 1);
  assert_eq!(Single::from_value("only"), Some(Single::Only));
}
