// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Azure.Iot.Operations.Connector.Files;
using Azure.Iot.Operations.Services.AssetAndDeviceRegistry;
using Azure.Iot.Operations.Services.AssetAndDeviceRegistry.Models;
using Moq;

namespace Azure.Iot.Operations.Connector.UnitTests
{
    public class MockAzureDeviceRegistryClientWrapper : IAzureDeviceRegistryClientWrapper
    {
        public Mock<IAzureDeviceRegistryClientWrapper> mockClientWrapper { get; set; } = new Mock<IAzureDeviceRegistryClientWrapper>();
        private readonly Mock<IAzureDeviceRegistryClient> _mockClient = new Mock<IAzureDeviceRegistryClient>();

        public event EventHandler<AssetChangedEventArgs>? AssetChanged;
        public event EventHandler<DeviceChangedEventArgs>? DeviceChanged;

        public void SimulateAssetChanged(AssetChangedEventArgs args)
        {
            AssetChanged?.Invoke(this, args);
        }

        public void SimulateDeviceChanged(DeviceChangedEventArgs args)
        {
            DeviceChanged?.Invoke(this, args);
        }

        public IEnumerable<string> GetAssetNames(string deviceName, string inboundEndpointName)
        {
            return mockClientWrapper.Object.GetAssetNames(deviceName, inboundEndpointName);
        }

        public EndpointCredentials GetEndpointCredentials(string deviceName, string inboundEndpointName, InboundEndpointSchemaMapValue inboundEndpoint)
        {
            return mockClientWrapper.Object.GetEndpointCredentials(deviceName, inboundEndpointName, inboundEndpoint);
        }

        public IEnumerable<string> GetDeviceNames()
        {
            return mockClientWrapper.Object.GetDeviceNames();
        }

        public IEnumerable<string> GetInboundEndpointNames(string deviceName)
        {
            return mockClientWrapper.Object.GetInboundEndpointNames(deviceName);
        }

        public void ObserveAssets(string deviceName, string inboundEndpointName)
        {
            mockClientWrapper.Object.ObserveAssets(deviceName, inboundEndpointName);
        }

        public void ObserveDevices()
        {
            mockClientWrapper.Object.ObserveDevices();
        }

        public Task UnobserveAllAsync(CancellationToken cancellationToken = default)
        {
            return mockClientWrapper.Object.UnobserveAllAsync();
        }

        public Task UnobserveAssetsAsync(string deviceName, string inboundEndpointName, CancellationToken cancellationToken = default)
        {
            return mockClientWrapper.Object.UnobserveAssetsAsync(deviceName, inboundEndpointName, cancellationToken);
        }

        public Task UnobserveDevicesAsync(CancellationToken cancellationToken = default)
        {
            return mockClientWrapper.Object.UnobserveDevicesAsync(cancellationToken);
        }

        public Task<DeviceStatus> GetDeviceStatusAsync(string deviceName, string inboundEndpointName, TimeSpan? commandTimeout = null, CancellationToken cancellationToken = default)
        {
            return mockClientWrapper.Object.GetDeviceStatusAsync(deviceName, inboundEndpointName, commandTimeout, cancellationToken);
        }

        public Task<AssetStatus> GetAssetStatusAsync(string deviceName, string inboundEndpointName, string assetName, TimeSpan? commandTimeout = null, CancellationToken cancellationToken = default)
        {
            return mockClientWrapper.Object.GetAssetStatusAsync(deviceName, inboundEndpointName, assetName, commandTimeout, cancellationToken);
        }

        public Task<AssetStatus> UpdateAssetStatusAsync(string deviceName, string inboundEndpointName, UpdateAssetStatusRequest request, TimeSpan? commandTimeout = null, CancellationToken cancellationToken = default)
        {
            return mockClientWrapper.Object.UpdateAssetStatusAsync(deviceName, inboundEndpointName, request, commandTimeout, cancellationToken);
        }

