using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Haoliang.Core.Services;
using Haoliang.Models.System;
using Haoliang.Models.Device;

namespace Haoliang.Api.Controllers
{
    [ApiController]
    [Route("api/v1/[controller]")]
    public class AlarmController : ControllerBase
    {
        private readonly IAlarmService _alarmService;
        private readonly IAlarmRuleService _alarmRuleService;
        private readonly IAlarmNotificationService _notificationService;
        private readonly ILoggingService _loggingService;

        public AlarmController(
            IAlarmService alarmService,
            IAlarmRuleService alarmRuleService,
            IAlarmNotificationService notificationService,
            ILoggingService loggingService)
        {
            _alarmService = alarmService;
            _alarmRuleService = alarmRuleService;
            _notificationService = notificationService;
            _loggingService = loggingService;
        }

        [HttpGet]
        public async Task<IActionResult> GetAllAlarms([FromQuery] AlarmType? type = null, [FromQuery] AlarmStatus? status = null)
        {
            try
            {
                IEnumerable<Alarm> alarms;
                if (type.HasValue)
                {
                    alarms = await _alarmService.GetAlarmsByTypeAsync(type.Value);
                }
                else if (status.HasValue)
                {
                    alarms = await _alarmService.GetActiveAlarmsAsync();
                }
                else
                {
                    alarms = await _alarmService.GetAllAlarmsAsync();
                }

                return Ok(ApiResponse.Success(alarms));
            }
            catch (Exception ex)
            {
                await _loggingService.LogErrorAsync("Failed to get alarms", ex);
                return StatusCode(500, ApiResponse.Error("Failed to get alarms"));
            }
        }

        [HttpGet("{id}")]
        public async Task<IActionResult> GetAlarm(int id)
        {
            try
            {
                var alarm = await _alarmService.GetAlarmByIdAsync(id);
                if (alarm == null)
                {
                    return NotFound(ApiResponse.NotFound("Alarm not found"));
                }
                return Ok(ApiResponse.Success(alarm));
            }
            catch (Exception ex)
            {
                await _loggingService.LogErrorAsync($"Failed to get alarm {id}", ex);
                return StatusCode(500, ApiResponse.Error("Failed to get alarm"));
            }
        }

        [HttpPost]
        public async Task<IActionResult> CreateAlarm([FromBody] Alarm alarm)
        {
            try
            {
                var createdAlarm = await _alarmService.CreateAlarmAsync(alarm);
                return Ok(ApiResponse.Success(createdAlarm, "Alarm created successfully"));
            }
            catch (Exception ex)
            {
                await _loggingService.LogErrorAsync("Failed to create alarm", ex);
                return StatusCode(500, ApiResponse.Error("Failed to create alarm"));
            }
        }

        [HttpPut("{id}")]
        public async Task<IActionResult> UpdateAlarm(int id, [FromBody] Alarm alarm)
        {
            try
            {
                alarm.AlarmId = id;
                var updatedAlarm = await _alarmService.UpdateAlarmAsync(id, alarm);
                if (updatedAlarm == null)
                {
                    return NotFound(ApiResponse.NotFound("Alarm not found"));
                }
                return Ok(ApiResponse.Success(updatedAlarm, "Alarm updated successfully"));
            }
            catch (Exception ex)
            {
                await _loggingService.LogErrorAsync($"Failed to update alarm {id}", ex);
                return StatusCode(500, ApiResponse.Error("Failed to update alarm"));
            }
        }

        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteAlarm(int id)
        {
            try
            {
                var result = await _alarmService.DeleteAlarmAsync(id);
                if (!result)
                {
                    return NotFound(ApiResponse.NotFound("Alarm not found"));
                }
                return Ok(ApiResponse.Success(null, "Alarm deleted successfully"));
            }
            catch (Exception ex)
            {
                await _loggingService.LogErrorAsync($"Failed to delete alarm {id}", ex);
                return StatusCode(500, ApiResponse.Error("Failed to delete alarm"));
            }
        }

        [HttpPost("{id}/resolve")]
        public async Task<IActionResult> ResolveAlarm(int id, [FromBody] ResolveAlarmRequest request)
        {
            try
            {
                var result = await _alarmService.ResolveAlarmAsync(id, request.ResolutionNote);
                if (!result)
                {
                    return NotFound(ApiResponse.NotFound("Alarm not found"));
                }
                return Ok(ApiResponse.Success(null, "Alarm resolved successfully"));
            }
            catch (Exception ex)
            {
                await _loggingService.LogErrorAsync($"Failed to resolve alarm {id}", ex);
                return StatusCode(500, ApiResponse.Error("Failed to resolve alarm"));
            }
        }

        [HttpPost("{id}/acknowledge")]
        public async Task<IActionResult> AcknowledgeAlarm(int id, [FromBody] AcknowledgeAlarmRequest request)
        {
            try
            {
                var result = await _alarmService.AcknowledgeAlarmAsync(id, request.AcknowledgeNote);
                if (!result)
                {
                    return NotFound(ApiResponse.NotFound("Alarm not found"));
                }
                return Ok(ApiResponse.Success(null, "Alarm acknowledged successfully"));
            }
            catch (Exception ex)
            {
                await _loggingService.LogErrorAsync($"Failed to acknowledge alarm {id}", ex);
                return StatusCode(500, ApiResponse.Error("Failed to acknowledge alarm"));
            }
        }

