using System;
using System.Threading.Tasks;
using FrameworkBLL.GOP;
using GB5Shared.DTO.Framework.Login;
using GB5Shared.DTO.Framework.ResponseStandard;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using static GB5Shared.GB5Constant.Constant;
namespace FrameworkSL.Controllers.GOP
{
///
/// GOP Document Intake Controller — the generic "AI identifies the document, GOP picks the
/// flow" pipeline (see IGopDocumentIntakeBLL's doc comment). Recruitment's resume-to-Candidate
/// conversion is its first consumer, not a special case baked into it.
///
/// POST SubmitDocument — accepts any file, classifies it via EAIAdmin's IDENTIFY_DOCUMENT
/// capability, resolves the matching MGOPDOCUMENTTYPE, converts it via
/// PARSE_VALIDATE_DOCUMENT, and submits the result as a normal GOP
/// execution (IGopQueueBLL.SubmitExecution, unchanged). Returns
/// immediately with an ExecutionId to poll/subscribe on, same as
/// GopQueueService/SubmitExecution.
///
[ApiController]
[Route("[controller]")]
public class GopDocumentIntakeService : ControllerBase
{
private readonly IGopDocumentIntakeBLL _IGopDocumentIntakeBLL;
public GopDocumentIntakeService(IGopDocumentIntakeBLL gopDocumentIntakeBLL)
{
_IGopDocumentIntakeBLL = gopDocumentIntakeBLL;
}
[HttpPost("SubmitDocument")]
public async Task> SubmitDocument(
[FromForm] GopDocumentIntakeRequestDTO request,
[FromHeader(Name = "Login")] string LoginDTOJson)
{
var LoginDTO = JsonConvert.DeserializeObject(LoginDTOJson);
try
{
if (request.File is null || request.File.Length == 0)
throw new ArgumentException("No file provided or file is empty.");
await using var stream = request.File.OpenReadStream();
var result = await _IGopDocumentIntakeBLL.SubmitDocumentAsync(
stream, request.File.FileName, request.File.ContentType, LoginDTO!)
.ConfigureAwait(false);
return await GB5Shared.ResponseStandard.Response.CreateSuccessResponse(
result, CacheKeyLevel.NOT_REQUIRED, LoginDTO!);
}
catch (Exception ex)
{
return await GB5Shared.ResponseStandard.Response.CreateExceptionError(
ex, CacheKeyLevel.NOT_REQUIRED, LoginDTO!, ex.Message, 500);
}
}
/// Human-in-the-loop variant — see IGopDocumentIntakeBLL.SubmitDocumentForPrefillAsync.
/// The caller supplies SourceCode directly (e.g. "RESUME_PREFILL") instead of relying on
/// AI classification; the resolved flow has no save step, so nothing is persisted until
/// the caller's own form is reviewed and saved by the user.
[HttpPost("PrefillFromDocument")]
public async Task> PrefillFromDocument(
[FromForm] GopDocumentIntakePrefillRequestDTO request,
[FromHeader(Name = "Login")] string LoginDTOJson)
{
var LoginDTO = JsonConvert.DeserializeObject(LoginDTOJson);
try
{
if (request.File is null || request.File.Length == 0)
throw new ArgumentException("No file provided or file is empty.");
await using var stream = request.File.OpenReadStream();
var result = await _IGopDocumentIntakeBLL.SubmitDocumentForPrefillAsync(
stream, request.File.FileName, request.File.ContentType, request.SourceCode, LoginDTO!)
.ConfigureAwait(false);
return await GB5Shared.ResponseStandard.Response.CreateSuccessResponse(
result, CacheKeyLevel.NOT_REQUIRED, LoginDTO!);
}
catch (Exception ex)
{
return await GB5Shared.ResponseStandard.Response.CreateExceptionError(
ex, CacheKeyLevel.NOT_REQUIRED, LoginDTO!, ex.Message, 500);
}
}
}
public class GopDocumentIntakeRequestDTO
{
public IFormFile? File { get; set; }
}
public class GopDocumentIntakePrefillRequestDTO
{
public IFormFile? File { get; set; }
public string SourceCode { get; set; } = string.Empty;
}
}