namespace SpaceGame.Api.Industry.Planning;

public sealed class ProductionGraph
{
    public required IReadOnlyDictionary<string, ProductionCommodityNode> Commodities { get; init; }
    public required IReadOnlyDictionary<string, ProductionProcessNode> Processes { get; init; }
    public required IReadOnlyDictionary<string, IReadOnlyList<ProductionProcessNode>> ProcessesByOutputId { get; init; }
    public required IReadOnlyDictionary<string, IReadOnlyList<ProductionProcessNode>> ProcessesByInputId { get; init; }
    public required IReadOnlyDictionary<string, IReadOnlyList<string>> OutputsByModuleId { get; init; }

    public IReadOnlyList<ProductionProcessNode> GetProcessesForOutput(string itemId) =>
        ProcessesByOutputId.TryGetValue(itemId, out var processes) ? processes : [];

    public IReadOnlyList<ProductionProcessNode> GetProcessesForInput(string itemId) =>
        ProcessesByInputId.TryGetValue(itemId, out var processes) ? processes : [];

    public string? GetPrimaryProducerModule(string itemId) =>
        GetProcessesForOutput(itemId)
          .SelectMany(process => process.RequiredModuleIds)
          .FirstOrDefault();

    public string? GetPrimaryOutputForModule(string moduleId) =>
        OutputsByModuleId.TryGetValue(moduleId, out var outputs)
          ? outputs.FirstOrDefault()
          : null;

    public IReadOnlyList<string> GetImmediateInputs(string itemId) =>
        GetProcessesForOutput(itemId)
          .SelectMany(process => process.Inputs.Keys)
          .Distinct(StringComparer.Ordinal)
          .ToList();
}

public sealed class ProductionCommodityNode
{
    public required string ItemId { get; init; }
    public required string Name { get; init; }
    public required string Group { get; init; }
    public required string CargoKind { get; init; }
    public List<string> ProducerProcessIds { get; } = [];
    public List<string> ConsumerProcessIds { get; } = [];
}

public sealed class ProductionProcessNode
{
    public required string Id { get; init; }
    public required string Label { get; init; }
    public required string FacilityCategory { get; init; }
    public required IReadOnlyList<string> RequiredModuleIds { get; init; }
    public required IReadOnlyDictionary<string, float> Inputs { get; init; }
    public required IReadOnlyDictionary<string, float> Outputs { get; init; }
    public required bool ProducesShip { get; init; }
}
