using System;
using System.Collections.Generic;
using Xunit;
using CncModels.Dto.Dashboard;
using CncModels.Entity;
using CncRepository.Interface;
using CncService.Interface;
using CncService.Impl;

namespace CncService.Tests
{
    // Fake repositories to isolate DashboardService.GetCollectorStatus tests
    public class FakeDashboardRepository : IDashboardRepository
    {
        public DashboardSummaryResponse GetSummary() => new DashboardSummaryResponse();
        public List<WorkshopProductionResponse> GetWorkshopProduction(DateTime startDate, DateTime endDate) => new List<WorkshopProductionResponse>();
        public List<MachineRankResponse> GetMachineRank(DateTime startDate, DateTime endDate, int top, string sortOrder = "desc") => new List<MachineRankResponse>();
        public List<WorkerRankResponse> GetWorkerRank(DateTime startDate, DateTime endDate, int top, string sortOrder = "desc") => new List<WorkerRankResponse>();
        public List<dynamic> GetProductionTrend(int days) => new List<dynamic>();
        public object GetMachineStatusDistribution() => new object();
        public List<AlertListItem> GetRecentAlerts(int count) => new List<AlertListItem>();
    }

    public class FakeCollectorHeartbeatRepository : ICollectorHeartbeatRepository
    {
        private readonly CollectorHeartbeat _latest;
        public FakeCollectorHeartbeatRepository(CollectorHeartbeat latest) { _latest = latest; }
        public long Create(CollectorHeartbeat entity) => 1;
        public CollectorHeartbeat GetLatest(string serviceId) => _latest;
        public int DeleteBeforeDate(DateTime date) => 0;
    }

    public class FakeWindowsServiceChecker : IWindowsServiceChecker
    {
        private readonly ServiceStatusEnum _status;
        public FakeWindowsServiceChecker(ServiceStatusEnum status) { _status = status; }
        public ServiceStatusEnum GetServiceStatus(string serviceName) => _status;
        public (bool, string) TryStartService(string serviceName, int timeoutSeconds) => (
            _status == ServiceStatusEnum.NotInstalled ? false : true,
            _status == ServiceStatusEnum.NotInstalled ? "NotInstalled" : "Started");
        public (bool, string) TryStopService(string serviceName, int timeoutSeconds) => (
            true, "Stopped");
    }

    public class FakeSysConfigRepository : ISysConfigRepository
    {
        public SysConfig GetByKey(string configKey) => new SysConfig { ConfigKey = configKey, ConfigValue = "300" };
        public List<SysConfig> GetAll() => new List<SysConfig>();
        public bool UpdateValue(int id, string value) => true;
    }

    public class DashboardServiceTests
    {
        [Fact]
        public void GetCollectorStatus_With_NotInstalled_Service_Returns_NotInstalled_State()
        {
            // Arrange
            var latest = new CollectorHeartbeat { Id = 1, ServiceId = "collector-service", Status = "running", UptimeSeconds = 120, LastCollectTime = DateTime.Now, CreatedAt = DateTime.Now };
            var dashboardRepo = new FakeDashboardRepository();
            var heartbeatRepo = new FakeCollectorHeartbeatRepository(latest);
            var checker = new FakeWindowsServiceChecker(CncService.Interface.ServiceStatusEnum.NotInstalled);

            var svc = new DashboardService(dashboardRepo, heartbeatRepo, new FakeSysConfigRepository(), checker);

            // Act
            var resultObj = svc.GetCollectorStatus();
            var t = resultObj.GetType();
            var statusProp = t.GetProperty("status");
            var serviceStatusProp = t.GetProperty("serviceStatus");
            var uptimeProp = t.GetProperty("uptimeSeconds");
            var lastCollectTimeProp = t.GetProperty("lastCollectTime");
            Assert.NotNull(statusProp);
            Assert.NotNull(serviceStatusProp);
            var statusVal = statusProp.GetValue(resultObj) as string;
            var serviceStatusVal = serviceStatusProp.GetValue(resultObj) as string;
            Assert.Equal("stopped", statusVal);
            Assert.Equal("NotInstalled", serviceStatusVal);
        }

        [Fact]
        public void GetCollectorStatus_With_Running_Heartbeats_Returns_Running_State()
        {
            var latest = new CollectorHeartbeat { Id = 1, ServiceId = "collector-service", Status = "running", UptimeSeconds = 60, LastCollectTime = DateTime.Now, CreatedAt = DateTime.Now };
            var dashboardRepo = new FakeDashboardRepository();
            var heartbeatRepo = new FakeCollectorHeartbeatRepository(latest);
            var checker = new FakeWindowsServiceChecker(CncService.Interface.ServiceStatusEnum.Running);
            var svc = new DashboardService(dashboardRepo, heartbeatRepo, new FakeSysConfigRepository(), checker);

            var resultObj = svc.GetCollectorStatus();
            var t = resultObj.GetType();
            var serviceStatusProp = t.GetProperty("serviceStatus");
            var statusProp = t.GetProperty("status");
            var serviceStatusVal = serviceStatusProp.GetValue(resultObj) as string;
            var statusVal = statusProp.GetValue(resultObj) as string;
            Assert.Equal("Running", serviceStatusVal);
            Assert.Equal("running", statusVal);
        }

        [Fact]
        public void GetCollectorStatus_With_Starting_ServiceStatus_Returns_Starting_State()
        {
            var latest = new CollectorHeartbeat { Id = 2, ServiceId = "collector-service", Status = "running", UptimeSeconds = 120, LastCollectTime = DateTime.Now, CreatedAt = DateTime.Now };
            var dashboardRepo = new FakeDashboardRepository();
            var heartbeatRepo = new FakeCollectorHeartbeatRepository(latest);
            var checker = new FakeWindowsServiceChecker(CncService.Interface.ServiceStatusEnum.Starting);
            var svc = new DashboardService(dashboardRepo, heartbeatRepo, new FakeSysConfigRepository(), checker);

            var resultObj = svc.GetCollectorStatus();
            var t = resultObj.GetType();
            var serviceStatusProp = t.GetProperty("serviceStatus");
            var statusProp = t.GetProperty("status");
            var serviceStatusVal = serviceStatusProp.GetValue(resultObj) as string;
            var statusVal = statusProp.GetValue(resultObj) as string;
            Assert.Equal("Starting", serviceStatusVal);
            Assert.Equal("running", statusVal);
        }
    }
}
