using ERPCore.Domain.Enums;

namespace ERPCore.Domain.Entities;

/// <summary>
/// One stage of a run — a copy of a <see cref="TemplateStage"/> taken at run creation
/// (FR-MFG-06), carrying its own live status and actual timings. Model: docs/30 Part C.
/// <para><b>Whether this stage is terminal is derived</b>, never stored: a stage is
/// terminal when it has no outbound <see cref="RunEdge"/>. Storing it would let it
/// drift from the edge set.</para>
/// </summary>
public class RunStage
{
    public int RunStageId { get; set; }

    public int RunId { get; set; }
    public ProductionRun? Run { get; set; }

    /// <summary>
    /// Provenance link back to the template stage. <b>Nullable</b>: a template PUT may
    /// delete a stage while completed/cancelled runs still reference it (the edit-lock
    /// only blocks edits during InProgress runs), so the FK is <c>SET NULL</c> rather
    /// than blocking the edit forever. Everything needed to display a historical run is
    /// copied below, which is exactly what FR-MFG-06 anticipates.
    /// </summary>
    public int? TemplateStageId { get; set; }
    public TemplateStage? TemplateStage { get; set; }

    // --- copied from the template at run creation (FR-MFG-06) ---
    public string Name { get; set; } = string.Empty;
    public string? RoleLabel { get; set; }
    public int EstimatedMinutes { get; set; }
    public decimal PosX { get; set; }
    public decimal PosY { get; set; }

    public ProductionStageStatus Status { get; set; } = ProductionStageStatus.Waiting;

    /// <summary>Stamped at start; preserved across a reject-intake rework so the original start stands (FR-MFG-19).</summary>
    public DateTime? ActualStartAt { get; set; }
    public DateTime? ActualEndAt { get; set; }

    /// <summary>Copied from the template stage; definitions survive a rework.</summary>
    public string FieldDefs { get; set; } = "[]";

    /// <summary>Captured at complete as a jsonb object; cleared by a terminal reject so required fields are re-answered.</summary>
    public string? FieldValues { get; set; }

    /// <summary>
    /// Concurrency token. Stage actions re-read the stage inside their transaction and
    /// let this xmin check serialize concurrent requests — it is what stops two
    /// simultaneous terminal approves from both reading <c>Done</c> and posting two
    /// receipts. See the idempotency note in <c>ProductionRunService</c>.
    /// </summary>
    public uint RowVersion { get; set; }

    public ICollection<RunStageInput> Inputs { get; set; } = new List<RunStageInput>();
    public ICollection<RunStageOutput> Outputs { get; set; } = new List<RunStageOutput>();
    public ICollection<RunStageEvent> Events { get; set; } = new List<RunStageEvent>();
}
