public static IEnumerable <object[]> ValidInstalledAppInstance()
        {
            var installedApp = new InstalledAppInstance()
            {
                InstalledAppId    = Guid.NewGuid().ToString(),
                InstalledLocation = new Location()
                {
                    CountryCode = "US",
                    Id          = Guid.NewGuid().ToString(),
                    Label       = "Home",
                    Latitude    = 40.347054,
                    Longitude   = -74.064308,
                    TempScale   = TemperatureScale.F,
                    TimeZoneId  = "America/New_York",
                    Locale      = "en"
                }
            };

            installedApp.SetTokens(Guid.NewGuid().ToString(), Guid.NewGuid().ToString());

            return(new List <object[]>
            {
                new object[] { installedApp }
            });
        }
        public static InstalledAppInstance GetValidInstalledAppInstance()
        {
            if (installedAppInstance == null)
            {
                installedAppInstance = new InstalledAppInstance()
                {
                    InstalledAppId    = "d692699d-e7a6-400d-a0b7-d5be96e7a564",
                    InstalledLocation = new Location()
                    {
                        CountryCode = "US",
                        Id          = "e675a3d9-2499-406c-86dc-8a492a88649",
                        Label       = "Home",
                        Latitude    = 40.347054,
                        Longitude   = -74.064308,
                        TempScale   = TemperatureScale.F,
                        TimeZoneId  = "America/New_York",
                        Locale      = "en"
                    }
                };
            }

            installedAppInstance.SetTokens(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), (long)TimeSpan.FromDays(99).TotalMilliseconds);

            return(installedAppInstance);
        }
        public void SmartThingsAPIHelper_RefreshTokensAsync_Should_Not_Throw()
        {
            var installedApp = new InstalledAppInstance()
            {
                InstalledAppId    = Guid.NewGuid().ToString(),
                InstalledLocation = new Location()
                {
                    CountryCode = "US",
                    Id          = Guid.NewGuid().ToString(),
                    Label       = "Home",
                    Latitude    = 40.347054,
                    Longitude   = -74.064308,
                    TempScale   = TemperatureScale.F,
                    TimeZoneId  = "America/New_York",
                    Locale      = "en"
                }
            };

            installedApp.SetTokens(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), -100);

            _mockHttpMessageHandler.SetupRequest(HttpMethod.Post,
                                                 "https://auth-global.api.smartthings.com/oauth/token")
            .ReturnsResponse(@"
                {
                    ""access_token"":""foo"",
                    ""refresh_token"":""foo"",
                    ""expires_in"":""1""
                }");

            _smartThingsAPIHelper.RefreshTokensAsync(installedApp);
        }
        public void SmartThingsAPIHelper_RefreshTokensAsync_Should_HandleError()
        {
            var installedApp = new InstalledAppInstance()
            {
                InstalledAppId    = Guid.NewGuid().ToString(),
                InstalledLocation = new Location()
                {
                    CountryCode = "US",
                    Id          = Guid.NewGuid().ToString(),
                    Label       = "Home",
                    Latitude    = 40.347054,
                    Longitude   = -74.064308,
                    TempScale   = TemperatureScale.F,
                    TimeZoneId  = "America/New_York",
                    Locale      = "en"
                }
            };

            installedApp.SetTokens(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), -100);

            _mockHttpMessageHandler.SetupRequest(HttpMethod.Post,
                                                 "https://auth-global.api.smartthings.com/oauth/token")
            .ReturnsResponse(System.Net.HttpStatusCode.InternalServerError,
                             "ERROR");

            _smartThingsAPIHelper.RefreshTokensAsync(installedApp);
        }
        public async Task <InstalledAppInstance> RefreshTokensAsync(InstalledAppInstance installedApp)
        {
            _ = installedApp ?? throw new ArgumentNullException(nameof(installedApp));

            if (installedApp.AccessToken.IsExpired ||
                installedApp.RefreshToken.IsExpired)
            {
                _logger.LogDebug($"Refreshing tokens for installedApp: {installedApp.InstalledAppId}...");

                var uri = new Uri($"https://auth-global.api.smartthings.com/oauth/token");

                using var request = new HttpRequestMessage(HttpMethod.Post, uri);

                request.SetBasicAuthHeader(_appConfig.SmartAppClientId,
                                           _appConfig.SmartAppClientSecret);

                var data = $"grant_type=refresh_token&client_id={_appConfig.SmartAppClientId}&client_secret={_appConfig.SmartAppClientSecret}&refresh_token={installedApp.RefreshToken.TokenValue}";
                request.Content = new StringContent(data, Encoding.UTF8, "application/x-www-form-urlencoded");

                var response = await _httpClient.SendAsync(request).ConfigureAwait(false);

                if (!response.IsSuccessStatusCode)
                {
                    var errorBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                    _logger.LogError($"Error trying to refresh tokens...  Response body: {errorBody}");
                }

                response.EnsureSuccessStatusCode();

                var body = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                dynamic tokenDetails = JObject.Parse(body);

                _ = tokenDetails.access_token ?? throw new InvalidOperationException("tokenDetails.access_token == null!");
                _ = tokenDetails.refresh_token ?? throw new InvalidOperationException("tokenDetails.refresh_token == null!");
                _ = tokenDetails.expires_in ?? throw new InvalidOperationException("tokenDetails.expires_in == null!");

                _logger.LogDebug($"Setting tokens for installedApp: {installedApp.InstalledAppId}...");

                installedApp.SetTokens(tokenDetails.access_token.Value,
                                       tokenDetails.refresh_token.Value,
                                       tokenDetails.expires_in.Value);
            }
            else
            {
                _logger.LogDebug($"NOT Refreshing tokens for installedApp: {installedApp.InstalledAppId}, tokens not expired...");
            }

            return(installedApp);
        }