using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;

namespace SmartAquaViewer.DataAnalysis
{
    [Table("water_quality")]
    public class WaterQualityVO
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        /// <summary>
        /// 측정 시각
        /// </summary>
        [Column("recorded_time")]
        public DateTime RecordedTime { get; set; }

        /// <summary>
        /// 저수조
        /// </summary>
        public WaterTank Tank { get; set; } = new();

        public List<WaterTank> Tanks { get; set; } = new();

        /// <summary>
        /// 여과 시스템
        /// </summary>
        public FilteringSystem Filtering { get; set; } = new();

        /// <summary>
        /// 살균 시스템
        /// </summary>
        public SterilizingSystem Sterilizing { get; set; } = new();

        /// <summary>
        /// 총 전력 소비 (킬로와트, kW)
        /// </summary>
        public double TotalEnergy { get; set; }

        /// <summary>
        /// 총 온실가스 배출량 (톤, tCO₂)
        /// </summary>
        public double TotalGreenhouseGas { get; set; }

        public WaterQualityVO() { }

        public WaterQualityVO(DateTime RecordedTime, WaterTank tank, FilteringSystem filtering, SterilizingSystem sterilizing)
        {
            this.RecordedTime = RecordedTime;
            Tank = tank;
            Filtering = filtering;
            Sterilizing = sterilizing;
        }

