# Storage Schema - Volume and storage configurations for provisioning
# Version: 1.0.0

{
  # Docker volume configuration
  DockerVolume = {
    name
      | String
      | doc "Volume name"
      | {
        label = "valid volume name",
        predicate = fun s =>
          std.string.is_match "^[a-z0-9-]+$" s &&
          std.string.length s >= 1 && std.string.length s <= 64
      },

    driver
      | [| 'local, 'nfs, 'cifs |]
      | doc "Volume driver"
      | default = 'local,

    driver_opts
      | {_: String}
      | doc "Driver-specific options"
      | default = {},

    external
      | Bool
      | doc "Use existing external volume"
      | default = false,

    labels
      | {_: String}
      | doc "Volume labels for metadata"
      | default = {},
  },

  # Volume mount configuration
  VolumeMount = {
    source
      | String
      | doc "Source volume or host path",

    target
      | String
      | doc "Target path in container"
      | {
        label = "valid path",
        predicate = fun s => std.string.length s >= 1 && std.string.length s <= 256
      },

    type
      | [| 'volume, 'bind, 'tmpfs |]
      | doc "Mount type"
      | default = 'volume,

    read_only
      | Bool
      | doc "Mount as read-only"
      | default = false,

    volume_options
      | {
        nocopy
          | Bool
          | doc "Disable copying data from container to volume"
          | default = false,

        labels
          | {_: String}
          | doc "Labels for the volume"
          | default = {},
      }
      | doc "Volume-specific options"
      | optional,

    bind_options
      | {
        propagation
          | [| 'private, 'rprivate, 'shared, 'rshared, 'slave, 'rslave |]
          | doc "Bind propagation mode"
          | default = 'rprivate,

        create_host_path
          | Bool
          | doc "Create host path if it doesn't exist"
          | default = false,
      }
      | doc "Bind mount-specific options"
      | optional,

    tmpfs_options
      | {
        size
          | String
          | doc "Size of tmpfs mount (e.g., '100Mi')"
          | {
            label = "valid size",
            predicate = fun s =>
              std.string.is_match "^[0-9]+(Mi|Gi|M|G|Ki|K)$" s
          }
          | optional,

        mode
          | Number
          | doc "File mode in octal (e.g., 1777)"
          | optional,
      }
      | doc "Tmpfs mount-specific options"
      | optional,
  },

  # Kubernetes PersistentVolume configuration
  KubernetesPersistentVolume = {
    name
      | String
      | doc "PersistentVolume name"
      | {
        label = "valid name",
        predicate = fun s =>
          std.string.is_match "^[a-z0-9-]+$" s &&
          std.string.length s >= 1 && std.string.length s <= 64
      },

    capacity
      | String
      | doc "Storage capacity (e.g., '10Gi')"
      | {
        label = "valid capacity",
        predicate = fun s =>
          std.string.is_match "^[0-9]+(Mi|Gi|Ti|M|G|T)$" s
      },

    access_modes
      | Array ([| 'ReadWriteOnce, 'ReadOnlyMany, 'ReadWriteMany, 'ReadWriteOncePod |])
      | doc "Access modes for the volume",

    reclaim_policy
      | [| 'Retain, 'Recycle, 'Delete |]
      | doc "Reclaim policy when PVC is deleted"
      | default = 'Retain,

    storage_class_name
      | String
      | doc "Storage class name"
      | optional,

    host_path
      | {
        path
          | String
          | doc "Path on the host node",

        type
          | [| 'DirectoryOrCreate, 'Directory, 'FileOrCreate, 'File, 'Socket, 'CharDevice, 'BlockDevice |]
          | doc "Type of host path"
          | default = 'DirectoryOrCreate,
      }
      | doc "Host path configuration"
      | optional,

    nfs
      | {
        server
          | String
          | doc "NFS server hostname or IP",

        path
          | String
          | doc "Exported NFS path",

        read_only
          | Bool
          | doc "Mount as read-only"
          | default = false,
      }
      | doc "NFS volume configuration"
      | optional,

    local
      | {
        path
          | String
          | doc "Local path on the node",
      }
      | doc "Local volume configuration"
      | optional,

    mount_options
      | Array String
      | doc "Mount options for the volume"
      | default = [],

    labels
      | {_: String}
      | doc "Volume labels"
      | default = {},
  },

  # Kubernetes PersistentVolumeClaim configuration
  KubernetesPersistentVolumeClaim = {
    name
      | String
      | doc "PersistentVolumeClaim name"
      | {
        label = "valid name",
        predicate = fun s =>
          std.string.is_match "^[a-z0-9-]+$" s &&
          std.string.length s >= 1 && std.string.length s <= 64
      },

    storage_class_name
      | String
      | doc "Storage class name"
      | optional,

    access_modes
      | Array ([| 'ReadWriteOnce, 'ReadOnlyMany, 'ReadWriteMany, 'ReadWriteOncePod |])
      | doc "Access modes for the volume",

    resources
      | {
        requests
          | {
            storage
              | String
              | doc "Requested storage size (e.g., '10Gi')"
              | {
                label = "valid size",
                predicate = fun s =>
                  std.string.is_match "^[0-9]+(Mi|Gi|Ti|M|G|T)$" s
              },
          }
          | doc "Resource requests",

        limits
          | {
            storage
              | String
              | doc "Storage limit (e.g., '20Gi')"
              | {
                label = "valid size",
                predicate = fun s =>
                  std.string.is_match "^[0-9]+(Mi|Gi|Ti|M|G|T)$" s
              }
              | optional,
          }
          | doc "Resource limits"
          | optional,
      }
      | doc "Resource requirements",

    volume_name
      | String
      | doc "Name of specific PV to bind to"
      | optional,

    selector
      | {
        matchLabels
          | {_: String}
          | doc "Label selector"
          | optional,
      }
      | doc "Label selector for binding to PV"
      | optional,

    volume_mode
      | [| 'Filesystem, 'Block |]
      | doc "Volume mode"
      | default = 'Filesystem,
  },

  # Main storage configuration
  StorageConfig = {
    docker_volumes
      | {_: DockerVolume}
      | doc "Docker volumes definition"
      | default = {},

    volume_mounts
      | Array VolumeMount
      | doc "Volume mounts for services"
      | default = [],

    kubernetes_pvs
      | Array KubernetesPersistentVolume
      | doc "Kubernetes PersistentVolumes"
      | default = [],

    kubernetes_pvcs
      | Array KubernetesPersistentVolumeClaim
      | doc "Kubernetes PersistentVolumeClaims"
      | default = [],

    backup_config
      | {
        enabled
          | Bool
          | doc "Enable automated backups"
          | default = false,

        schedule
          | String
          | doc "Backup schedule in cron format"
          | optional,

        retention_days
          | Number
          | doc "Number of days to retain backups"
          | default = 7,

        destination
          | String
          | doc "Backup destination path or URL"
          | optional,
      }
      | doc "Backup configuration"
      | optional,
  },
}
