using SpaceGame.Api.Definitions;
using SpaceGame.Api.Shared.Runtime;

namespace SpaceGame.Api.Stations.Runtime;

public sealed class StationRuntime
{
    public required string Id { get; init; }
    public required string SystemId { get; init; }
    public required string Label { get; set; }
    public string Category { get; set; } = "station";
    public string Objective { get; set; } = "general";
    public string Color { get; set; } = "#8df0d2";
    public required Vector3 Position { get; set; }
    public float Radius { get; set; } = 24f;
    public required string FactionId { get; init; }
    public string? CelestialId { get; set; }
    public string? CommanderId { get; set; }
    public string? PolicySetId { get; set; }
    public List<StationModuleRuntime> Modules { get; } = [];
    public float Health { get; set; } = 600f;
    public float MaxHealth { get; set; } = 600f;
    public IEnumerable<string> InstalledModules => Modules.Select((module) => module.ModuleId);
    public Dictionary<string, float> Inventory { get; } = new(StringComparer.Ordinal);
    public Dictionary<string, float> ProductionLaneTimers { get; } = new(StringComparer.Ordinal);
    public Dictionary<int, string> DockingPadAssignments { get; } = new();
    public HashSet<string> MarketOrderIds { get; } = new(StringComparer.Ordinal);
    public float Population { get; set; }
    public float PopulationCapacity { get; set; }
    public float WorkforceRequired { get; set; }
    public float WorkforceEffectiveRatio { get; set; } = 0.1f;
    public float PopulationGrowthProgress { get; set; }
    public float ShipProductionProgressSeconds { get; set; }
    public HashSet<string> DockedShipIds { get; } = [];
    public ModuleConstructionRuntime? ActiveConstruction { get; set; }
    public string LastDeltaSignature { get; set; } = string.Empty;
}

public class StationModuleRuntime
{
    public required string Id { get; init; }
    public required string ModuleId { get; init; }
    public required ModuleType ModuleType { get; init; }
    public float Health { get; set; }
    public float MaxHealth { get; set; }

    public static StationModuleRuntime Create(string id, ModuleDefinition definition) =>
      definition switch
      {
          StorageModuleDefinition storage => new StorageStationModuleRuntime
          {
              Id = id,
              ModuleId = storage.Id,
              ModuleType = storage.ModuleType,
              StorageKind = storage.StorageKind,
              Health = storage.Hull,
              MaxHealth = storage.Hull,
          },
          ProductionModuleDefinition production => new ProductionStationModuleRuntime
          {
              Id = id,
              ModuleId = production.Id,
              ModuleType = production.ModuleType,
              ProductItemIds = [.. production.ProductItemIds],
              Health = production.Hull,
              MaxHealth = production.Hull,
          },
          BuildModuleDefinition build => new BuildStationModuleRuntime
          {
              Id = id,
              ModuleId = build.Id,
              ModuleType = build.ModuleType,
              Health = build.Hull,
              MaxHealth = build.Hull,
          },
          _ => new StationModuleRuntime
          {
              Id = id,
              ModuleId = definition.Id,
              ModuleType = definition.ModuleType,
              Health = definition.Hull,
              MaxHealth = definition.Hull,
          },
      };
}

public sealed class ProductionStationModuleRuntime : StationModuleRuntime
{
    public IReadOnlyList<string> ProductItemIds { get; init; } = [];
}

public sealed class BuildStationModuleRuntime : StationModuleRuntime
{
}

public sealed class StorageStationModuleRuntime : StationModuleRuntime
{
    public StorageKind StorageKind { get; init; }
    public float CurrentLevel { get; set; }
}

public sealed class ModuleConstructionRuntime
{
    public required string ModuleId { get; init; }
    public float ProgressSeconds { get; set; }
    public float RequiredSeconds { get; init; }
    public string AssignedConstructorShipId { get; set; } = string.Empty;
}
