using System;
using System.Collections.Generic;
using System.Linq;
using CNCSystem.Data.Entities;
using CNCSystem.Models.Production;

namespace CNCSystem.Data.Repositories
{
    public class ProductionRepository
    {
        private readonly CNCBusinessDbContext _context;

        public ProductionRepository(CNCBusinessDbContext context)
        {
            _context = context;
        }

        public List<ProductionRecord> GetProductionRecords(int? deviceId = null, DateTime? startDate = null, 
            DateTime? endDate = null, string ncProgram = null)
        {
            var query = _context.ProductionRecords.AsQueryable();

            if (deviceId.HasValue)
            {
                query = query.Where(pr => pr.DeviceId == deviceId.Value);
            }

            if (startDate.HasValue)
            {
                query = query.Where(pr => pr.ProductionDate >= startDate.Value);
            }

            if (endDate.HasValue)
            {
                query = query.Where(pr => pr.ProductionDate <= endDate.Value);
            }

            if (!string.IsNullOrEmpty(ncProgram))
            {
                query = query.Where(pr => pr.NCProgram == ncProgram);
            }

            return query.OrderByDescending(pr => pr.ProductionDate)
                       .ThenByDescending(pr => pr.CreatedAt)
                       .ToList();
        }

        public ProductionRecord GetProductionRecord(int id)
        {
            return _context.ProductionRecords.Find(id);
        }

        public ProductionRecord CreateProductionRecord(ProductionRecord record)
        {
            _context.ProductionRecords.Add(record);
            _context.SaveChanges();
            return record;
        }

        public void UpdateProductionRecord(ProductionRecord record)
        {
            _context.Entry(record).State = System.Data.Entity.EntityState.Modified;
            _context.SaveChanges();
        }

        public void DeleteProductionRecord(int id)
        {
            var record = _context.ProductionRecords.Find(id);
            if (record != null)
            {
                _context.ProductionRecords.Remove(record);
                _context.SaveChanges();
            }
        }

        public List<ProgramProductionSummary> GetProgramProductionSummary(int deviceId, DateTime date)
        {
            return _context.ProgramProductionSummary
                .Where(s => s.DeviceId == deviceId && s.ProductionDate == date)
                .ToList();
        }

        public ProgramProductionSummary CreateOrUpdateProgramProductionSummary(ProgramProductionSummary summary)
        {
            var existing = _context.ProgramProductionSummary
                .FirstOrDefault(s => s.DeviceId == summary.DeviceId && 
                                    s.NCProgram == summary.NCProgram && 
                                    s.ProductionDate == summary.ProductionDate);

            if (existing != null)
            {
                // 更新现有记录
                existing.TotalQuantity = summary.TotalQuantity;
                existing.ValidQuantity = summary.ValidQuantity;
                existing.InvalidQuantity = summary.InvalidQuantity;
                existing.QualityRate = summary.QualityRate;
                _context.Entry(existing).State = System.Data.Entity.EntityState.Modified;
            }
            else
            {
                // 创建新记录
                _context.ProgramProductionSummary.Add(summary);
            }

            _context.SaveChanges();
            return existing ?? summary;
        }

        public ProductionStatistics GetProductionStatistics(DateTime date, int? deviceId = null, string ncProgram = null)
        {
            var query = _context.ProductionRecords.AsQueryable();

            query = query.Where(pr => pr.ProductionDate == date);

            if (deviceId.HasValue)
            {
                query = query.Where(pr => pr.DeviceId == deviceId.Value);
            }

            if (!string.IsNullOrEmpty(ncProgram))
            {
                query = query.Where(pr => pr.NCProgram == ncProgram);
            }

            var records = query.ToList();

            return new ProductionStatistics
            {
                Date = date,
                DeviceId = deviceId ?? 0,
                NCProgram = ncProgram,
                TotalQuantity = records.Sum(pr => pr.Quantity),
                ValidQuantity = records.Sum(pr => pr.Quantity),
                InvalidQuantity = 0, // 需要根据实际情况计算
                QualityRate = records.Any() ? records.Average(pr => pr.QualityRate) : 100
            };
        }

