//===----------------------------------------------------------------------===//
// Copyright © 2025 Apple Inc. and the container project authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

import Foundation

/// A named volume that can be mounted in containers.
public struct Volume: Sendable, Codable, Equatable, Identifiable {
    // id of the volume.
    public var id: String { name }
    // Name of the volume.
    public var name: String
    // Driver used to create the volume.
    public var driver: String
    // Filesystem format of the volume.
    public var format: String
    // The mount point of the volume on the host.
    public var source: String
    // Timestamp when the volume was created.
    public var createdAt: Date
    // User-defined key/value metadata.
    public var labels: [String: String]
    // Driver-specific options.
    public var options: [String: String]
    // Size of the volume in bytes (optional).
    public var sizeInBytes: UInt64?

    public init(
        name: String,
        driver: String = "local",
        format: String = "ext4",
        source: String,
        createdAt: Date = Date(),
        labels: [String: String] = [:],
        options: [String: String] = [:],
        sizeInBytes: UInt64? = nil,
    ) {
        self.name = name
        self.driver = driver
        self.format = format
        self.source = source
        self.createdAt = createdAt
        self.labels = labels
        self.options = options
        self.sizeInBytes = sizeInBytes
    }
}

/// Error types for volume operations.
public enum VolumeError: Error, LocalizedError {
    case volumeNotFound(String)
    case volumeAlreadyExists(String)
    case volumeInUse(String)
    case invalidVolumeName(String)
    case driverNotSupported(String)
    case storageError(String)

    public var errorDescription: String? {
        switch self {
        case .volumeNotFound(let name):
            return "Volume '\(name)' not found"
        case .volumeAlreadyExists(let name):
            return "Volume '\(name)' already exists"
        case .volumeInUse(let name):
            return "Volume '\(name)' is currently in use and cannot be accessed by another container, or deleted."
        case .invalidVolumeName(let name):
            return "Invalid volume name '\(name)'"
        case .driverNotSupported(let driver):
            return "Volume driver '\(driver)' is not supported"
        case .storageError(let message):
            return "Storage error: \(message)"
        }
    }
}

/// Volume storage management utilities.
public struct VolumeStorage {
    public static let volumeNamePattern = "^[A-Za-z0-9][A-Za-z0-9_.-]*$"
    public static let defaultVolumeSizeBytes: UInt64 = 512 * 1024 * 1024 * 1024  // 512GB

    public static func isValidVolumeName(_ name: String) -> Bool {
        guard name.count <= 255 else { return false }

        do {
            let regex = try Regex(volumeNamePattern)
            return name.contains(regex)
        } catch {
            return false
        }
    }
}
