src/lightspeed/integration/data.gleam

//// Data integration patterns for ecosystem compatibility (M26).

import gleam/int
import lightspeed/data/repository

/// Migration-track strategy for integrating data boundaries.
pub type MigrationTrack {
  DualWriteFirst
  ReadReplicaFirst
  BigBangCutover
}

/// One data integration pattern.
pub type Pattern {
  Pattern(
    name: String,
    adapter: repository.Adapter,
    migration_track: MigrationTrack,
    scope_enforced: Bool,
    retry_budget: Int,
    read_after_write_check: Bool,
  )
}

/// CRUD-oriented mixed-runtime data pattern.
pub fn crud_pattern() -> Pattern {
  Pattern(
    name: "crud_mixed_runtime",
    adapter: repository.MixedBridge(
      read_module: "MyApp.RepoRead",
      write_module: "MyApp.RepoWrite",
    ),
    migration_track: DualWriteFirst,
    scope_enforced: True,
    retry_budget: 3,
    read_after_write_check: True,
  )
}

/// Event-stream oriented data pattern.
pub fn event_stream_pattern() -> Pattern {
  Pattern(
    name: "event_stream_bridge",
    adapter: repository.ElixirBridge(module: "MyApp.EventStore"),
    migration_track: ReadReplicaFirst,
    scope_enforced: True,
    retry_budget: 5,
    read_after_write_check: True,
  )
}

/// In-memory local development fallback pattern.
pub fn local_dev_pattern() -> Pattern {
  Pattern(
    name: "local_dev_in_memory",
    adapter: repository.GleamInMemory,
    migration_track: BigBangCutover,
    scope_enforced: True,
    retry_budget: 1,
    read_after_write_check: True,
  )
}

/// Validate data integration constraints.
pub fn valid(pattern: Pattern) -> Bool {
  pattern.scope_enforced
  && pattern.retry_budget > 0
  && pattern.read_after_write_check
  && adapter_track_compatible(pattern.adapter, pattern.migration_track)
}

/// Stable migration-track label.
pub fn migration_track_label(track: MigrationTrack) -> String {
  case track {
    DualWriteFirst -> "dual_write_first"
    ReadReplicaFirst -> "read_replica_first"
    BigBangCutover -> "big_bang_cutover"
  }
}

/// Stable pattern signature.
pub fn signature(pattern: Pattern) -> String {
  "data:"
  <> pattern.name
  <> "|adapter="
  <> repository.adapter_label(pattern.adapter)
  <> "|track="
  <> migration_track_label(pattern.migration_track)
  <> "|scope_enforced="
  <> bool_label(pattern.scope_enforced)
  <> "|retry_budget="
  <> int.to_string(pattern.retry_budget)
  <> "|read_after_write_check="
  <> bool_label(pattern.read_after_write_check)
}

/// Pattern adapter.
pub fn adapter(pattern: Pattern) -> repository.Adapter {
  pattern.adapter
}

/// Pattern name.
pub fn name(pattern: Pattern) -> String {
  pattern.name
}

fn adapter_track_compatible(
  adapter: repository.Adapter,
  track: MigrationTrack,
) -> Bool {
  case adapter, track {
    repository.GleamInMemory, BigBangCutover -> True
    repository.GleamInMemory, _ -> False
    _, _ -> True
  }
}

fn bool_label(value: Bool) -> String {
  case value {
    True -> "true"
    False -> "false"
  }
}