using System.Threading;
using System.Threading.Tasks;
namespace RecruitmentBLL.Integration
{
/// Outcome of a DXP Auth call. Unlike EcpIntegrationService's fire-and-forget
/// notification calls, Register/Login are user-facing — a failure here must propagate a real
/// error back to the caller (401/400), never silently no-op.
public class DxpAuthOutcome
{
public bool Success { get; set; }
public string? Error { get; set; }
public int DxpUserId { get; set; } = -1;
}
/// Login additionally carries FullName back — DXP's own MDXPUSER row is the only
/// place this candidate's display name is known until Recruitment provisions/links its own
/// MCANDIDATE row for them (see CandidatePortalBLL.EnsureCandidateAsync).
public class DxpLoginOutcome : DxpAuthOutcome
{
public string FullName { get; set; } = string.Empty;
}
///
/// Cross-host HTTP integration with DXP's real Auth surface (hosted by PlatformHost, a
/// different process than Recruitment's HRFinanceHost) — thin wrappers over
/// POST /DXP/Auth/Register and POST /DXP/Auth/Login, following the exact
/// IHttpClientFactory named-client pattern established by
/// RecruitmentBLL.Integration.EcpIntegrationService / DXPBLL.VendorPo.MmIntegrationService.
///
/// Verified real request/response shapes (read from DXPSL/Endpoints/Auth/Register.cs,
/// DXPSL/Endpoints/Auth/Login.cs, DXPSL/Parameters/Auth/*.cs, DXPBLL/Auth/AuthBLL.cs —
/// 2026-09-04):
/// POST /DXP/Auth/Register — plain JSON body { FullName, Email, Mobile?, Password },
/// NOT wrapped, no Login header (Register/Login are plain FastEndpoints Endpoint<,>,
/// not BaseEndpoint — DXP resolves its own "system" LoginDTO internally via
/// IDXPSystemContext, so callers never supply one). Success: ResponseStandardDTO.Body is
/// "{SuccessResponse.SaveSuccessMessage} {DxpUserId}" (200). Failure (duplicate email /
/// bad password length): ResponseStandardDTO.ErrorBody carries the message (400).
/// POST /DXP/Auth/Login — plain JSON body { Email, Password, DeviceInfo? }. Success (200):
/// ResponseStandardDTO.Body is a serialized DXPLoginResultDTO { DxpUserId, FullName,
/// Contexts[], Tokens (DXPTokenPair, null unless the account has exactly one
/// Party/Role/tenant-link context), IntermediateToken (string, populated only when
/// Contexts.Count != 1) }. A candidate account has NO DXP Party/Role at all (DXP's
/// PartyType model doesn't fit an individual candidate — see the plan's Phase 3 note),
/// so Contexts is always empty and Tokens is always null; only IntermediateToken would be
/// populated, carrying nothing but a bare `dxp_user_id` claim (RoleCode/TenantId/etc are
/// zero/empty — see DXPBLL.Auth.AuthBLL.LoginAsync's zero/one-context branch). This class
/// does NOT relay that token — see CandidatePortalBLL for why Recruitment mints its own
/// token instead. Failure (bad credentials / locked account): ResponseStandardDTO.ErrorBody
/// carries a deliberately generic message (401).
///
/// Every method here degrades to a clear failure result (Success=false + Error) on a non-2xx
/// response or thrown exception — it never throws back into CandidatePortalBLL uncaught, but
/// (unlike Ecp/Mm's fire-and-forget calls) that failure is always surfaced to the end user as
/// a real 400/401, never swallowed into a silent success.
///
public interface IDxpAuthIntegrationService
{
Task RegisterCandidateUserAsync(
string fullName, string email, string? mobile, string password, CancellationToken ct);
Task LoginCandidateAsync(
string email, string password, CancellationToken ct);
}
}