namespace Fast.Web.Controllers;

[Authorize]
[ApiController]
[Route("api/[controller]")]
public class StorageFacilityController : ODataController
{
    private readonly MyDbContext db;
    private readonly AuthorizationHelper authHelper;

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

    [Permission("Storage Facility", PermissionType.View)]
    [Route("/odata/GetStorageFacilityItems")]
    public IActionResult GetItems(ODataQueryOptions<StorageFacilityListItem> queryOptions, bool isExport)
    {
        queryOptions = Util.GetQueryOptionsWithConvertedDates(queryOptions);
        var itemsQueryable = GetItemsInternal();
        var items = (queryOptions.ApplyTo(itemsQueryable) as IEnumerable<StorageFacilityListItem>)?.ToList();

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

    [Permission("Storage Facility", PermissionType.View)]
    [Route("[action]")]
    public IQueryable<StorageFacilityListItem> GetItemsInternal()
    {
        IQueryable<StorageFacilityListItem>? itemsQueryable = null;

        itemsQueryable = (
            from q in db.StorageFacilities
            select new StorageFacilityListItem
            {
                StorageFacilityId = q.Id,
                FacilityName = q.Name
            }
        ).AsNoTracking();

        return itemsQueryable;
    }

    [Permission("Storage Facility", PermissionType.View)]
    [Route("[action]")]
    public async Task<IActionResult> GetRequiredData()
    {
        var hasModifyPermission = await authHelper.IsAuthorizedAsync(User, "Storage Facility", PermissionType.Modify);

        var result = new { hasModifyPermission };
        return Ok(result);
    }

    [Permission("Storage Facility", PermissionType.View)]
    [Route("[action]")]
    public async Task<IActionResult> GetDetail(int id)
    {
        var detail = await (
            from q in db.StorageFacilities
            where q.Id == id
            select new StorageFacilityDetail
            {
                StorageFacilityId = q.Id,
                FacilityName = q.Name
            }
        ).AsNoTracking().FirstAsync();

        return Ok(detail);
    }

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

    [Permission("Storage Facility", PermissionType.Modify)]
    [Route("[action]")]
    public async Task<IActionResult> SaveDetail(StorageFacilityDetail detail, SaveType saveType)
    {
        int resultId = 0;
        await db.Database.CreateExecutionStrategy().Execute(async () =>
        {
            using var dbContextTransaction = await db.Database.BeginTransactionAsync();
            StorageFacility? dbItem = null;
            if (saveType != SaveType.New)
            {
                dbItem = await (
                    from q in db.StorageFacilities
                    where q.Id == detail.StorageFacilityId
                    select q
                ).FirstOrDefaultAsync();
            }

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

            var d = detail;
            dbItem.Name = d.FacilityName;

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

            await dbContextTransaction.CommitAsync();
        });

        return Ok(resultId);
    }

    [Permission("Storage Facility", PermissionType.Modify)]
    [Route("[action]/{id}")]
    public async Task<IActionResult> DeleteDetail(int id)
    {
        StorageFacility dbItem = await db.StorageFacilities.Where(x => x.Id == id).FirstAsync();
        db.StorageFacilities.Remove(dbItem);
        await db.SaveChangesAsync();

        return Ok();
    }
}
