namespace Shared.Problems;

public sealed record KbxProblemAction(string Id, string Label);

public sealed record KbxValidationError(
    string? Field,
    string? RowKey,
    string Code,
    string Message);

public sealed record KbxValidationProblem(
    string Type,
    string Title,
    IReadOnlyList<KbxValidationError> Errors,
    string? Detail = null,
    string? CorrelationId = null)
{
    public static KbxValidationProblem Create(params KbxValidationError[] errors) =>
        new("validation", "입력값을 확인하세요.", errors);
}

public sealed record KbxBusinessProblem(
    string Type,
    string Code,
    string Title,
    string? Detail = null,
    IReadOnlyList<KbxProblemAction>? Actions = null,
    string? CorrelationId = null)
{
    public static KbxBusinessProblem Create(
        string code,
        string title,
        string? detail = null,
        IReadOnlyList<KbxProblemAction>? actions = null) =>
        new("business-rule", code, title, detail, actions);
}

public sealed record KbxConflictProblem(
    string Type,
    string Code,
    string Title,
    long? CurrentVersion = null,
    string? Detail = null,
    string? CorrelationId = null)
{
    public static KbxConflictProblem Version(long? currentVersion = null) =>
        new("conflict", "VERSION_CONFLICT", "다른 사용자가 데이터를 변경했습니다.", currentVersion);
}

public sealed record KbxPermissionProblem(
    string Type,
    string Code,
    string Title,
    string? Detail = null,
    string? CorrelationId = null)
{
    public static KbxPermissionProblem Denied(string? detail = null) =>
        new("permission", "PERMISSION_DENIED", "이 작업을 수행할 권한이 없습니다.", detail);
}

public sealed record KbxNotFoundProblem(
    string Type,
    string Code,
    string Title,
    string? Detail = null,
    string? CorrelationId = null)
{
    public static KbxNotFoundProblem Create(string code, string title, string? detail = null) =>
        new("not-found", code, title, detail);
}

public sealed record KbxIntegrationProblem(
    string Type,
    string Code,
    string Title,
    bool Retryable,
    string? Detail = null,
    string? CorrelationId = null)
{
    public static KbxIntegrationProblem Create(string code, string title, bool retryable, string? detail = null) =>
        new("integration", code, title, retryable, detail);
}

public sealed record KbxSystemProblem(
    string Type,
    string Code,
    string Title,
    string CorrelationId,
    string? Detail = null,
    bool Retryable = false)
{
    public static KbxSystemProblem Unexpected(string correlationId, string? detail = null) =>
        new("system", "UNEXPECTED_ERROR", "요청을 처리하지 못했습니다.", correlationId, detail);
}
