// Copyright Two Neutron Stars Incorporated and contributors
// SPDX-License-Identifier: BlueOak-1.0.0

//! Public API smoke tests for symbolique.

use symbolique::*;

#[test]
fn symbol_definition_methods() {
  let sym: Symbol<DefaultValue, StringIdent, String> = Symbol::Definition {
    name: StringIdent::new("foo"),
    value: Some(DefaultValue::Integer(42)),
    visibility: SymbolVisibility::Public,
  };
  assert_eq!(sym.kind(), "definition");
  assert!(sym.has_value());
  assert!(!sym.is_reference());
  assert!(!sym.is_import());
}

#[test]
fn symbol_reference_methods() {
  let sym: Symbol<DefaultValue, StringIdent, String> = Symbol::Reference {
    path: "ref::bar".to_string(),
    name: Some(StringIdent::new("bar")),
    target_path: "mod::bar".to_string(),
    is_absolute: true,
    nameable: true,
  };
  assert_eq!(sym.kind(), "reference");
  assert!(sym.is_reference());
  assert!(sym.is_absolute_reference());
  assert_eq!(sym.target_path(), Some(&"mod::bar".to_string()));
}

#[test]
fn default_value_variants() {
  let s = DefaultValue::String("hello".to_string());
  let i = DefaultValue::Integer(42);
  let f = DefaultValue::Float(2.72);
  let b = DefaultValue::Boolean(true);

  assert_eq!(s, DefaultValue::String("hello".to_string()));
  assert_eq!(i, DefaultValue::Integer(42));
  assert_eq!(f, DefaultValue::Float(2.72));
  assert_eq!(b, DefaultValue::Boolean(true));
}

#[test]
fn resolution_enum_variants() {
  let failed = Resolution::<DefaultValue, StringIdent, String>::Unresolved;
  assert!(failed.is_failed());
  assert!(!failed.is_resolved());
  assert!(failed.symbol_id().is_none());

  let deferred = Resolution::<DefaultValue, StringIdent, String>::Deferred;
  assert!(deferred.is_deferred());
}

#[test]
fn error_builder_pattern() {
  let err = Error::new("test error".to_string(), None)
    .with_severity(Severity::Warning)
    .with_context("some context".to_string())
    .with_suggestion("try this".to_string());

  assert!(!err.is_error());
  assert!(err.has_context());
  assert!(err.has_suggestions());
  assert_eq!(err.severity.as_str(), "warning");
}

#[test]
fn default_resolver_returns_failed() {
  let resolver = DefaultResolver;
  let mut cache = laburnum::SpanCache::new(1, 0);
  let span = laburnum::Span::new(&mut cache, 0, 5);
  let hash = laburnum::ContentHash::new(b"test");
  let handle = laburnum::database::RecordHandle::<symbolique::Symbols<DefaultValue, StringIdent, String>>::new(hash);
  let entry = symbolique::SymbolEntry::new("foo".to_string(), span, handle);

  let result = resolver.resolve(
    &symbolique::EmptyResolveCtx,
    &"foo::bar".to_string(),
    &"caller".to_string(),
    entry,
  );
  assert!(result.is_failed());
}