        /// <summary>
        /// 샘플 데이터 리스트 생성
        /// </summary>
        public static List<WaterQualityVO> GetSampleData(DateTime start, DateTime end, int totalRowsCount)
        {
            var list = new List<WaterQualityVO>();
            var rand = new Random();

            double CalculateTotalEnergy(WaterQualityVO vo)
            {
                return vo.Filtering.SandFilterEnergy +
                       vo.Filtering.CirculationPumpEnergy +
                       vo.Filtering.HeatPumpEnergy +
                       vo.Filtering.AirBlowerEnergy +
                       vo.Sterilizing.OzoneGeneratorEnergy +
                       vo.Sterilizing.UVSterilizerEnergy +
                       vo.Sterilizing.OzoneDissolverEnergy +
                       vo.Sterilizing.ExcessOzoneDestroyerEnergy;
            }

            double ConvertEnergyToGHG(double energy)
            {
                // 2024년 배출계수 (kgCO₂/kWh)
                const double EmissionFactor = 0.4747;
                return (energy * EmissionFactor);  // / 1000.0; // tCO₂
            }

            double CalculateTotalGreenhouseGas(WaterQualityVO vo)
            {
                return vo.Filtering.AirBlowerGreenhouseGas +
                       vo.Filtering.CirculationPumpGreenhouseGas +
                       vo.Filtering.HeatPumpGreenhouseGas +
                       vo.Filtering.SandFilterGreenhouseGas +
                       vo.Sterilizing.ExcessOzoneDestroyerGreenhouseGas +
                       vo.Sterilizing.OzoneDissolverGreenhouseGas +
                       vo.Sterilizing.OzoneGeneratorGreenhouseGas +
                       vo.Sterilizing.UVSterilizerGreenhouseGas;
            }

            if (totalRowsCount <= 0) return list;

            double totalSeconds;

            if (start == end)
            {
                totalSeconds = 24 * 60 * 60;
            }
            else
            {
                totalSeconds = (end - start).TotalSeconds;
                if (totalSeconds < 0) throw new ArgumentException("end 날짜는 start 날짜보다 같거나 커야 합니다.");
            }

            double stepSeconds = totalSeconds / totalRowsCount;

            for (int i = 0; i < totalRowsCount; i++)
            {
                DateTime ts = start.AddSeconds(stepSeconds * i);

                var vo = new WaterQualityVO
                {
                    RecordedTime = ts,
                    Tank = new WaterTank(
                        number: rand.Next(1, 4),
                        doValue: Math.Round(rand.NextDouble() * 5 + 5, 2),
                        ph: Math.Round(rand.NextDouble() * 2 + 6, 2),
                        orp: Math.Round(rand.NextDouble() * 200 + 100, 2),
                        temperature: Math.Round(rand.NextDouble() * 10 + 15, 2),
                        flowRate: Math.Round(rand.NextDouble() * 5 + 1, 2)
                    ),
                    Tanks = new List<WaterTank>()
                    {
                        new WaterTank(
                            number: 1,
                            doValue: Math.Round(rand.NextDouble() * 5 + 5, 2),
                            ph: Math.Round(rand.NextDouble() * 2 + 6, 2),
                            orp: Math.Round(rand.NextDouble() * 200 + 100, 2),
                            temperature: Math.Round(rand.NextDouble() * 10 + 15, 2),
                            flowRate: Math.Round(rand.NextDouble() * 5 + 1, 2)),
                        new WaterTank(
                            number: 2,
                            doValue: Math.Round(rand.NextDouble() * 5 + 5, 2),
                            ph: Math.Round(rand.NextDouble() * 2 + 6, 2),
                            orp: Math.Round(rand.NextDouble() * 200 + 100, 2),
                            temperature: Math.Round(rand.NextDouble() * 10 + 15, 2),
                            flowRate: Math.Round(rand.NextDouble() * 5 + 1, 2)),
                        new WaterTank(
                            number: 3,
                            doValue: Math.Round(rand.NextDouble() * 5 + 5, 2),
                            ph: Math.Round(rand.NextDouble() * 2 + 6, 2),
                            orp: Math.Round(rand.NextDouble() * 200 + 100, 2),
                            temperature: Math.Round(rand.NextDouble() * 10 + 15, 2),
                            flowRate: Math.Round(rand.NextDouble() * 5 + 1, 2)),
                    },
                    Filtering = new FilteringSystem(
                        sandFilterPower: rand.Next(0, 2) == 1,
                        sandFilterEnergy: Math.Round(rand.NextDouble() * 2 + 0.5, 2),
                        sandFilterGreenhouseGas: 0, // 추후 계산
                        sumpPH: Math.Round(rand.NextDouble() * 2 + 6, 2),
                        sumpORP: Math.Round(rand.NextDouble() * 200 + 100, 2),
                        sumpWaterLevel: Math.Round(rand.NextDouble() * 2 + 1, 2),
                        sumpFlowRate: Math.Round(rand.NextDouble() * 5 + 1, 2),
                        sumpTemperature: Math.Round(rand.NextDouble() * 10 + 15, 2),
                        circulationPumpPower: rand.Next(0, 2) == 1,
                        circulationPumpEnergy: Math.Round(rand.NextDouble() * 2 + 0.5, 2),
                        circulationPumpGreenhouseGas: 0, // 추후 계산
                        inverterControllerStatus: rand.Next(0, 2) == 1 ? "Normal" : "Error",
                        flowRate: Math.Round(rand.NextDouble() * 5 + 1, 2),
                        heatPumpPower: rand.Next(0, 2) == 1,
                        heatPumpTemperature: Math.Round(rand.NextDouble() * 10 + 15, 2),
                        heatPumpEnergy: Math.Round(rand.NextDouble() * 2 + 0.5, 2),
                        heatPumpGreenhouseGas: 0, // 추후 계산
                        airBlowerPower: rand.Next(0, 2) == 1,
                        airBlowerEnergy: Math.Round(rand.NextDouble() * 2 + 0.5, 2),
                        airBlowerGreenhouseGas: 0  // 추후 계산
                    ),
                    Sterilizing = new SterilizingSystem(
                        ozoneGeneratorPower: rand.Next(0, 2) == 1,
                        ozoneGeneratorEnergy: Math.Round(rand.NextDouble() * 2 + 0.5, 2),
                        ozoneGeneratorGreenhouseGas: 0, // 추후 계산
                        uvSterilizerId: "UV" + rand.Next(1, 100),
                        uvSterilizerPower: rand.Next(0, 2) == 1,
                        uvSterilizerEnergy: Math.Round(rand.NextDouble() * 2 + 0.5, 2),
                        uvSterilizerGreenhouseGas: 0, // 추후 계산
                        ozoneDissolverPower: rand.Next(0, 2) == 1,
                        ozoneDissolverPressure: Math.Round(rand.NextDouble() * 100 + 50, 2),
                        ozoneDissolverEnergy: Math.Round(rand.NextDouble() * 2 + 0.5, 2),
                        ozoneDissolverGreenhouseGas: 0, // 추후 계산
                        excessOzoneDestroyerPower: rand.Next(0, 2) == 1,
                        excessOzoneDestroyerEnergy: Math.Round(rand.NextDouble() * 2 + 0.5, 2),
                        excessOzoneDestroyerGreenhouseGas: 0  // 추후 계산
                    ),
                };
                vo.TotalEnergy = CalculateTotalEnergy(vo);
                vo.Filtering.SandFilterGreenhouseGas = ConvertEnergyToGHG(vo.Filtering.SandFilterEnergy);
                vo.Filtering.CirculationPumpGreenhouseGas = ConvertEnergyToGHG(vo.Filtering.CirculationPumpEnergy);
                vo.Filtering.HeatPumpGreenhouseGas = ConvertEnergyToGHG(vo.Filtering.HeatPumpEnergy);
                vo.Filtering.AirBlowerGreenhouseGas = ConvertEnergyToGHG(vo.Filtering.AirBlowerEnergy);
                vo.Sterilizing.OzoneGeneratorGreenhouseGas = ConvertEnergyToGHG(vo.Sterilizing.OzoneGeneratorEnergy);
                vo.Sterilizing.UVSterilizerGreenhouseGas = ConvertEnergyToGHG(vo.Sterilizing.UVSterilizerEnergy);
                vo.Sterilizing.OzoneDissolverGreenhouseGas = ConvertEnergyToGHG(vo.Sterilizing.OzoneDissolverEnergy);
                vo.Sterilizing.ExcessOzoneDestroyerGreenhouseGas = ConvertEnergyToGHG(vo.Sterilizing.ExcessOzoneDestroyerEnergy);
                vo.TotalGreenhouseGas = CalculateTotalGreenhouseGas(vo);

                list.Add(vo);
            }

            return list;
        }
    }

    [Owned]
    public class WaterTank
    {
        /// <summary>
        /// 저수조 번호
        /// </summary>
        [Column("tank_number")]
        public int Number { get; set; }

        /// <summary>
        /// Dissolved Oxygen (mg/L)
        /// </summary>
        [Column("tank_do_value")]
        public double DOValue { get; set; }
        /// <summary>
        /// pH (산도)
        /// </summary>
        [Column("tank_ph")]
        public double PH { get; set; }
        /// <summary>
        /// 산화환원전위 (mV)
        /// </summary>
        [Column("tank_orp")]
        public double ORP { get; set; }
        /// <summary>
        /// 수온 (°C)
        /// </summary>
        [Column("tank_temperature")]
        public double Temperature { get; set; }
        /// <summary>
        /// 유량 (m³/s)
        /// </summary>
        [Column("tank_flow_rate")]
        public double FlowRate { get; set; }

        public WaterTank() { }

        public WaterTank(int number, double doValue, double ph, double orp, double temperature, double flowRate)
        {
            Number = number;
            DOValue = doValue;
            PH = ph;
            ORP = orp;
            Temperature = temperature;
            FlowRate = flowRate;
        }
    }

    [Owned]
    public class FilteringSystem
    {
        /// <summary>
        /// 모래여과기 전원 (true: ON, false: OFF)
        /// </summary>
        [Column("filter_sand_filter_power")]
        public bool SandFilterPower { get; set; }

        /// <summary>
        /// 모래여과기 전력 (kW)
        /// </summary>
        [Column("filter_sand_filter_energy")]
        public double SandFilterEnergy { get; set; }

        /// <summary>
        /// 모래여과기 온실가스 (tCO₂)
        /// </summary>
        [Column("filter_sand_filter_greenhouse_gas")]
        public double SandFilterGreenhouseGas { get; set; }

        /// <summary>
        /// 섬프탱크 pH (산도)
        /// </summary>
        [Column("filter_sump_ph")]
        public double SumpPH { get; set; }

        /// <summary>
        /// 섬프탱크 산화환원전위 (mV)
        /// </summary>
        [Column("filter_sump_orp")]
        public double SumpORP { get; set; }

        /// <summary>
        /// 섬프탱크 수위 (m)
        /// </summary>
        [Column("filter_sump_water_level")]
        public double SumpWaterLevel { get; set; }

        /// <summary>
        /// 섬프탱크 유량 (m³/s)
        /// </summary>
        [Column("filter_sump_flow_rate")]
        public double SumpFlowRate { get; set; }

        /// <summary>
        /// 섬프탱크 수온 (°C)
        /// </summary>
        [Column("filter_sump_temperature")]
        public double SumpTemperature { get; set; }

        /// <summary>
        /// 순환펌프 전원 (true: ON, false: OFF)
        /// </summary>
        [Column("filter_circulation_pump_power")]
        public bool CirculationPumpPower { get; set; }

        /// <summary>
        /// 순환펌프 전력 (kW)
        /// </summary>
        [Column("filter_circulation_pump_energy")]
        public double CirculationPumpEnergy { get; set; }

        /// <summary>
        /// 순환펌프 온실가스 (tCO₂)
        /// </summary>
        [Column("filter_circulation_pump_greenhouse_gas")]
        public double CirculationPumpGreenhouseGas { get; set; }

        /// <summary>
        /// 인버터 제어기 상태
        /// </summary>
        [Column("filter_inverter_controller_status")]
        public string? InverterControllerStatus { get; set; }

        /// <summary>
        /// 순환펌프 유량 (m³/s)
        /// </summary>
        [Column("filter_flow_rate")]
        public double FlowRate { get; set; }

        /// <summary>
        /// 히트펌프 전원 (true: ON, false: OFF)
        /// </summary>
        [Column("filter_heat_pump_power")]
        public bool HeatPumpPower { get; set; }

        /// <summary>
        /// 히트펌프 온도 (°C)
        /// </summary>
        [Column("filter_heat_pump_temperature")]
        public double HeatPumpTemperature { get; set; }

        /// <summary>
        /// 히트펌프 전력 (kW)
        /// </summary>
        [Column("filter_heat_pump_energy")]
        public double HeatPumpEnergy { get; set; }

        /// <summary>
        /// 히트펌프 온실가스 (tCO₂)
        /// </summary>
        [Column("filter_heat_pump_greenhouse_gas")]
        public double HeatPumpGreenhouseGas { get; set; }

        /// <summary>
        /// 에어브로와 전원 (true: ON, false: OFF)
        /// </summary>
        [Column("filter_air_blower_power")]
        public bool AirBlowerPower { get; set; }

        /// <summary>
        /// 에어브로와 전력 (kW)
        /// </summary>
        [Column("filter_air_blower_energy")]
        public double AirBlowerEnergy { get; set; }

        /// <summary>
        /// 에어브로와 온실가스 (tCO₂)
        /// </summary>
        [Column("filter_air_blower_greenhouse_gas")]
        public double AirBlowerGreenhouseGas { get; set; }

        public FilteringSystem() { }

        public FilteringSystem(
            bool sandFilterPower, double sandFilterEnergy, double sandFilterGreenhouseGas,
            double sumpPH, double sumpORP, double sumpWaterLevel, double sumpFlowRate, double sumpTemperature,
            bool circulationPumpPower, double circulationPumpEnergy, double circulationPumpGreenhouseGas, string? inverterControllerStatus, double flowRate,
            bool heatPumpPower, double heatPumpTemperature, double heatPumpEnergy, double heatPumpGreenhouseGas,
            bool airBlowerPower, double airBlowerEnergy, double airBlowerGreenhouseGas)
        {
            SandFilterPower = sandFilterPower;
            SandFilterEnergy = sandFilterEnergy;
            SandFilterGreenhouseGas = sandFilterGreenhouseGas;
            SumpPH = sumpPH;
            SumpORP = sumpORP;
            SumpWaterLevel = sumpWaterLevel;
            SumpFlowRate = sumpFlowRate;
            SumpTemperature = sumpTemperature;
            CirculationPumpPower = circulationPumpPower;
            CirculationPumpEnergy = circulationPumpEnergy;
            CirculationPumpGreenhouseGas = circulationPumpGreenhouseGas;
            InverterControllerStatus = inverterControllerStatus;
            FlowRate = flowRate;
            HeatPumpPower = heatPumpPower;
            HeatPumpTemperature = heatPumpTemperature;
            HeatPumpEnergy = heatPumpEnergy;
            HeatPumpGreenhouseGas = heatPumpGreenhouseGas;
            AirBlowerPower = airBlowerPower;
            AirBlowerEnergy = airBlowerEnergy;
            AirBlowerGreenhouseGas = airBlowerGreenhouseGas;
        }
    }

    [Owned]
    public class SterilizingSystem
    {
        /// <summary>
        /// 오존 발생기 전원 (true: ON, false: OFF)
        /// </summary>
        [Column("ster_ozone_generator_power")]
        public bool OzoneGeneratorPower { get; set; }

        /// <summary>
        /// 오존 발생기 전력 (kW)
        /// </summary>
        [Column("ster_ozone_generator_energy")]
        public double OzoneGeneratorEnergy { get; set; }

        /// <summary>
        /// 오존 발생기 온실가스 (tCO₂)
        /// </summary>
        [Column("ster_ozone_generator_greenhouse_gas")]
        public double OzoneGeneratorGreenhouseGas { get; set; }

        /// <summary>
        /// 자외선 살균기 ID
        /// </summary>
        [Column("ster_uv_sterilizer_id")]
        public string UVSterilizerId { get; set; }

        /// <summary>
        /// 자외선 살균기 전원 (true: ON, false: OFF)
        /// </summary>
        [Column("ster_uv_sterilizer_power")]
        public bool UVSterilizerPower { get; set; }

        /// <summary>
        /// 자외선 살균기 전력 (kW)
        /// </summary>
        [Column("ster_uv_sterilizer_energy")]
        public double UVSterilizerEnergy { get; set; }

        /// <summary>
        /// 자외선 살균기 온실가스 (tCO₂)
        /// </summary>
        [Column("ster_uv_sterilizer_greenhouse_gas")]
        public double UVSterilizerGreenhouseGas { get; set; }

        /// <summary>
        /// 오존용해장치 전원 (true: ON, false: OFF)
        /// </summary>
        [Column("ster_ozone_dissolver_power")]
        public bool OzoneDissolverPower { get; set; }

        /// <summary>
        /// 오존용해장치 압력 (kPa)
        /// </summary>
        [Column("ster_ozone_dissolver_pressure")]
        public double OzoneDissolverPressure { get; set; }

        /// <summary>
        /// 오존용해장치 전력 (kW)
        /// </summary>
        [Column("ster_ozone_dissolver_energy")]
        public double OzoneDissolverEnergy { get; set; }

        /// <summary>
        /// 오존용해장치 온실가스 (tCO₂)
        /// </summary>
        [Column("ster_ozone_dissolver_greenhouse_gas")]
        public double OzoneDissolverGreenhouseGas { get; set; }

        /// <summary>
        /// 배오존장치 전원 (true: ON, false: OFF)
        /// </summary>
        [Column("ster_excess_ozone_destroyer_power")]
        public bool ExcessOzoneDestroyerPower { get; set; }

        /// <summary>
        /// 배오존장치 전력 (kW)
        /// </summary>
        [Column("ster_excess_ozone_destroyer_energy")]
        public double ExcessOzoneDestroyerEnergy { get; set; }

        /// <summary>
        /// 배오존장치 온실가스 (tCO₂)
        /// </summary>
        [Column("ster_excess_ozone_destroyer_greenhouse_gas")]
        public double ExcessOzoneDestroyerGreenhouseGas { get; set; }

        public SterilizingSystem() { }

        public SterilizingSystem(
            bool ozoneGeneratorPower, double ozoneGeneratorEnergy, double ozoneGeneratorGreenhouseGas,
            string uvSterilizerId, bool uvSterilizerPower, double uvSterilizerEnergy, double uvSterilizerGreenhouseGas,
            bool ozoneDissolverPower, double ozoneDissolverPressure, double ozoneDissolverEnergy, double ozoneDissolverGreenhouseGas,
            bool excessOzoneDestroyerPower, double excessOzoneDestroyerEnergy, double excessOzoneDestroyerGreenhouseGas)
        {
            OzoneGeneratorPower = ozoneGeneratorPower;
            OzoneGeneratorEnergy = ozoneGeneratorEnergy;
            OzoneGeneratorGreenhouseGas = ozoneGeneratorGreenhouseGas;
            UVSterilizerId = uvSterilizerId;
            UVSterilizerPower = uvSterilizerPower;
            UVSterilizerEnergy = uvSterilizerEnergy;
            UVSterilizerGreenhouseGas = uvSterilizerGreenhouseGas;
            OzoneDissolverPower = ozoneDissolverPower;
            OzoneDissolverPressure = ozoneDissolverPressure;
            OzoneDissolverEnergy = ozoneDissolverEnergy;
            OzoneDissolverGreenhouseGas = ozoneDissolverGreenhouseGas;
            ExcessOzoneDestroyerPower = excessOzoneDestroyerPower;
            ExcessOzoneDestroyerEnergy = excessOzoneDestroyerEnergy;
            ExcessOzoneDestroyerGreenhouseGas = excessOzoneDestroyerGreenhouseGas;
        }
    }
}
