-- =============================================================
-- R__005_fn_cop_estimate.sql
-- EMS Platform – odhad COP tepelného čerpadla dle venkovní teploty
-- Repeatable migration
-- =============================================================

CREATE OR REPLACE FUNCTION ems.fn_cop_estimate(
    p_heat_pump_id   INT,
    p_outdoor_temp_c NUMERIC
)
RETURNS NUMERIC(4,2)
LANGUAGE plpgsql
STABLE
AS $$
DECLARE
    v_cop_rated          NUMERIC;
    v_cop_ref_temp       NUMERIC;
    v_cop_estimated      NUMERIC;
BEGIN
    -- Načíst referenční COP a teplotu z konfigurace čerpadla
    SELECT cop_rated, cop_temp_reference_c
    INTO v_cop_rated, v_cop_ref_temp
    FROM ems.asset_heat_pump
    WHERE id = p_heat_pump_id;

    IF v_cop_rated IS NULL OR v_cop_ref_temp IS NULL THEN
        -- Fallback: obecný odhad pro vzduch-voda TČ bez konfigurace
        -- Zdroj: přibližná lineární závislost COP na venkovní teplotě
        -- COP ≈ 2.0 při -10°C, COP ≈ 4.5 při +15°C
        v_cop_estimated := 2.0 + (p_outdoor_temp_c + 10.0) * (4.5 - 2.0) / 25.0;
    ELSE
        -- Lineární interpolace od referenčního bodu
        -- COP klesá přibližně o 0.10 na každý stupeň poklesu venkovní teploty
        -- Toto je zjednodušený model – zpřesnit dle skutečných dat z tepelky
        v_cop_estimated := v_cop_rated + (p_outdoor_temp_c - v_cop_ref_temp) * 0.10;
    END IF;

    -- Omezit na rozumné hodnoty (COP vzduch-voda reálně 1.5–6.0)
    v_cop_estimated := GREATEST(1.5, LEAST(6.0, v_cop_estimated));

    RETURN ROUND(v_cop_estimated, 2);
END;
$$;

COMMENT ON FUNCTION ems.fn_cop_estimate(INT, NUMERIC) IS
'Odhadne COP tepelného čerpadla pro danou venkovní teplotu.
Používá lineární model od referenčního bodu (cop_rated při cop_temp_reference_c).
Výstup slouží k rozhodnutí zda je výhodné spustit TČ v daném intervalu.
Přesnost modelu zlepšit kalibrací na historická data (cop_actual z telemetrie).
Výsledek omezen na rozsah 1.5–6.0.';

-- ------------------------------------------------------------

CREATE OR REPLACE FUNCTION ems.fn_heat_pump_cost_per_kwh_heat(
    p_heat_pump_id   INT,
    p_outdoor_temp_c NUMERIC,
    p_buy_price_czk_kwh NUMERIC
)
RETURNS NUMERIC(8,4)
LANGUAGE sql
STABLE
AS $$
    -- Cena za 1 kWh tepla = cena elektřiny / COP
    -- Čím vyšší COP, tím levnější teplo
    SELECT ROUND(
        p_buy_price_czk_kwh / NULLIF(ems.fn_cop_estimate(p_heat_pump_id, p_outdoor_temp_c), 0),
        4
    );
$$;

COMMENT ON FUNCTION ems.fn_heat_pump_cost_per_kwh_heat(INT, NUMERIC, NUMERIC) IS
'Vypočte efektivní cenu za 1 kWh dodaného tepla v Kč.
Vstup: ID tepelného čerpadla, venkovní teplota, nákupní cena elektřiny.
Výstup slouží k porovnání výhodnosti ohřevu v různých časových intervalech.
Nižší hodnota = výhodnější čas pro provoz TČ.';

-- ------------------------------------------------------------

CREATE OR REPLACE FUNCTION ems.fn_heat_pump_should_run(
    p_heat_pump_id      INT,
    p_interval_start    TIMESTAMPTZ,
    p_outdoor_temp_c    NUMERIC,
    p_tuv_tank_temp_c   NUMERIC,
    p_buy_price_czk_kwh NUMERIC,
    p_max_cost_threshold NUMERIC DEFAULT 3.0  -- Kč/kWh tepla – maximální akceptovatelná cena
)
RETURNS BOOLEAN
LANGUAGE plpgsql
STABLE
AS $$
DECLARE
    v_hp            ems.asset_heat_pump%ROWTYPE;
    v_cost_per_kwh  NUMERIC;
    v_override      BOOLEAN;
BEGIN
    SELECT * INTO v_hp FROM ems.asset_heat_pump WHERE id = p_heat_pump_id;

    -- Kontrola override (blokování TČ)
    SELECT EXISTS(
        SELECT 1 FROM ems.site_override
        WHERE site_id = v_hp.site_id
          AND override_type = 'block_heat_pump'
          AND valid_from <= p_interval_start
          AND (valid_to IS NULL OR valid_to > p_interval_start)
    ) INTO v_override;

    IF v_override THEN
        RETURN false;
    END IF;

    -- Povinný ohřev: teplota pod minimem
    IF p_tuv_tank_temp_c IS NOT NULL AND p_tuv_tank_temp_c < v_hp.tuv_min_temp_c THEN
        RETURN true;
    END IF;

    -- Zásobník je plný
    IF p_tuv_tank_temp_c IS NOT NULL AND p_tuv_tank_temp_c >= v_hp.tuv_max_temp_c THEN
        RETURN false;
    END IF;

    -- Ekonomické rozhodnutí: spustit pokud cena tepla je pod prahem
    v_cost_per_kwh := ems.fn_heat_pump_cost_per_kwh_heat(
        p_heat_pump_id, p_outdoor_temp_c, p_buy_price_czk_kwh
    );

    RETURN v_cost_per_kwh <= p_max_cost_threshold;
END;
$$;

COMMENT ON FUNCTION ems.fn_heat_pump_should_run(INT, TIMESTAMPTZ, NUMERIC, NUMERIC, NUMERIC, NUMERIC) IS
'Rozhodne zda má tepelné čerpadlo v daném intervalu běžet.
Logika priorit:
1. Pokud existuje override block_heat_pump → false.
2. Pokud teplota zásobníku pod tuv_min_temp_c → true (povinný ohřev).
3. Pokud zásobník nad tuv_max_temp_c → false.
4. Jinak ekonomické rozhodnutí: spustit pokud cena tepla ≤ p_max_cost_threshold Kč/kWh.
Výhodné časy jsou přes poledne v chladných měsících (vyšší venkovní teplota = lepší COP).';
