using System;
using System.Linq;
using System.Collections.Generic;

namespace HydraulicSimulator.Models
{
    /// <summary>
    /// Tanque especial para descarga libre con cálculo de nivel dinámico
    /// </summary>
    public class DischargeTank : Element
    {
        public double Area { get; set; }              // m² - área del tanque
        public double CurrentVolume { get; set; }     // m³ - volumen actual
        public double MaxVolume { get; set; }         // m³ - volumen máximo
        public double MinVolume { get; set; }         // m³ - volumen mínimo
        public string TankId { get; set; }            // ID del tanque

        public DischargeTank(string tankId, double area, double initialVolume = 0, 
                           double maxVolume = double.MaxValue, double minVolume = 0)
        {
            TankId = tankId;
            Area = area;
            CurrentVolume = initialVolume;
            MaxVolume = maxVolume;
            MinVolume = minVolume;
        }

        /// <summary>
        /// Altura actual del líquido en el tanque
        /// </summary>
        public double CurrentHeight => CurrentVolume / Area;

        /// <summary>
        /// Presión hidrostática en el fondo del tanque
        /// </summary>
        public double BottomPressure(Fluid fluid) => fluid.Rho * 9.81 * CurrentHeight;

        /// <summary>
        /// Actualizar volumen basado en flujo neto
        /// </summary>
        public void UpdateVolume(double netFlowRate, double deltaTime)
        {
            double volumeChange = netFlowRate * deltaTime;
            CurrentVolume += volumeChange;
            
            // Limitar entre mínimo y máximo
            CurrentVolume = Math.Max(MinVolume, Math.Min(MaxVolume, CurrentVolume));
        }

        /// <summary>
        /// Para tanque de descarga, la caída de presión es mínima
        /// </summary>
        public override double Dp(double q, Fluid fluid)
        {
            // Caída de presión mínima para tanque de descarga
            return Math.Sign(q) * 100.0; // 100 Pa de pérdida nominal
        }

        public override double DdpDq(double q, Fluid fluid)
        {
            return 1e-6; // Derivada muy pequeña para estabilidad
        }

        /// <summary>
        /// Verificar si el tanque está desbordando
        /// </summary>
        public bool IsOverflowing => CurrentVolume >= MaxVolume;

        /// <summary>
        /// Verificar si el tanque está vacío
        /// </summary>
        public bool IsEmpty => CurrentVolume <= MinVolume;

        /// <summary>
        /// Porcentaje de llenado (0.0 - 1.0)
        /// </summary>
        public double FillPercentage => (CurrentVolume - MinVolume) / (MaxVolume - MinVolume);
    }
}