        public List<ProductionRealtimeData> GetProductionRealtimeData()
        {
            // 获取所有设备的实时生产数据
            var devices = _context.Devices.ToList();
            var realtimeData = new List<ProductionRealtimeData>();

            foreach (var device in devices)
            {
                var todayProduction = _context.ProductionRecords
                    .FirstOrDefault(pr => pr.DeviceId == device.Id && 
                                       pr.ProductionDate == DateTime.Today);

                var latestStatus = _context.DeviceStatus
                    .Where(ds => ds.DeviceId == device.Id)
                    .OrderByDescending(ds => ds.RecordTime)
                    .FirstOrDefault();

                var realtime = new ProductionRealtimeData
                {
                    DeviceId = device.Id,
                    DeviceCode = device.DeviceCode,
                    DeviceName = device.DeviceName,
                    Status = latestStatus?.Status ?? "离线",
                    IsRunning = latestStatus?.IsRunning ?? false,
                    NCProgram = latestStatus?.NCProgram,
                    CurrentCount = latestStatus?.CumulativeCount ?? 0,
                    TodayQuantity = todayProduction?.Quantity ?? 0,
                    LastUpdateTime = latestStatus?.RecordTime ?? DateTime.Now
                };

                realtimeData.Add(realtime);
            }

            return realtimeData;
        }

        public void CleanupOldProductionRecords(int retentionDays)
        {
            var cutoffDate = DateTime.Today.AddDays(-retentionDays);
            var oldRecords = _context.ProductionRecords
                .Where(pr => pr.ProductionDate < cutoffDate)
                .ToList();

            _context.ProductionRecords.RemoveRange(oldRecords);
            _context.SaveChanges();
        }
    }

    public class ProductionCollectionService
    {
        private readonly ProductionRepository _productionRepository;
        private readonly DeviceCurrentStatusRepository _deviceStatusRepository;
        private readonly TemplateMappingService _templateMappingService;
        private readonly CNCLLogDbContext _logContext;

        public ProductionCollectionService(ProductionRepository productionRepository,
            DeviceCurrentStatusRepository deviceStatusRepository,
            TemplateMappingService templateMappingService,
            CNCLLogDbContext logContext)
        {
            _productionRepository = productionRepository;
            _deviceStatusRepository = deviceStatusRepository;
            _templateMappingService = templateMappingService;
            _logContext = logContext;
        }

        public void ProcessDeviceData(int deviceId, Dictionary<string, object> rawData)
        {
            try
            {
                // 获取设备信息
                var device = _deviceStatusRepository.GetDeviceCurrentStatus(deviceId);
                if (device == null)
                {
                    throw new Exception($"设备 {deviceId} 不存在");
                }

                // 获取设备模板
                var deviceTemplate = GetDeviceTemplate(deviceId);
                if (deviceTemplate == null)
                {
                    throw new Exception($"设备 {deviceId} 未配置模板");
                }

                // 映射原始数据到标准格式
                var standardData = _templateMappingService.MapRawDataToStandardFormat(
                    deviceTemplate.BrandName, rawData);

                // 创建设备状态记录
                var deviceStatus = new DeviceStatus
                {
                    DeviceId = deviceId,
                    Status = standardData.ContainsKey("_io_status") ? 
                        standardData["_io_status"].ToString() : "未知",
                    IsRunning = standardData.ContainsKey("Tag9") && 
                        standardData["Tag9"].ToString() == "1",
                    NCProgram = standardData.ContainsKey("Tag5") ? 
                        standardData["Tag5"].ToString() : null,
                    CumulativeCount = standardData.ContainsKey("Tag8") ? 
                        int.Parse(standardData["Tag8"].ToString()) : 0,
                    OperatingMode = standardData.ContainsKey("Tag11") ? 
                        standardData["Tag11"].ToString() : null,
                    RecordTime = DateTime.Now
                };

                // 保存设备状态
                SaveDeviceStatus(deviceStatus);

                // 计算产量
                CalculateAndSaveProduction(deviceId, deviceStatus);

                // 记录原始采集数据
                LogRawCollectionData(deviceId, rawData, true);

                // 更新设备最后采集时间
                UpdateDeviceLastCollectionTime(deviceId);
            }
            catch (Exception ex)
            {
                // 记录错误信息
                LogRawCollectionData(deviceId, rawData, false, ex.Message);
                throw;
            }
        }

