namespace Fast.Web.Controllers
{
    [Authorize]
    [ApiController]
    [Route("api/[controller]")]
    public class LeaseController : ODataController
    {
        private readonly MyDbContext db;
        private readonly AuthorizationHelper authHelper;

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

        [Permission("Lease", PermissionType.View)]
        [Route("/odata/GetLeaseItems")]
        public IActionResult GetItems(ODataQueryOptions<LeaseListItem> queryOptions, bool isExport, DateTime? asOfDate)
        {
            queryOptions = Util.GetQueryOptionsWithConvertedDates(queryOptions);
            var itemsQueryable = GetItemsInternal(asOfDate);
            var items = (queryOptions.ApplyTo(itemsQueryable) as IEnumerable<LeaseListItem>)?.ToList();
            if (isExport)
                return File(Util.Excel.GetExportFileStream(items), "application/octet-stream");
            else
                return Ok(items);
        }

        [Permission("Lease", PermissionType.View)]
        [Route("[action]")]
        public IQueryable<LeaseListItem> GetItemsInternal(DateTime? asOfDate)
        {
            var asOfDateOnly = DateOnly.FromDateTime(asOfDate ?? DateTime.Today);
            var itemsQueryable = (
                from q in db.Leases
                where asOfDate == null || q.InactiveDate == null || q.InactiveDate <= asOfDateOnly
                select new LeaseListItem
                {
                    LeaseId = q.Id,
                    Name = q.Name ?? "",
                    Number = q.Number ?? "",
                    LeaseType = q.LeaseType.Name,
                    InactiveDate = q.InactiveDate
                }
            ).AsNoTracking();

            return itemsQueryable;
        }

        [Permission("Lease", PermissionType.View)]
        [Route("[action]")]
        public async Task<IActionResult> GetRequiredData()
        {
            var hasModifyPermission = await authHelper.IsAuthorizedAsync(User, "Lease", PermissionType.Modify);
            var products = await DataHelper.GetLeasesAsync();
            var leaseTypes = from q in db.LeaseTypes select new IdName(q.Id, q.Name);
            var result = new { hasModifyPermission, products, leaseTypes };
            return Ok(result);
        }

        [Permission("Lease", PermissionType.View)]
        [Route("[action]")]
        public async Task<IActionResult> GetDetail(int id)
        {
            var detail = await (
                from q in db.Leases
                where q.Id == id
                select new LeaseDetail
                {
                    LeaseId = q.Id,
                    Name = q.Name ?? "",
                    Number = q.Number ?? "",
                    LeaseTypeId = q.LeaseTypeId,
                    InactiveDate = q.InactiveDate
                }
            ).AsNoTracking().FirstAsync();

            return Ok(detail);
        }

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

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

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

                var d = detail;
                dbItem.Name = d.Name;
                dbItem.Number = d.Number;
                dbItem.LeaseTypeId = d.LeaseTypeId;
                dbItem.InactiveDate = d.InactiveDate;


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

                await dbContextTransaction.CommitAsync();
            });

            return Ok(resultId);
        }

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

            return Ok();
        }
    }
}