        [HttpGet("device/{deviceId}")]
        public async Task<IActionResult> GetDeviceAlarms(int deviceId, [FromQuery] int days = 7)
        {
            try
            {
                var alarms = await _alarmService.GetDeviceAlarmsAsync(deviceId, days);
                return Ok(ApiResponse.Success(alarms));
            }
            catch (Exception ex)
            {
                await _loggingService.LogErrorAsync($"Failed to get alarms for device {deviceId}", ex);
                return StatusCode(500, ApiResponse.Error("Failed to get device alarms"));
            }
        }

        [HttpGet("critical")]
        public async Task<IActionResult> GetCriticalAlarms()
        {
            try
            {
                var alarms = await _alarmService.GetCriticalAlarmsAsync();
                return Ok(ApiResponse.Success(alarms));
            }
            catch (Exception ex)
            {
                await _loggingService.LogErrorAsync("Failed to get critical alarms", ex);
                return StatusCode(500, ApiResponse.Error("Failed to get critical alarms"));
            }
        }

        [HttpGet("statistics")]
        public async Task<IActionResult> GetAlarmStatistics([FromQuery] DateTime date)
        {
            try
            {
                if (date == default)
                    date = DateTime.Today;

                var statistics = await _alarmService.GetAlarmStatisticsAsync(date);
                return Ok(ApiResponse.Success(statistics));
            }
            catch (Exception ex)
            {
                await _loggingService.LogErrorAsync("Failed to get alarm statistics", ex);
                return StatusCode(500, ApiResponse.Error("Failed to get alarm statistics"));
            }
        }

        [HttpGet("date-range")]
        public async Task<IActionResult> GetAlarmsByDateRange([FromQuery] DateTime startDate, [FromQuery] DateTime endDate)
        {
            try
            {
                var alarms = await _alarmService.GetAlarmsByDateRangeAsync(startDate, endDate);
                return Ok(ApiResponse.Success(alarms));
            }
            catch (Exception ex)
            {
                await _loggingService.LogErrorAsync("Failed to get alarms by date range", ex);
                return StatusCode(500, ApiResponse.Error("Failed to get alarms by date range"));
            }
        }

        [HttpPost("test-notification")]
        public async Task<IActionResult> TestNotification([FromBody] TestNotificationRequest request)
        {
            try
            {
                var notification = new AlarmNotification
                {
                    AlarmId = -1,
                    DeviceId = request.DeviceId,
                    NotificationType = request.NotificationType,
                    Message = "Test notification",
                    SendTime = DateTime.Now,
                    Status = NotificationStatus.Sent,
                    Recipient = request.Recipient
                };

                await _notificationService.SendAlarmNotificationAsync(notification);
                return Ok(ApiResponse.Success(null, "Test notification sent successfully"));
            }
            catch (Exception ex)
            {
                await _loggingService.LogErrorAsync("Failed to send test notification", ex);
                return StatusCode(500, ApiResponse.Error("Failed to send test notification"));
            }
        }

        [HttpGet("rules")]
        public async Task<IActionResult> GetAlarmRules()
        {
            try
            {
                var rules = await _alarmRuleService.GetAllAlarmRulesAsync();
                return Ok(ApiResponse.Success(rules));
            }
            catch (Exception ex)
            {
                await _loggingService.LogErrorAsync("Failed to get alarm rules", ex);
                return StatusCode(500, ApiResponse.Error("Failed to get alarm rules"));
            }
        }

        [HttpPost("rules")]
        public async Task<IActionResult> CreateAlarmRule([FromBody] AlarmRule rule)
        {
            try
            {
                var createdRule = await _alarmRuleService.CreateAlarmRuleAsync(rule);
                return Ok(ApiResponse.Success(createdRule, "Alarm rule created successfully"));
            }
            catch (Exception ex)
            {
                await _loggingService.LogErrorAsync("Failed to create alarm rule", ex);
                return StatusCode(500, ApiResponse.Error("Failed to create alarm rule"));
            }
        }

        [HttpPost("rules/{id}/test")]
        public async Task<IActionResult> TestAlarmRule(int id)
        {
            try
            {
                await _alarmRuleService.TestAlarmRuleAsync(id);
                return Ok(ApiResponse.Success(null, "Alarm rule test completed"));
            }
            catch (Exception ex)
            {
                await _loggingService.LogErrorAsync($"Failed to test alarm rule {id}", ex);
                return StatusCode(500, ApiResponse.Error("Failed to test alarm rule"));
            }
        }
    }

    public class ResolveAlarmRequest
    {
        public string ResolutionNote { get; set; }
    }

    public class AcknowledgeAlarmRequest
    {
        public string AcknowledgeNote { get; set; }
    }

    public class TestNotificationRequest
    {
        public int DeviceId { get; set; }
        public NotificationType NotificationType { get; set; }
        public string Recipient { get; set; }
    }
}