        private CNCBrandTemplate GetDeviceTemplate(int deviceId)
        {
            // 这里需要根据实际业务逻辑获取设备模板
            // 简化实现，实际应该从数据库查询
            return null;
        }

        private void SaveDeviceStatus(DeviceStatus status)
        {
            // 这里应该使用相应的仓库保存设备状态
            // 简化实现
        }

        private void CalculateAndSaveProduction(int deviceId, DeviceStatus currentStatus)
        {
            var today = DateTime.Today;
            var lastStatus = GetLastStatusForProductionCalculation(deviceId, today);

            if (lastStatus != null)
            {
                // 计算产量差
                var quantity = ProductionCalculator.CalculateProduction(
                    ConvertToDeviceCurrentStatus(currentStatus), 
                    ConvertToDeviceCurrentStatus(lastStatus));

                if (quantity > 0)
                {
                    // 创建生产记录
                    var productionRecord = new ProductionRecord
                    {
                        DeviceId = deviceId,
                        NCProgram = currentStatus.NCProgram,
                        ProductionDate = today,
                        Quantity = quantity,
                        QualityRate = 100, // 默认100%，实际可以根据数据计算
                        StartTime = lastStatus.RecordTime,
                        EndTime = currentStatus.RecordTime,
                        CreatedAt = DateTime.Now
                    };

                    _productionRepository.CreateProductionRecord(productionRecord);

                    // 更新程序产量汇总
                    UpdateProgramProductionSummary(deviceId, currentStatus.NCProgram, today, quantity);
                }
            }
        }

        private DeviceStatus GetLastStatusForProductionCalculation(int deviceId, DateTime date)
        {
            // 获取指定日期前的最后一个状态记录
            return _logContext.CollectionHistory
                .Where(ch => ch.DeviceId == deviceId && ch.CollectionTime < date)
                .OrderByDescending(ch => ch.CollectionTime)
                .FirstOrDefault()
                ?.ToDeviceStatus(); // 需要实现转换方法
        }

        private DeviceCurrentStatus ConvertToDeviceCurrentStatus(DeviceStatus status)
        {
            return new DeviceCurrentStatus
            {
                DeviceId = status.DeviceId,
                NCProgram = status.NCProgram,
                CumulativeCount = status.CumulativeCount,
                RecordTime = status.RecordTime
            };
        }

        private void UpdateProgramProductionSummary(int deviceId, string ncProgram, DateTime date, int quantity)
        {
            var summary = _productionRepository.GetProgramProductionSummary(deviceId, date)
                .FirstOrDefault(s => s.NCProgram == ncProgram);

            if (summary != null)
            {
                summary.TotalQuantity += quantity;
                summary.ValidQuantity += quantity;
                _productionRepository.UpdateProgramProductionSummary(summary);
            }
            else
            {
                var newSummary = new ProgramProductionSummary
                {
                    DeviceId = deviceId,
                    NCProgram = ncProgram,
                    ProductionDate = date,
                    TotalQuantity = quantity,
                    ValidQuantity = quantity,
                    InvalidQuantity = 0,
                    QualityRate = 100
                };

                _productionRepository.CreateOrUpdateProgramProductionSummary(newSummary);
            }
        }

        private void LogRawCollectionData(int deviceId, Dictionary<string, object> rawData, bool isSuccess, string errorMessage = null)
        {
            var logData = new RawCollectionData
            {
                DeviceId = deviceId,
                RawJson = Newtonsoft.Json.JsonConvert.SerializeObject(rawData),
                IsSuccess = isSuccess,
                ErrorMessage = errorMessage,
                CollectionTime = DateTime.Now,
                CreatedAt = DateTime.Now
            };

            _logContext.RawCollectionData.Add(logData);
            _logContext.SaveChanges();
        }

        private void UpdateDeviceLastCollectionTime(int deviceId)
        {
            // 这里应该使用相应的仓库更新设备最后采集时间
            // 简化实现
        }
    }
}