        public Task<DeviceStatus> UpdateDeviceStatusAsync(string deviceName, string inboundEndpointName, DeviceStatus status, TimeSpan? commandTimeout = null, CancellationToken cancellationToken = default)
        {
            return mockClientWrapper.Object.UpdateDeviceStatusAsync(deviceName, inboundEndpointName, status, commandTimeout, cancellationToken);
        }

        public Task<CreateOrUpdateDiscoveredAssetResponsePayload> CreateOrUpdateDiscoveredAssetAsync(string deviceName, string inboundEndpointName, CreateOrUpdateDiscoveredAssetRequest request, TimeSpan? commandTimeout = null, CancellationToken cancellationToken = default)
        {
            return mockClientWrapper.Object.CreateOrUpdateDiscoveredAssetAsync(deviceName, inboundEndpointName, request, commandTimeout, cancellationToken);
        }

        public Task<CreateOrUpdateDiscoveredDeviceResponsePayload> CreateOrUpdateDiscoveredDeviceAsync(CreateOrUpdateDiscoveredDeviceRequestSchema request, string inboundEndpointType, TimeSpan? commandTimeout = null, CancellationToken cancellationToken = default)
        {
            return mockClientWrapper.Object.CreateOrUpdateDiscoveredDeviceAsync(request, inboundEndpointType, commandTimeout, cancellationToken);
        }

        public ValueTask DisposeAsync()
        {
            return ValueTask.CompletedTask;
        }

        public async Task ReportDeviceEndpointRuntimeHealthAsync(string deviceName, string inboundEndpointName, RuntimeHealth deviceEndpointRuntimeHealth, TimeSpan? telemetryTimeout = null, CancellationToken cancellationToken = default)
        {
            await mockClientWrapper.Object.ReportDeviceEndpointRuntimeHealthAsync(deviceName, inboundEndpointName, deviceEndpointRuntimeHealth, telemetryTimeout, cancellationToken);
        }

        public async Task ReportDatasetRuntimeHealthAsync(string deviceName, string inboundEndpointName, string assetName, List<DatasetsRuntimeHealthEvent> datasetsRuntimeHealth, TimeSpan? telemetryTimeout = null, CancellationToken cancellationToken = default)
        {
            await mockClientWrapper.Object.ReportDatasetRuntimeHealthAsync(deviceName, inboundEndpointName, assetName, datasetsRuntimeHealth, telemetryTimeout, cancellationToken);
        }

        public async Task ReportEventRuntimeHealthAsync(string deviceName, string inboundEndpointName, string assetName, List<EventsRuntimeHealthEvent> eventsRuntimeHealth, TimeSpan? telemetryTimeout = null, CancellationToken cancellationToken = default)
        {
            await mockClientWrapper.Object.ReportEventRuntimeHealthAsync(deviceName, inboundEndpointName, assetName, eventsRuntimeHealth, telemetryTimeout, cancellationToken);
        }

        public async Task ReportStreamRuntimeHealthAsync(string deviceName, string inboundEndpointName, string assetName, List<StreamsRuntimeHealthEvent> streamsRuntimeHealth, TimeSpan? telemetryTimeout = null, CancellationToken cancellationToken = default)
        {
            await mockClientWrapper.Object.ReportStreamRuntimeHealthAsync(deviceName, inboundEndpointName, assetName, streamsRuntimeHealth, telemetryTimeout, cancellationToken);
        }

        public async Task ReportManagementActionRuntimeHealthAsync(string deviceName, string inboundEndpointName, string assetName, List<ManagementActionsRuntimeHealthEvent> managementActionsRuntimeHealth, TimeSpan? telemetryTimeout = null, CancellationToken cancellationToken = default)
        {
            await mockClientWrapper.Object.ReportManagementActionRuntimeHealthAsync(deviceName, inboundEndpointName, assetName, managementActionsRuntimeHealth, telemetryTimeout, cancellationToken);
        }

        public IAzureDeviceRegistryClient GetWrapped()
        {
            return _mockClient.Object;
        }
    }
}
