namespace Fast.Web.Controllers;

[Authorize]
[ApiController]
[Route("api/[controller]")]
public class ProcessorController : ODataController

{
    private readonly MyDbContext db;
    private readonly AuthorizationHelper authHelper;

    public ProcessorController(MyDbContext context)
    {
        db = context;
        authHelper = new AuthorizationHelper(Main.IsAuthenticationEnabled);
    }

    [Permission("Processor or Inlet Pipe", PermissionType.View)]
    [Route("/odata/GetProcessorItems")]
    public IActionResult GetItems(ODataQueryOptions<ProcessorListItem> queryOptions, bool isExport)
    {
        queryOptions = Util.GetQueryOptionsWithConvertedDates(queryOptions);
        var itemsQueryable = GetItemsInternal();
        var items = (queryOptions.ApplyTo(itemsQueryable) as IEnumerable<ProcessorListItem>)?.ToList();

        if (isExport)
            return File(Util.Excel.GetExportFileStream(items), "application/octet-stream");
        else
            return Ok(items);
    }

    [Permission("Processor or Inlet Pipe", PermissionType.View)]
    [Route("[action]")]
    public IQueryable<ProcessorListItem> GetItemsInternal()
    {
        IQueryable<ProcessorListItem>? itemsQueryable = null;

        itemsQueryable = (
            from q in db.PlantStatementDescriptors
            select new ProcessorListItem
            {
                ProcessorId = q.Id,
                Name = q.Name ?? ""
            }

        ).AsNoTracking();

        return itemsQueryable;
    }

    [Permission("Processor or Inlet Pipe", PermissionType.View)]
    [Route("[action]")]
    public async Task<IActionResult> GetRequiredData()
    {
        var hasModifyPermission = await authHelper.IsAuthorizedAsync(User, "Processor or Inlet Pipe", PermissionType.Modify);
        var result = new { hasModifyPermission };
        return Ok(result);
    }

    [Permission("Processor or Inlet Pipe", PermissionType.View)]
    [Route("[action]")]
    public async Task<IActionResult> GetDetail(int ProcessorId)
    {
        var detail = await (
            from q in db.PlantStatementDescriptors
            where q.Id == ProcessorId
            select new ProcessorDetail
            {
                ProcessorId = q.Id,
                Name = q.Name ?? ""

            }
        ).AsNoTracking().FirstOrDefaultAsync();

        return Ok(detail);
    }

    public enum SaveType
    {
        New = 1,
        Normal = 2
    }

    [Permission("Processor or Inlet Pipe", PermissionType.Modify)]
    [Route("[action]")]
    public async Task<IActionResult> SaveDetail(ProcessorDetail detail, SaveType saveType)
    {
        int resultId = 0;
        await db.Database.CreateExecutionStrategy().Execute(async () =>
        {
            using var dbContextTransaction = await db.Database.BeginTransactionAsync();
            PlantStatementDescriptor? dbItem = null;
            if (saveType != SaveType.New)
            {
                dbItem = await (
                    from q in db.PlantStatementDescriptors
                    where q.Id == detail.ProcessorId
                    select q
                ).FirstOrDefaultAsync();
            }

            if (dbItem == null) //if the item does not exist then add it
            {
                dbItem = new PlantStatementDescriptor();
                db.PlantStatementDescriptors.Add(dbItem);
            }
            else
            {
                //remove existing items so that they get completely re-inserted
            }

            var d = detail;
            dbItem.Name = d.Name;
            // dbItem.Id = d.ProcessorId;

            await db.SaveChangesAsync();
            resultId = dbItem.Id;

            await dbContextTransaction.CommitAsync();
        });

        return Ok(resultId);
    }

    [Permission("Processor or Inlet Pipe", PermissionType.Modify)]
    [Route("[action]/{id}")]
    public async Task<IActionResult> DeleteDetail(int id)
    {
        PlantStatementDescriptor dbitem = await db.PlantStatementDescriptors.Where(x => x.Id == id).FirstAsync();
        db.PlantStatementDescriptors.Remove(dbitem);
        await db.SaveChangesAsync();

        return Ok();
    }
}
