using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Haoliang.Models.System;
using Haoliang.Models.Device;
using Haoliang.Models.DataCollection;
using Haoliang.Data.Repositories;
using Haoliang.Core.Services;

namespace Haoliang.Core.Services
{
    public interface IAlarmService
    {
        Task<Alarm> CreateAlarmAsync(Alarm alarm);
        Task<Alarm> UpdateAlarmAsync(int alarmId, Alarm alarm);
        Task<bool> DeleteAlarmAsync(int alarmId);
        Task<Alarm> GetAlarmByIdAsync(int alarmId);
        Task<IEnumerable<Alarm>> GetAllAlarmsAsync();
        Task<IEnumerable<Alarm>> GetAlarmsByDeviceAsync(int deviceId);
        Task<IEnumerable<Alarm>> GetAlarmsByTypeAsync(AlarmType type);
        Task<IEnumerable<Alarm>> GetActiveAlarmsAsync();
        Task<IEnumerable<Alarm>> GetAlarmsByDateRangeAsync(DateTime startDate, DateTime endDate);
        Task<bool> ResolveAlarmAsync(int alarmId, string resolutionNote);
        Task<bool> AcknowledgeAlarmAsync(int alarmId, string acknowledgeNote);
        Task<AlarmStatistics> GetAlarmStatisticsAsync(DateTime date);
        Task<IEnumerable<Alarm>> GetCriticalAlarmsAsync();
        Task<IEnumerable<Alarm>> GetDeviceAlarmsAsync(int deviceId, int days = 7);
    }

    public class AlarmManager : IAlarmService
    {
        private readonly IAlarmRepository _alarmRepository;
        private readonly IAlarmRuleService _alarmRuleService;
        private readonly IAlarmNotificationService _notificationService;

        public AlarmManager(
            IAlarmRepository alarmRepository,
            IAlarmRuleService alarmRuleService,
            IAlarmNotificationService notificationService)
        {
            _alarmRepository = alarmRepository;
            _alarmRuleService = alarmRuleService;
            _notificationService = notificationService;
        }

        public async Task<Alarm> CreateAlarmAsync(Alarm alarm)
        {
            alarm.AlarmStatus = AlarmStatus.Active;
            alarm.CreateTime = DateTime.Now;
            alarm.UpdateTime = DateTime.Now;
            
            var createdAlarm = await _alarmRepository.AddAsync(alarm);
            await _notificationService.SendAlarmNotificationAsync(createdAlarm);
            
            return createdAlarm;
        }

        public async Task<Alarm> UpdateAlarmAsync(int alarmId, Alarm alarm)
        {
            var existingAlarm = await _alarmRepository.GetByIdAsync(alarmId);
            if (existingAlarm == null)
            {
                throw new KeyNotFoundException($"Alarm with ID {alarmId} not found");
            }

            alarm.AlarmId = alarmId;
            alarm.UpdateTime = DateTime.Now;
            
            var updatedAlarm = await _alarmRepository.UpdateAsync(alarm);
            return updatedAlarm;
        }

        public async Task<bool> DeleteAlarmAsync(int alarmId)
        {
            return await _alarmRepository.DeleteAsync(alarmId);
        }

        public async Task<Alarm> GetAlarmByIdAsync(int alarmId)
        {
            return await _alarmRepository.GetByIdAsync(alarmId);
        }

        public async Task<IEnumerable<Alarm>> GetAllAlarmsAsync()
        {
            return await _alarmRepository.GetAllAsync();
        }

        public async Task<IEnumerable<Alarm>> GetAlarmsByDeviceAsync(int deviceId)
        {
            return await _alarmRepository.GetByDeviceIdAsync(deviceId);
        }

        public async Task<IEnumerable<Alarm>> GetAlarmsByTypeAsync(AlarmType type)
        {
            return await _alarmRepository.GetByAlarmTypeAsync(type);
        }

        public async Task<IEnumerable<Alarm>> GetActiveAlarmsAsync()
        {
            return await _alarmRepository.GetByStatusAsync(AlarmStatus.Active);
        }

        public async Task<IEnumerable<Alarm>> GetAlarmsByDateRangeAsync(DateTime startDate, DateTime endDate)
        {
            return await _alarmRepository.GetByDateRangeAsync(startDate, endDate);
        }

        public async Task<bool> ResolveAlarmAsync(int alarmId, string resolutionNote)
        {
            var alarm = await _alarmRepository.GetByIdAsync(alarmId);
            if (alarm == null)
            {
                return false;
            }

            alarm.AlarmStatus = AlarmStatus.Resolved;
            alarm.ResolutionNote = resolutionNote;
            alarm.ResolvedTime = DateTime.Now;
            alarm.UpdateTime = DateTime.Now;

            return await _alarmRepository.UpdateAsync(alarm) != null;
        }

        public async Task<bool> AcknowledgeAlarmAsync(int alarmId, string acknowledgeNote)
        {
            var alarm = await _alarmRepository.GetByIdAsync(alarmId);
            if (alarm == null)
            {
                return false;
            }

            alarm.AlarmStatus = AlarmStatus.Acknowledged;
            alarm.AcknowledgeNote = acknowledgeNote;
            alarm.AcknowledgedTime = DateTime.Now;
            alarm.UpdateTime = DateTime.Now;

            return await _alarmRepository.UpdateAsync(alarm) != null;
        }

        public async Task<AlarmStatistics> GetAlarmStatisticsAsync(DateTime date)
        {
            return await _alarmRepository.GetAlarmStatisticsAsync(date);
        }

        public async Task<IEnumerable<Alarm>> GetCriticalAlarmsAsync()
        {
            return await _alarmRepository.GetBySeverityAsync(AlarmSeverity.Critical);
        }

        public async Task<IEnumerable<Alarm>> GetDeviceAlarmsAsync(int deviceId, int days = 7)
        {
            var startDate = DateTime.Now.AddDays(-days);
            var endDate = DateTime.Now;
            return await _alarmRepository.GetByDeviceAndDateRangeAsync(deviceId, startDate, endDate);
        }
    }
}