using System.Text.Json.Serialization;

namespace Sdt.Config;

public sealed class DevToolConfig
{
    public string Name { get; init; } = "SDT Project";
    public string Version { get; init; } = "0.1.0";
    public List<BuildTarget> Targets { get; init; } = [];
    public List<WorkflowDefinition> Workflows { get; init; } = [];
    public List<EnvVarDef> Env { get; init; } = [];
    public ToolchainConfig? Toolchains { get; init; }
    public ToolingConfig? Tooling { get; init; }
    public ProjectMetadata? Project { get; init; }
    public DebugConfig? Debug { get; init; }
}

public sealed class BuildTarget
{
    public string Id { get; init; } = "";
    public string Label { get; init; } = "";
    public string Description { get; init; } = "";
    public string Group { get; init; } = "General";

    /// <summary>Executable name. Null = virtual aggregator (runs DependsOn only).</summary>
    public string? Command { get; init; }

    public List<string> Args { get; init; } = [];

    /// <summary>Working directory relative to project root.</summary>
    public string WorkingDir { get; init; } = ".";

    public List<string> DependsOn { get; init; } = [];
}

public sealed class EnvVarDef
{
    public string Key { get; init; } = "";
    public string Description { get; init; } = "";

    [System.Text.Json.Serialization.JsonPropertyName("default")]
    public string DefaultValue { get; init; } = "";

    /// <summary>If non-empty, shown as a dropdown. Otherwise free-text input.</summary>
    public List<string> Options { get; init; } = [];
}

public sealed class WorkflowDefinition
{
    public string Id { get; init; } = "";
    public string Label { get; init; } = "";
    public string Description { get; init; } = "";
    public string Group { get; init; } = "General";
    public List<string> DependsOn { get; init; } = [];
    public List<WorkflowStep> Steps { get; init; } = [];
}

public sealed class WorkflowStep
{
    public string Id { get; init; } = "";
    public string Label { get; init; } = "";
    public string? Command { get; init; }
    public List<string> Args { get; init; } = [];
    public string WorkingDir { get; init; } = ".";
    public string? Action { get; init; }
    public List<string> ActionArgs { get; init; } = [];
    public List<ToolRequirement> Requires { get; init; } = [];
}

public sealed class ToolRequirement
{
    public string Tool { get; init; } = "";

    [JsonConverter(typeof(JsonStringEnumConverter))]
    public InstallPolicy InstallPolicy { get; init; } = InstallPolicy.Prompt;
}

[JsonConverter(typeof(JsonStringEnumConverter))]
public enum InstallPolicy
{
    Prompt,
    Auto,
    Never,
}

public sealed class ToolingConfig
{
    public List<ToolInstallDefinition> Tools { get; init; } = [];
}

public sealed class ToolInstallDefinition
{
    public string Tool { get; init; } = "";
    public List<string> PreferredInstallCommands { get; init; } = [];
    public List<string> Executables { get; init; } = [];
}

public sealed class ProjectMetadata
{
    public string Type { get; init; } = "";
    public List<string> RootHints { get; init; } = [];
    public List<string> Artifacts { get; init; } = [];
}

public sealed class DebugConfig
{
    public List<DebugProfileDefinition> Profiles { get; init; } = [];
    public DebugDiagnosticsOptions Diagnostics { get; init; } = new();
}

public sealed class DebugProfileDefinition
{
    public string Id { get; init; } = "";
    public string Label { get; init; } = "";
    public string Type { get; init; } = "generic";
    public string Command { get; init; } = "";
    public List<string> Args { get; init; } = [];
    public string WorkingDir { get; init; } = ".";
    public Dictionary<string, string> Env { get; init; } = new(StringComparer.OrdinalIgnoreCase);
    public List<ToolRequirement> Requires { get; init; } = [];
    public DebugAttachConfig? Attach { get; init; }
}

public sealed class DebugAttachConfig
{
    public string Kind { get; init; } = "";
    public int? Port { get; init; }
    public string? ProcessName { get; init; }
    public string? Note { get; init; }
}

public sealed class DebugDiagnosticsOptions
{
    public bool Enabled { get; init; } = true;
    public string OutputDir { get; init; } = ".sdt/debug";
    public bool IncludeAllEnv { get; init; } = false;
    public List<string> CaptureEnvKeys { get; init; } = [];
    public bool BundleOnFailure { get; init; } = true;
}

// ── Toolchain config ──────────────────────────────────────────────────────────

public sealed class ToolchainConfig
{
    public PythonToolchain? Python { get; init; }
    public NodeToolchain? Node { get; init; }
}

public sealed class PythonToolchain
{
    /// <summary>Python executable (e.g. "python3.14", "python").</summary>
    public string Executable { get; init; } = "python";

    /// <summary>Windows-specific override (e.g. "py" when using the launcher).</summary>
    public string? WindowsExecutable { get; init; }

    /// <summary>Optional version flag to pass (e.g. "-3.14" for py launcher).</summary>
    public string? LauncherVersion { get; init; }

    /// <summary>Venv directory relative to project root.</summary>
    public string VenvDir { get; init; } = ".venv";

    public List<PythonProfile> Profiles { get; init; } = [];

    /// <summary>Optional path to a pip wrapper script (relative to project root).</summary>
    public string? PipScript { get; init; }
}

public sealed class PythonProfile
{
    public string Id { get; init; } = "";
    public string Label { get; init; } = "";
    public string RequirementsFile { get; init; } = "";
    public string? ExtraIndexUrl { get; init; }
    public List<string> PostInstallCommands { get; init; } = [];
}

public sealed class NodeToolchain
{
    /// <summary>Package manager: "npm", "pnpm", or "yarn".</summary>
    public string PackageManager { get; init; } = "npm";

    /// <summary>Working directory for the frontend (relative to project root).</summary>
    public string WorkingDir { get; init; } = ".";
}
