package com.livingworld.modules;

import java.util.Collections;
import java.util.ArrayList;
import java.util.List;

/**
 * Immutable metadata describing a simulation module.
 *
 * <p>This class validates that essential fields are present and normalises
 * null dependency lists into empty lists for safe downstream usage.</p>
 */
public final class ModuleMetadata {

    private final String moduleId;
    private final String displayName;
    private final String version;
    private final String description;
    private final String requiredCoreVersion;
    private final List<String> dependencies;
    private final List<String> optionalDependencies;
    private final boolean defaultEnabled;
    private final boolean serverOnly;
    private final boolean experimental;

    /**
     * Creates new ModuleMetadata with the given values.
     *
     * @param moduleId             unique module identifier (must not be null or blank)
     * @param displayName          human-readable name (must not be null or blank)
     * @param version              semantic version string (may be null, defaults to "0.0.0")
     * @param description          short description of the module (may be null, defaults to empty)
     * @param requiredCoreVersion  minimum core schema version required (may be null, defaults to "1")
     * @param dependencies         list of required module IDs (null becomes empty list)
     * @param optionalDependencies list of optional module IDs (null becomes empty list)
     * @param defaultEnabled       whether the module is enabled by default
     * @param serverOnly           whether this module only runs on dedicated servers
     * @param experimental         whether this module is experimental and may change behaviour
     */
    public ModuleMetadata(String moduleId, String displayName, String version,
                          String description, String requiredCoreVersion,
                          List<String> dependencies, List<String> optionalDependencies,
                          boolean defaultEnabled, boolean serverOnly, boolean experimental) {

        if (moduleId == null || moduleId.isBlank()) {
            throw new IllegalArgumentException("moduleId must not be null or blank");
        }
        if (displayName == null || displayName.isBlank()) {
            throw new IllegalArgumentException("displayName must not be null or blank");
        }

        this.moduleId = moduleId;
        this.displayName = displayName;
        this.version = version != null ? version : "0.0.0";
        this.description = description != null ? description : "";
        this.requiredCoreVersion = requiredCoreVersion != null ? requiredCoreVersion : "1";
        this.dependencies = dependencies != null
                ? Collections.unmodifiableList(new ArrayList<>(dependencies))
                : Collections.emptyList();
        this.optionalDependencies = optionalDependencies != null
                ? Collections.unmodifiableList(new ArrayList<>(optionalDependencies))
                : Collections.emptyList();
        this.defaultEnabled = defaultEnabled;
        this.serverOnly = serverOnly;
        this.experimental = experimental;
    }

    /**
     * Returns the unique module identifier.
     */
    public String moduleId() {
        return moduleId;
    }

    /**
     * Returns the human-readable display name.
     */
    public String displayName() {
        return displayName;
    }

    /**
     * Returns the semantic version string.
     */
    public String version() {
        return version;
    }

    /**
     * Returns the description of this module.
     */
    public String description() {
        return description;
    }

    /**
     * Returns the minimum core schema version required by this module.
     */
    public String requiredCoreVersion() {
        return requiredCoreVersion;
    }

    /**
     * Returns an unmodifiable list of required dependency module IDs.
     */
    public List<String> dependencies() {
        return dependencies;
    }

    /**
     * Returns an unmodifiable list of optional dependency module IDs.
     */
    public List<String> optionalDependencies() {
        return optionalDependencies;
    }

    /**
     * Returns whether this module is enabled by default.
     */
    public boolean defaultEnabled() {
        return defaultEnabled;
    }

    /**
     * Returns whether this module only runs on dedicated servers.
     */
    public boolean serverOnly() {
        return serverOnly;
    }

    /**
     * Returns whether this module is experimental and may change behaviour.
     */
    public boolean experimental() {
        return experimental;
    }
}
