"""Souhrn EV nabíjecího plánu pro notifikace (Discord webhook i bot).

Sdílené mezi telemetry_collector (zpráva po příjezdu) a discord_bot
(přestavba zprávy po akci tlačítkem).
"""

from __future__ import annotations

import logging
from zoneinfo import ZoneInfo

import asyncpg

logger = logging.getLogger(__name__)

_PRAGUE = ZoneInfo("Europe/Prague")


async def get_open_session(
    site_id: int, charger_code: str, conn: asyncpg.Connection
) -> asyncpg.Record | None:
    return await conn.fetchrow(
        """
        select es.id as session_id, es.soc_at_connect_pct, es.target_soc_pct,
               es.target_deadline, v.battery_capacity_kwh, v.name as vehicle_name,
               v.default_deadline_hour
        from ems.ev_session es
        join ems.asset_ev_charger c on c.id = es.charger_id
        left join ems.asset_vehicle v on v.id = es.vehicle_id
        where es.site_id = $1 and c.code = $2 and es.session_end is null
        order by es.id desc limit 1
        """,
        site_id,
        charger_code,
    )


async def build_ev_plan_summary(
    site_id: int, charger_code: str, conn: asyncpg.Connection
) -> str | None:
    """Markdown souhrn: stav baterie auta → cíl, deadline, nabíjecí okna z plánu."""
    row = await get_open_session(site_id, charger_code, conn)
    if row is None:
        return None
    ev_col = "ev1_setpoint_w" if charger_code.endswith("1") else "ev2_setpoint_w"
    slots = await conn.fetch(
        f"""
        select pi.interval_start, pi.{ev_col} as w, pi.effective_buy_price
        from ems.planning_interval pi
        join ems.planning_run pr on pr.id = pi.run_id
        where pr.site_id = $1 and pr.status = 'active'
          and coalesce(pi.{ev_col}, 0) > 0
        order by pi.interval_start
        """,
        site_id,
    )

    def _fmt(dt) -> str:
        return dt.astimezone(_PRAGUE).strftime("%H:%M")

    windows: list[str] = []
    kwh = 0.0
    prices: list[float] = []
    if slots:
        start = prev = slots[0]["interval_start"]
        for r in slots:
            ts = r["interval_start"]
            if (ts - prev).total_seconds() > 900:
                windows.append(f"{_fmt(start)}–{_fmt(prev)} (+15m)")
                start = ts
            prev = ts
            kwh += float(r["w"]) * 0.25 / 1000.0
            prices.append(float(r["effective_buy_price"] or 0))
        windows.append(f"{_fmt(start)}–{_fmt(prev)} (+15m)")

    soc = row["soc_at_connect_pct"]
    tgt = row["target_soc_pct"]
    cap = float(row["battery_capacity_kwh"] or 0)
    need = max(0.0, (float(tgt or 0) - float(soc or 0)) / 100.0 * cap)
    lines = [
        f"🔌 **{row['vehicle_name'] or charger_code} připojeno**",
        f"Baterie auta: **{soc if soc is not None else '?'} %** → cíl {tgt if tgt is not None else '?'} %"
        + (f" (~{need:.0f} kWh)" if need else ""),
    ]
    dl = row["target_deadline"]
    if dl is not None:
        lines.append(f"Deadline: {dl.astimezone(_PRAGUE).strftime('%a %d.%m. %H:%M')}")
    if windows:
        avg_p = sum(prices) / max(1, len(prices))
        lines.append(
            f"Plán nabíjení: {'; '.join(windows[:4])} — {kwh:.1f} kWh, ø {avg_p:.2f} Kč/kWh"
        )
    else:
        lines.append("Plán nabíjení: zatím žádné sloty (čeká na levné okno / PV)")
    return "\n".join(lines)


async def send_ev_arrival(site_id: int, charger_code: str, conn: asyncpg.Connection) -> None:
    """Pošle souhrn po příjezdu: přednostně bot s tlačítky, jinak webhook."""
    from services.notification_service import send_discord

    text = await build_ev_plan_summary(site_id, charger_code, conn)
    if text is None:
        return
    try:
        from services.discord_bot import post_ev_arrival

        row = await get_open_session(site_id, charger_code, conn)
        if row is not None and await post_ev_arrival(
            site_id, charger_code, int(row["session_id"]), text
        ):
            return
    except Exception:
        logger.exception("Discord bot post failed — fallback webhook")
    await send_discord(conn, site_id, text, level="info")
