#include "PhiHumidity.h"

/*
 ===========================================================
    PhiHumidity.cpp - Temperature & Humidity
 ===========================================================
*/

PhiHumidity::PhiHumidity()
: _temperature(0),
  _humidity(0),
  _deltaTemp(0),
  _deltaHumidity(0),
  _baselineTemp(0),
  _baselineHum(0),
  _calibrated(false),
  _lpfTemp(0.05f),   // Slow smoothing (slow sensor)
  _lpfHum(0.1f)      // Humidity slightly faster
{}

bool PhiHumidity::begin() {
    // HS300x.begin() must have been called before in setup()
    
    Serial.println("✓ PhiHumidity initialized (HS3003)");
    return true;
}

void PhiHumidity::calibrateBaseline(uint16_t samples) {
    Serial.print("🌡️  Calibrating temp/humidity baseline (");
    Serial.print(samples);
    Serial.println(" samples)...");

    float sumTemp = 0;
    float sumHum = 0;
    uint16_t validSamples = 0;

    for (uint16_t i = 0; i < samples; i++) {
        float t = HS300x.readTemperature();
        float h = HS300x.readHumidity();
        
        // Verify valid readings
        if (!isnan(t) && !isnan(h) && t > -40 && t < 85 && h >= 0 && h <= 100) {
            sumTemp += t;
            sumHum += h;
            validSamples++;
        }
        delay(100);  // HS3003 slow, 10 Hz max
    }

    if (validSamples > 0) {
        _baselineTemp = sumTemp / validSamples;
        _baselineHum = sumHum / validSamples;
        _calibrated = true;

        Serial.print("   Baseline Temp: ");
        Serial.print(_baselineTemp, 2);
        Serial.println(" °C");
        
        Serial.print("   Baseline RH:   ");
        Serial.print(_baselineHum, 1);
        Serial.println(" %");
        
        Serial.println("   ✅ Calibration OK");
    } else {
        Serial.println("   ❌ Calibration failed (HS3003 not available)");
    }
}

void PhiHumidity::update() {
    float t = HS300x.readTemperature();
    float h = HS300x.readHumidity();
    
    // Verify valid values
    if (isnan(t) || isnan(h))
        return;
    
    if (t < -40 || t > 85)  // Out of sensor range
        return;
    
    if (h < 0 || h > 100)   // Invalid humidity
        return;

    // Exponential smoothing
    _temperature = _lpfTemp.step(t);
    _humidity = _lpfHum.step(h);

    // Delta vs baseline
    if (_calibrated) {
        _deltaTemp = _temperature - _baselineTemp;
        _deltaHumidity = _humidity - _baselineHum;
    } else {
        _deltaTemp = 0;
        _deltaHumidity = 0;
    }
}

float PhiHumidity::heatIndex() const {
    // Heat Index - Simplified Steadman formula
    // Valid for T > 20°C and RH > 40%
    
    if (_temperature < 20 || _humidity < 40)
        return _temperature;  // Not applicable
    
    float T = _temperature;
    float R = _humidity;
    
    // Simplified formula
    float HI = -8.78469475556 
             + 1.61139411 * T 
             + 2.33854883889 * R
             - 0.14611605 * T * R
             - 0.012308094 * T * T
             - 0.0164248277778 * R * R
             + 0.002211732 * T * T * R
             + 0.00072546 * T * R * R
             - 0.000003582 * T * T * R * R;
    
    return HI;
}

float PhiHumidity::dewPoint() const {
    // Dew Point - Magnus-Tetens formula
    // Temperature at which relative humidity reaches 100%
    
    float T = _temperature;
    float RH = _humidity;
    
    if (RH <= 0)
        return T;
    
    float a = 17.27;
    float b = 237.7;
    
    float alpha = ((a * T) / (b + T)) + log(RH / 100.0);
    float Td = (b * alpha) / (a - alpha);
    
    return Td;
}

bool PhiHumidity::isComfortable() const {
    // ASHRAE comfort zone (simplified)
    // Temperature: 18-24°C
    // Humidity: 30-60%
    
    bool tempOK = (_temperature >= 18.0 && _temperature <= 24.0);
    bool humOK = (_humidity >= 30.0 && _humidity <= 60.0);
    
    return (tempOK && humOK);
}