using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Haoliang.Models.Device;
using Haoliang.Models.DataCollection;

namespace Haoliang.Core.Services
{
    public interface IDeviceCollectionService
    {
        Task CollectAllDevicesAsync();
        Task CollectDeviceAsync(int deviceId);
        Task<DeviceCurrentStatus> CollectDeviceDataAsync(int deviceId);
        Task<bool> PingDeviceAsync(string ipAddress);
        Task<string> GetDeviceDataAsync(string httpUrl);
        Task ProcessCollectedDataAsync(CollectionResult result);
        Task<IEnumerable<CollectionResult>> GetCollectionHistoryAsync(int deviceId, DateTime startDate, DateTime endDate);
        Task<CollectionStatistics> GetCollectionStatisticsAsync(DateTime date);
        Task<CollectionHealth> GetCollectionHealthAsync();
        Task RestartFailedCollectionsAsync();
        Task<bool> TestConnectionAsync(int deviceId);
    }

    public interface IPingService
    {
        Task<bool> PingAsync(string ipAddress);
        Task<int> GetPingTimeAsync(string ipAddress);
        Task<bool> IsDeviceOnlineAsync(string ipAddress);
        Task<PingResult> GetPingResultAsync(string ipAddress);
    }

    public interface IDataParserService
    {
        Task<DeviceCurrentStatus> ParseDeviceDataAsync(string rawJson, int deviceId);
        Task<TagData> ParseTagDataAsync(object tagValue, string dataType);
        Task<bool> ValidateDeviceDataAsync(DeviceCurrentStatus data);
        Task<string> ConvertDataFormatAsync(object value, string dataType);
    }

    public interface IDataStorageService
    {
        Task SaveCollectionResultAsync(CollectionResult result);
        Task SaveDeviceStatusAsync(DeviceCurrentStatus status);
        Task SaveRawDataAsync(int deviceId, string rawJson, bool isSuccess, string errorMessage = null);
        Task LogCollectionAsync(int deviceId, LogLevel logLevel, string message, string data = null);
        Task ArchiveOldDataAsync(int daysToKeep = 30);
    }

    public class PingResult
    {
        public bool IsSuccess { get; set; }
        public int PingTimeMs { get; set; }
        public string ErrorMessage { get; set; }
        public DateTime Timestamp { get; set; }
    }

    public interface IRetryService
    {
        Task<T> ExecuteWithRetryAsync<T>(Func<Task<T>> operation, int maxRetries = 3, int delayMs = 30000);
        Task ExecuteWithRetryAsync(Func<Task> operation, int maxRetries = 3, int delayMs = 30000);
        bool ShouldRetry(Exception ex, int attemptNumber);
    }

    public class CollectionException : Exception
    {
        public int DeviceId { get; set; }
        public string DeviceCode { get; set; }
        public CollectionErrorType ErrorType { get; set; }
        
        public CollectionException(int deviceId, string deviceCode, string message, CollectionErrorType errorType)
            : base(message)
        {
            DeviceId = deviceId;
            DeviceCode = deviceCode;
            ErrorType = errorType;
        }
    }

    public enum CollectionErrorType
    {
        DeviceOffline,
        NetworkError,
        DataParseError,
        DatabaseError,
        Unknown
    }
}