public async Task <IActionResult> DownloadReport(string reportId)
        {
            Guard.ArgumentNotNull(reportId, nameof(reportId));

            SpecificationReportIdentifier specificationReportIdentifier = DecodeReportId(reportId);

            ReportType reportType    = GetReportType(specificationReportIdentifier.JobType);
            string     containerName = GetContainerName(reportType);
            string     blobName      = GenerateFileName(specificationReportIdentifier);

            ICloudBlob cloudBlob;

            try
            {
                cloudBlob = await _blobClient.GetBlobReferenceFromServerAsync(blobName, containerName);
            }
            catch (StorageException)
            {
                return(new StatusCodeResult((int)HttpStatusCode.NotFound));
            }

            cloudBlob.Metadata.TryGetValue("file_name", out string fileName);

            string blobUrl = _blobClient.GetBlobSasUrl(blobName, DateTimeOffset.Now.AddDays(1), SharedAccessBlobPermissions.Read, containerName);

            SpecificationsDownloadModel downloadModel = new SpecificationsDownloadModel {
                Url = blobUrl, FileName = fileName
            };

            return(new OkObjectResult(downloadModel));
        }
        private static string EncodeSpecificationReportIdentifier(SpecificationReportIdentifier specificationReportIdentifier)
        {
            string idJson = specificationReportIdentifier.AsJson();

            byte[] idBytes = Encoding.UTF8.GetBytes(idJson);
            return(Convert.ToBase64String(idBytes));
        }
        public async Task DownloadReport_GivenNotExistingIdSent_ReturnsNotFound()
        {
            JobType jobType         = JobType.Released;
            string  fundingLineCode = NewRandomString();
            string  fundingPeriodId = NewRandomString();
            string  fundingStreamId = NewRandomString();
            string  specificationId = NewRandomString();

            SpecificationReportIdentifier id = new SpecificationReportIdentifier
            {
                JobType         = jobType,
                FundingLineCode = fundingLineCode,
                FundingPeriodId = fundingPeriodId,
                FundingStreamId = fundingStreamId,
                SpecificationId = specificationId
            };

            string expectedBlobName = $"funding-lines-{specificationId}-{jobType}-{fundingLineCode}-{fundingStreamId}.csv";

            _blobClient
            .When(_ => _.GetBlobReferenceFromServerAsync(expectedBlobName, PublishedProviderVersionsContainerName))
            .Do(_ => throw new StorageException());

            IActionResult result = await _service.DownloadReport(EncodeSpecificationReportIdentifier(id));

            result
            .Should()
            .BeOfType <StatusCodeResult>()
            .Which
            .StatusCode
            .Should()
            .Be((int)HttpStatusCode.NotFound);
        }
        public void GetReportMetadata_GivenSpecificationIdWithBlobs_ReturnsReportMetadata(JobType jobType,
                                                                                          ReportCategory expectedReportCategory,
                                                                                          string targetFundingPeriodId)
        {
            string fundingLineBlobName      = NewRandomString();
            string fundingLineFileExtension = "csv";
            string fundingLineFileName      = "Funding Lines";

            string calcResultsBlobName      = NewRandomString();
            string calcResultsFileExtension = "xlsx";

            string fundingLineCode = NewRandomString();
            string fundingPeriodId = targetFundingPeriodId ?? NewRandomString();
            string fundingStreamId = NewRandomString();
            string specificationId = NewRandomString();

            IDictionary <string, string> fundingLineFileMetadata = new Dictionary <string, string>
            {
                { "job_type", jobType.ToString() },
                { "file_name", fundingLineFileName },
                { "funding_line_code", fundingLineCode },
                { "funding_period_id", fundingPeriodId },
                { "funding_stream_id", fundingStreamId },
                { "specification_id", specificationId }
            };

            SpecificationReportIdentifier id = new SpecificationReportIdentifier
            {
                JobType         = jobType,
                FundingLineCode = fundingLineCode,
                FundingPeriodId = fundingPeriodId,
                FundingStreamId = fundingStreamId,
                SpecificationId = specificationId
            };

            BlobProperties blobProperties = new BlobProperties();

            ICloudBlob fundingLineCloudBlob = Substitute.For <ICloudBlob>();

            fundingLineCloudBlob
            .Uri
            .Returns(BuildUri(fundingLineBlobName, fundingLineFileExtension));

            fundingLineCloudBlob
            .Metadata
            .Returns(fundingLineFileMetadata);

            fundingLineCloudBlob
            .Properties
            .Returns(blobProperties);

            IEnumerable <IListBlobItem> fundingLineListBlobItems = new List <IListBlobItem>
            {
                fundingLineCloudBlob
            };

            ICloudBlob calcResultsCloudBlob = Substitute.For <ICloudBlob>();

            calcResultsCloudBlob
            .Uri
            .Returns(BuildUri(calcResultsBlobName, calcResultsFileExtension));

            calcResultsCloudBlob
            .Properties
            .Returns(blobProperties);

            IEnumerable <IListBlobItem> calcResultsListBlobItems = new List <IListBlobItem>
            {
                calcResultsCloudBlob
            };

            _blobClient
            .ListBlobs(
                $"funding-lines-{specificationId}",
                PublishedProviderVersionsContainerName,
                true,
                BlobListingDetails.Metadata)
            .Returns(fundingLineListBlobItems);

            _blobClient
            .ListBlobs(
                $"calculation-results-{specificationId}",
                "calcresults",
                true,
                BlobListingDetails.Metadata)
            .Returns(calcResultsListBlobItems);

            IActionResult result = _service.GetReportMetadata(specificationId, targetFundingPeriodId);

            result
            .Should()
            .BeOfType <OkObjectResult>();

            IEnumerable <SpecificationReport> reportMetadata = ((OkObjectResult)result).Value as IEnumerable <SpecificationReport>;

            reportMetadata
            .Should()
            .NotBeNull();

            reportMetadata
            .Count()
            .Should()
            .Be(2);

            SpecificationReport metadata = reportMetadata
                                           .ElementAt(0);

            metadata
            .Should()
            .BeEquivalentTo(new SpecificationReport
            {
                Name     = fundingLineFileName,
                Category = expectedReportCategory.ToString(),
                Format   = "CSV",
                Size     = "-1 B",
                SpecificationReportIdentifier = EncodeSpecificationReportIdentifier(id)
            });
        }
        public async Task DownloadReport_GivenFileNameAndType_ReturnsDownloadUrl(JobType jobType)
        {
            string sasUrl = "http://www.test.com/test.csv";

            string fundingLineCode = NewRandomString();
            string fundingPeriodId = NewRandomString();
            string fundingStreamId = NewRandomString();
            string specificationId = NewRandomString();

            SpecificationReportIdentifier id = new SpecificationReportIdentifier
            {
                JobType         = jobType,
                FundingLineCode = fundingLineCode,
                FundingPeriodId = fundingPeriodId,
                FundingStreamId = fundingStreamId,
                SpecificationId = specificationId
            };

            string expectedBlobName = jobType == JobType.HistoryPublishedProviderEstate ?
                                      $"funding-lines-{specificationId}-{jobType}-{fundingPeriodId}.csv" :
                                      $"funding-lines-{specificationId}-{jobType}-{fundingLineCode}-{fundingStreamId}.csv";

            _blobClient
            .GetBlobSasUrl(expectedBlobName, Arg.Any <DateTimeOffset>(), SharedAccessBlobPermissions.Read, PublishedProviderVersionsContainerName)
            .Returns(sasUrl);

            string fundingLineFileName = "Funding Lines";

            IDictionary <string, string> fundingLineFileMetadata = new Dictionary <string, string>
            {
                { "file_name", fundingLineFileName },
            };

            ICloudBlob fundingLineCloudBlob = Substitute.For <ICloudBlob>();

            fundingLineCloudBlob
            .Metadata
            .Returns(fundingLineFileMetadata);

            _blobClient
            .GetBlobReferenceFromServerAsync(expectedBlobName, PublishedProviderVersionsContainerName)
            .Returns(Task.FromResult(fundingLineCloudBlob));

            IActionResult result = await _service.DownloadReport(EncodeSpecificationReportIdentifier(id));

            result
            .Should()
            .BeOfType <OkObjectResult>()
            .Which
            .Value
            .Should()
            .BeOfType <SpecificationsDownloadModel>();

            SpecificationsDownloadModel downloadModel = ((OkObjectResult)result).Value as SpecificationsDownloadModel;

            downloadModel
            .Url
            .Should()
            .Be(sasUrl);

            downloadModel
            .FileName
            .Should()
            .Be(fundingLineFileName);
        }