import os
import re
import sqlite3
import requests
from bs4 import BeautifulSoup
from datetime import datetime, timedelta
import pytz


# Шлях до локальної бази даних в папці бота
DB_PATH = os.path.join(os.path.dirname(__file__), "river_history.db")

def init_db():
    """Створює таблицю для збереження історії температур, якщо її немає"""
    with sqlite3.connect(DB_PATH) as conn:
        cursor = conn.cursor()
        cursor.execute("""
            CREATE TABLE IF NOT EXISTS water_temperatures (
                date_key TEXT PRIMARY KEY,
                temperature REAL
            )
        """)
        conn.commit()

# Ініціалізуємо БД при завантаженні скрипта
init_db()

# Словник для зіставлення місяців для парсера температури води
UKR_MONTHS_SHORT = {
    1: "СІЧ", 2: "ЛЮТ", 3: "БЕР", 4: "КВІ", 5: "ТРА", 6: "ЧЕР",
    7: "ЛИП", 8: "СЕР", 9: "ВЕР", 10: "ЖОФ", 11: "ЛИС", 12: "ГРУ"
}


def format_to_ukr_date(date_str):
    """Перетворює '09.07.2026' на '9 липня'"""
    try:
        dt = datetime.strptime(date_str, "%d.%m.%Y")
        months = {
            1: "січня", 2: "лютого", 3: "березня", 4: "квітня", 
            5: "травня", 6: "червня", 7: "липня", 8: "серпня", 
            9: "вересня", 10: "жовтня", 11: "листопада", 12: "грудня"
        }
        return f"{dt.day} {months[dt.month]}"
    except:
        return date_str


def get_all_seatemperatures_dict():
 
    kyiv_tz = pytz.timezone("Europe/Kyiv")
    now = datetime.now(kyiv_tz)
    today_key = now.strftime("%d.%m.%Y")
    temps_dict = {}


    try:
        with sqlite3.connect(DB_PATH) as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT date_key, temperature FROM water_temperatures")
            for row in cursor.fetchall():
                temps_dict[row[0]] = row[1]
                
    except Exception as e:
        pass # Щоб не мусорити в консоль

    # 2. Якщо сьогоднішній день вже є в базі, не дьоргаємо сайт взагалі!
    if today_key in temps_dict:
        return temps_dict

    # 3. Якщо сьогоднішніх даних немає — йдемо на сайт оновлювати історію
    url = "https://ukr.seatemperature.net/richki/water-temp-in-cheremosh"
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
        "Accept-Language": "uk-UA,uk;q=0.9,en-US;q=0.8,en;q=0.7",
        "Cookie": "typdisplay=1; cntgo=UA"
    }
    
    try:
        res = requests.get(url, headers=headers, timeout=10)
        if res.status_code == 200:
            res.encoding = 'utf-8'
            soup = BeautifulSoup(res.text, 'html.parser')
            table = soup.find('table', class_='temp-table4')
            if table:
                rows = table.find('tbody').find_all('tr') if table.find('tbody') else table.find_all('tr')
                
                inv_months = {
                    "СІЧ": 1, "ЛЮТ": 2, "БЕР": 3, "КВІ": 4, "ТРА": 5, "ЧЕР": 6,
                    "ЛИП": 7, "СЕР": 8, "ВЕР": 9, "ЖОФ": 10, "ЛИС": 11, "ГРУ": 12
                }
                
                new_records = []
                for row in rows:
                    cols = row.find_all('td')
                    if len(cols) >= 2:
                        date_cell = cols[0].text.strip().replace('\xa0', ' ').upper()
                        temp_text = cols[1].text.strip()
                        
                        cleaned_temp = re.sub(r'[^\d.]', '', temp_text)
                        if not cleaned_temp: 
                            continue
                        t_float = float(cleaned_temp)
                        
                        parts = date_cell.split()
                        if len(parts) >= 2:
                            m_str = parts[0][:3]
                            d_str = parts[1]
                            if m_str in inv_months:
                                m_num = inv_months[m_str]
                                d_num = int(d_str)
                                date_key = f"{d_num:02d}.{m_num:02d}.{now.year}"
                                
                                temps_dict[date_key] = t_float
                                new_records.append((date_key, t_float))
                
                # Записуємо нові унікальні дні в базу даних, щоб більше їх не парсити
                if new_records:
                    with sqlite3.connect(DB_PATH) as conn:
                        cursor = conn.cursor()
                        cursor.executemany("""
                            INSERT OR REPLACE INTO water_temperatures (date_key, temperature)
                            VALUES (?, ?)
                        """, new_records)
                        conn.commit()
                        
    except Exception:
        pass # Захист від падінь та зайвого спаму в логи сервера
        
    return temps_dict


def get_water_temperature():
    """Парсить базову температуру води в Черемоші з урахуванням кук та правильного формату дат"""
    url = "https://ukr.seatemperature.net/richki/water-temp-in-cheremosh"
    
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
        "Accept-Language": "uk-UA,uk;q=0.9,en-US;q=0.8,en;q=0.7",
        "Cache-Control": "no-cache",
        "Cookie": "typdisplay=1; cntgo=UA",
        "Pragma": "no-cache",
        "Upgrade-Insecure-Requests": "1"
    }
    
    try:
        res = requests.get(url, headers=headers, timeout=10)
        if res.status_code != 200:
            return None
            
        # ПРИМУСОВО ВИСТАВЛЯЄМО ПРАВИЛЬНЕ КОДУВАННЯ, ЩОБ НЕ БУЛО КРАКОЗЯБР (Â)
        res.encoding = 'utf-8'
            
        soup = BeautifulSoup(res.text, 'html.parser')
        table = soup.find('table', class_='temp-table4')
        if not table:
            return None
            
        now = datetime.now()
        day_str = str(now.day) # Без нуля попереду (наприклад: "7")
        month_str = UKR_MONTHS_SHORT.get(now.month, "")
        
        # Точний маркер пошуку: наприклад "ЛИП 7"
        target_date_label = f"{month_str} {day_str}".upper()
        
        rows = table.find('tbody').find_all('tr') if table.find('tbody') else table.find_all('tr')
        
        import re

        def clean_temp_value(text):
            """Допоміжна функція для очищення тексту від градусів та сміття типу Â"""
            if not text or text == "—":
                return None
            # Залишаємо тільки цифри та крапку
            cleaned = re.sub(r'[^\d.]', '', text)
            try:
                return float(cleaned) if cleaned else None
            except ValueError:
                return None
        
        for row in rows:
            row_style = row.get('style', '')
            cols = row.find_all('td')
            
            if len(cols) >= 2:
                date_cell = cols[0].text.strip().replace('\xa0', ' ').upper()
                
                # Спосіб 1: Якщо рядок підсвічений сайтом (сьогодня) або дата точно збіглася
                if "91DBFF" in row_style or target_date_label in date_cell:
                    val = clean_temp_value(cols[1].text)
                    if val is not None:
                        return val
                        
        # Спосіб 2 (Резервний): Йдемо з кінця таблиці вгору і шукаємо ОСТАННЄ РЕАЛЬНЕ фактичне значення
        for row in reversed(rows):
            cols = row.find_all('td')
            if len(cols) >= 2:
                val = clean_temp_value(cols[1].text)
                if val is not None:
                    return val
                    
    except Exception as e:
        print(f"Помилка парсингу температури води з сайту: {e}")
    return None



def get_fallback_water_temp(target_date_str=None):
    """Розумний фолбек: вираховує температуру гірської річки на основі погоди Попельників"""
    try:
        is_tomorrow = False
        if target_date_str:
            try:
                dt = datetime.strptime(target_date_str, "%d.%m.%Y")
                if dt.date() > datetime.now().date():
                    is_tomorrow = True
            except:
                pass
        weather_now = get_weather_popelnyky(target_time="morning", is_tomorrow=is_tomorrow)
        air_temp = float(weather_now.get("temp", 16.5))
        return round(air_temp - 2.0, 1)
    except:
        return 14.5



# --- Гідропости: Кути (верх) + Вашківці/Чортория (низ). Реальні см. ---
KUTY_STATION_ID = 42191
VASH_STATION_ID = 90013  # API: Чортория; у текстах — Вашківці
NIGHT_VERDICT_FROM_HOUR = 14
NIGHT_PENDING_TEXT = "Вердикт на нічну рибалку — після 14:00"
RISE_ALERT_CM = 1  # навіть +1 см на будь-якому посту → ризик каламуті в Попельниках
FALLING_DAYS_MIN = 2  # мінімум 2 дні спад або стабільність → можна казати «чиста»
HYDRO_HEADERS = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
    "X-Requested-With": "XMLHttpRequest",
    "Referer": "https://www.meteo.gov.ua/ua/Dani-avtomatichnikh-hidrolohichnikh-postiv",
}


def _fetch_hydro_raw(station_id, date_from, date_to):
    url = (
        f"https://www.meteo.gov.ua/_/?ACT=HydroAuto&INC=DB"
        f"&P={station_id}&F={date_from}&T={date_to}"
    )
    try:
        res = requests.get(url, headers=HYDRO_HEADERS, timeout=12)
        if res.status_code != 200:
            return None
        return res.json()
    except Exception:
        return None


def _clean_hydro_levels(raw):
    """{ 'dd.mm.YYYY': {hour: cm} } — реальні см з поста"""
    cleaned = {}
    if not raw:
        return cleaned
    for d_str, hours in raw.items():
        day_pts = {}
        for hr, val in enumerate(hours[:24]):
            if val is None or isinstance(val, bool):
                continue
            try:
                v_int = int(val)
            except (TypeError, ValueError):
                continue
            if 50 <= v_int <= 2000:
                day_pts[hr] = v_int
        if day_pts:
            cleaned[d_str] = day_pts
    return cleaned


def _detect_water_temp_from_raw(raw):
    if not raw:
        return None
    for d_str in sorted(raw.keys(), reverse=True):
        hours_data = raw[d_str]
        if len(hours_data) <= 24:
            continue
        for idx in range(24, len(hours_data)):
            val = hours_data[idx]
            if val is not None and not isinstance(val, bool):
                try:
                    fval = float(val)
                except (TypeError, ValueError):
                    continue
                if 0.0 < fval < 28.0:
                    return round(fval, 1)
    return None


def _station_val_near(station, d_str, hour, max_gap=3):
    """Точне значення або найближче ±max_gap год (дірки API)."""
    pts = station.get(d_str, {})
    if not pts:
        return None
    if hour in pts:
        return pts[hour]
    best = None
    best_dist = None
    for h, val in pts.items():
        dist = abs(h - hour)
        if dist <= max_gap and (best_dist is None or dist < best_dist):
            best, best_dist = val, dist
    return best


def _timeline(series):
    """Усі точки поста хронологічно: [(date_str, hour, cm), ...]"""
    out = []
    for d_str in sorted(series.keys(), key=lambda d: datetime.strptime(d, "%d.%m.%Y")):
        for h in sorted(series[d_str].keys()):
            out.append((d_str, h, series[d_str][h]))
    return out


def _prev_day_key(series, date_today):
    days = sorted(series.keys(), key=lambda d: datetime.strptime(d, "%d.%m.%Y"))
    prev = None
    for d in days:
        if d == date_today:
            break
        if series[d]:
            prev = d
    return prev


def _prev_day_last(series, date_today):
    d = _prev_day_key(series, date_today)
    if not d:
        return None
    return series[d][max(series[d].keys())]


def _prev_day_step_base(series, date_today):
    """База для дельти «останнього вчора»: попередня точка того дня або позавчора."""
    d = _prev_day_key(series, date_today)
    if not d:
        return None
    hours = sorted(series[d].keys())
    if len(hours) >= 2:
        return series[d][hours[-2]]
    return _prev_day_last(series, d)


def _latest_snapshot(series):
    """(hour, value, diff_vs_previous_point) або (None, None, None)."""
    tl = _timeline(series)
    if not tl:
        return None, None, None
    _d, hour, val = tl[-1]
    prev_val = tl[-2][2] if len(tl) >= 2 else None
    return hour, val, (val - prev_val) if prev_val is not None else None


def _fmt_level_diff(current, previous):
    if current is None or previous is None:
        return ""
    diff = current - previous
    if diff > 0:
        return f" (+{diff} см)"
    if diff < 0:
        return f" ({diff} см)"
    return " (0 см)"


def _fmt_short_diff(diff):
    if diff is None:
        return ""
    if diff > 0:
        return f" (+{diff})"
    if diff < 0:
        return f" ({diff})"
    return " (0)"


def _today_rise(series, date_today):
    """
    Підйом сьогодні (для каламуті).
    База: мін. ночі 0–6, інакше перша точка сьогодні (коли ніч у пропуску).
    Також враховуємо стрибок першої точки відносно вчора.
    """
    pts = series.get(date_today, {})
    if not pts:
        return 0
    hours = sorted(pts.keys())
    night = [pts[h] for h in hours if h <= 6]
    if night:
        base = min(night)
    else:
        base = pts[hours[0]]
    intraday = max(pts.values()) - base

    prev = _prev_day_last(series, date_today)
    overnight = (pts[hours[0]] - prev) if prev is not None else 0
    return max(intraday, overnight)


def _daily_max_list(series, last_n=10):
    days = sorted(series.keys(), key=lambda d: datetime.strptime(d, "%d.%m.%Y"))
    rows = []
    for d_str in days:
        pts = series[d_str]
        if pts:
            rows.append((d_str, max(pts.values())))
    return rows[-last_n:]


def _falling_or_stable_days(daily_max_rows, min_days=FALLING_DAYS_MIN):
    """True, якщо останні min_days днів максимум не зростав (спад або рівно)."""
    if len(daily_max_rows) < min_days:
        return False
    chunk = daily_max_rows[-min_days:]
    for i in range(1, len(chunk)):
        if chunk[i][1] > chunk[i - 1][1]:
            return False
    return True


def analyze_water_and_night(kuty, vash, date_today, as_of_hour):
    """
    Каламуть — якщо Кути АБО Вашківці сьогодні піднялись (≥1 см).
    «Чиста» — лише якщо ≥2 дні спад/стабільність і сьогодні без підйому.
    """
    rise_k = _today_rise(kuty, date_today) if kuty else 0
    rise_v = _today_rise(vash, date_today) if vash else 0
    today_rise = max(rise_k, rise_v)

    # для «чистої» дивимось основний ряд з даними (Кути, інакше Вашківці)
    primary = kuty if kuty else vash
    daily = _daily_max_list(primary, last_n=10) if primary else []
    settling_ok = _falling_or_stable_days(daily, min_days=FALLING_DAYS_MIN)
    night_ready = as_of_hour >= NIGHT_VERDICT_FROM_HOUR
    is_muddy = False

    if today_rise >= RISE_ALERT_CM:
        is_muddy = True
        clarity = "Сиди вдома!!\n\nРічка каламутна."
        night = "Нічна рибалка відміняється."
        return clarity, night, is_muddy

    if settling_ok and today_rise <= 0:
        clarity = "Річка ймовірно чиста."
        night = "Можна йти з остами на нічну рибалку." if night_ready else NIGHT_PENDING_TEXT
        return clarity, night, is_muddy

    clarity = "Вода ще відстоюється.\n\nМожлива легка каламуть."
    night = "Нічна рибалка під питанням." if night_ready else NIGHT_PENDING_TEXT
    return clarity, night, is_muddy


def get_river_data():
    kyiv_tz = pytz.timezone("Europe/Kyiv")
    now = datetime.now(kyiv_tz).replace(tzinfo=None)

    if now.hour >= 23 or now.hour < 4:
        target_date_dt = now if now.hour >= 23 else (now - timedelta(days=1))
        date_today = target_date_dt.strftime("%d.%m.%Y")
    else:
        date_today = now.strftime("%d.%m.%Y")

    date_to = now.strftime("%Y-%m-%d")
    date_from = (now - timedelta(days=30)).strftime("%Y-%m-%d")

    river_dict = {
        "date_str": format_to_ukr_date(date_today),
        "level": "Невідомо",
        "change": "0 см",
        "raw_time": "—",
        "status": "",
        "water_clarity": "",
        "night_fishing": NIGHT_PENDING_TEXT,
        "is_muddy": False,
        "source": "Кути",
        "kuty_latest": "немає даних",
        "vash_latest": "немає даних",
        "h0": "Очікується...",
        "h9": "Очікується...",
        "h15": "Очікується...",
        "h20": "Очікується...",
        "h0_diff": "",
        "h9_diff": "",
        "h15_diff": "",
        "h20_diff": "",
        "history_00": "Немає даних",
        "water_temp": "Очікується...",
    }

    try:
        raw_k = _fetch_hydro_raw(KUTY_STATION_ID, date_from, date_to)
        raw_v = _fetch_hydro_raw(VASH_STATION_ID, date_from, date_to)
        kuty = _clean_hydro_levels(raw_k)
        vash = _clean_hydro_levels(raw_v)

        detected_temp = _detect_water_temp_from_raw(raw_k)
        if detected_temp is None:
            detected_temp = get_water_temperature()
        if detected_temp is None:
            detected_temp = get_fallback_water_temp()
        river_dict["water_temp"] = f"{detected_temp}°C"

        # --- Останні дані обох постів (стовпчик) ---
        kh, kv, kd = _latest_snapshot(kuty)
        vh, vv, vd = _latest_snapshot(vash)
        if kh is not None:
            river_dict["kuty_latest"] = f"{kh:02d}:00 — {kv} см{_fmt_short_diff(kd)}"
        if vh is not None:
            river_dict["vash_latest"] = f"{vh:02d}:00 — {vv} см{_fmt_short_diff(vd)}"

        # Для годинних точок і історії — Кути; якщо Кути порожні сьогодні/взагалі — Вашківці
        levels = kuty if kuty else vash
        river_dict["source"] = "Кути" if kuty else "Вашківці"
        use_vash_only = not kuty and bool(vash)

        sorted_days = sorted(levels.keys(), key=lambda d: datetime.strptime(d, "%d.%m.%Y"))
        kyiv_today_str = now.strftime("%d.%m.%Y")

        # --- Історія 10 днів ---
        db_temperatures = get_all_seatemperatures_dict()
        history_lines = []
        day_max_values = {}
        hist_days = sorted_days[-10:]
        for d_str in hist_days:
            pts = levels.get(d_str, {})
            day_max_values[d_str] = max(pts.values()) if pts else None

        for i, d_str in enumerate(hist_days):
            val_max = day_max_values[d_str]
            is_today = d_str == kyiv_today_str
            if i > 0 and val_max is not None:
                prev_max = day_max_values.get(hist_days[i - 1])
                if prev_max is not None:
                    day_diff = val_max - prev_max
                    if day_diff > 0:
                        diff_str = f"📈 +{day_diff} см"
                    elif day_diff < 0:
                        diff_str = f"📉 {day_diff} см"
                    else:
                        diff_str = "🔹 0 см"
                else:
                    diff_str = "🔹 ---"
            else:
                diff_str = "🔹 ---"

            clean_date = format_to_ukr_date(d_str)
            val_text = (
                f"[{val_max} см]*" if (val_max is not None and is_today)
                else (f"[{val_max} см]" if val_max is not None else "[— см]")
            )
            day_temp = db_temperatures.get(d_str, get_fallback_water_temp(d_str))
            line = (
                f"📅 <b>{clean_date}</b> | <code>{val_text}</code> | <code>{diff_str}</code>\n"
                f"(🌡️ {day_temp}°C)"
            )
            if is_today:
                line += "\n<code>* (макс. значення на сьогодні)</code>"
            history_lines.append(line)

        if history_lines:
            river_dict["history_00"] = "\n\n".join(history_lines)

        # --- Контрольні години (Кути), з фолбеком на вчора для 00:00 ---
        def checkpoint(target_hour):
            if date_today == kyiv_today_str and now.hour < target_hour:
                return None
            val = _station_val_near(levels, date_today, target_hour, max_gap=3)
            if val is not None:
                return val
            # 00:00 часто в пропуску — беремо останнє за минулу добу
            if target_hour == 0:
                return _prev_day_last(levels, date_today)
            return None

        prev_day_val = _prev_day_last(levels, date_today)
        prev_step_base = _prev_day_step_base(levels, date_today)

        v0 = checkpoint(0)
        v9 = checkpoint(9)
        v15 = checkpoint(15)
        v20 = checkpoint(20)

        if v0 is not None:
            river_dict["h0"] = f"{v0} см"
            # якщо 00:00 з учора (пропуск вночі) — дельта останнього вчорашнього кроку
            today_has_early = any(h <= 3 for h in levels.get(date_today, {}))
            if today_has_early:
                river_dict["h0_diff"] = _fmt_level_diff(v0, prev_day_val)
            else:
                river_dict["h0_diff"] = _fmt_level_diff(v0, prev_step_base)
        if v9 is not None:
            river_dict["h9"] = f"{v9} см"
            river_dict["h9_diff"] = _fmt_level_diff(v9, v0)
        if v15 is not None:
            river_dict["h15"] = f"{v15} см"
            river_dict["h15_diff"] = _fmt_level_diff(v15, v9 if v9 is not None else v0)
        if v20 is not None:
            river_dict["h20"] = f"{v20} см"
            river_dict["h20_diff"] = _fmt_level_diff(v20, v15 if v15 is not None else v9)

        # «Останні дані» в шапці — пріоритет Кути
        if kh is not None:
            river_dict["level"] = f"{kv} см"
            river_dict["raw_time"] = f"{kh:02d}:00"
            river_dict["change"] = _fmt_short_diff(kd).strip(" ()") or "0 см"
            if kd is not None:
                if kd > 0:
                    river_dict["change"] = f"+{kd} см"
                elif kd < 0:
                    river_dict["change"] = f"{kd} см"
                else:
                    river_dict["change"] = "0 см"
        elif vh is not None:
            river_dict["level"] = f"{vv} см"
            river_dict["raw_time"] = f"Вашківці {vh:02d}:00"
            if vd is not None:
                river_dict["change"] = f"+{vd} см" if vd > 0 else (f"{vd} см" if vd < 0 else "0 см")

        clarity, night, is_muddy = analyze_water_and_night(kuty, vash, date_today, now.hour)
        if use_vash_only:
            clarity = f"{clarity}\n\nДані з Кутів тимчасово немає."

        river_dict["water_clarity"] = clarity
        river_dict["night_fishing"] = night
        river_dict["is_muddy"] = is_muddy

    except Exception as e:
        print(f"Помилка парсера УкрГідрометцентру: {e}")
        scraped_temp = get_water_temperature()
        river_dict["water_temp"] = f"{scraped_temp if scraped_temp else get_fallback_water_temp()}°C"

    return river_dict


def format_river_msg(river):
    temp_val = river["water_temp"]
    temp_formatted = f"<code>{temp_val}</code>" if "°C" in str(temp_val) else temp_val
    ukr_date = format_to_ukr_date(river["date_str"])
    clarity = river.get("water_clarity", "")
    night = river.get("night_fishing", NIGHT_PENDING_TEXT)
    kuty_line = river.get("kuty_latest", "немає даних")
    vash_line = river.get("vash_latest", "немає даних")

    return (
        f"━━━━━━━━━━━━━━━━\n"
        f"________ | {ukr_date} | ________\n\n"
        f"✨ <b>СТАН ВОДИ ТА ТЕЧІЇ:</b>\n\n"
        f"<b>Останні дані:</b>\n"
        f"Кути: <code>{kuty_line}</code>\n"
        f"Вашківці: <code>{vash_line}</code>\n\n"
        f"{clarity}\n\n"
        f"🌡️ Температура води: {temp_formatted}\n\n"
        f"━━━━━━━━━━━━━━━━\n"
        f"📊 <b>РІВЕНЬ (Кути) СЬОГОДНІ:</b>\n\n"
        f"•  00:00 🌙 — <code>{river['h0']}</code>{river['h0_diff']}\n"
        f"•  09:00 🌤️ — <code>{river['h9']}</code>{river['h9_diff']}\n"
        f"•  15:00 ☀️ — <code>{river['h15']}</code>{river['h15_diff']}\n"
        f"•  20:00 🌙 — <code>{river['h20']}</code>{river['h20_diff']}\n\n"
        f"━━━━━━━━━━━━━━━━\n"
        f"{night}\n"
        f"━━━━━━━━━━━━━━━━"
    )


def get_weather_popelnyky(target_time="morning", is_tomorrow=False):
    """РЕАЛЬНА погода для Попельників (Івано-Франківська обл.)"""
    lat, lon = 48.45, 25.15
    url = (
        f"https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}"
        "&hourly=temperature_2m,pressure_msl,weather_code,wind_speed_10m,precipitation_probability"
        "&timezone=Europe/Kyiv&forecast_days=2"
    )

    try:
        headers = {"User-Agent": "Mozilla/5.0 (compatible; RiverBot/1.0)"}
        res = requests.get(url, headers=headers, timeout=10)
        if res.status_code != 200:
            return get_weather_fallback(target_time, is_tomorrow)

        data = res.json()
        hourly = data["hourly"]
        hour_map = {"morning": 9, "day": 14, "evening": 20}
        target_hour = hour_map.get(target_time, 9)
        idx = target_hour + (24 if is_tomorrow else 0)
        if idx >= len(hourly["temperature_2m"]):
            idx = min(target_hour, len(hourly["temperature_2m"]) - 1)

        wmo = get_wmo_description(hourly["weather_code"][idx])
        # Open-Meteo: pressure_msl у гПа → мм рт.ст. для рибалки
        pressure_mm = int(round(hourly["pressure_msl"][idx] * 0.750062))
        return {
            "temp": round(hourly["temperature_2m"][idx]),
            "pressure": pressure_mm,
            "wind": hourly["wind_speed_10m"][idx],
            "rain_chance": hourly["precipitation_probability"][idx],
            "icon": wmo["icon"],
            "desc": wmo["desc"],
            "date": "Завтра" if is_tomorrow else "Сьогодні",
        }
    except Exception as e:
        print(f"Помилка Open-Meteo: {e}")
        return get_weather_fallback(target_time, is_tomorrow)

def get_weather_fallback(target_time="morning", is_tomorrow=False):
    """Фолбек, якщо API не працює"""
    target_date = (datetime.now() + timedelta(days=1)).strftime("%d.%m.%Y") if is_tomorrow else datetime.now().strftime("%d.%m.%Y")
    presets = {
        "morning": {"temp": "16", "icon": "🌅", "desc": "свіжо, ясно", "wind": "1.9", "rain_chance": "10", "pressure": 745},
        "day":     {"temp": "24", "icon": "⛅", "desc": "малохмарно", "wind": "3.0", "rain_chance": "20", "pressure": 743},
        "evening": {"temp": "19", "icon": "🌤️", "desc": "ясно", "wind": "1.8", "rain_chance": "15", "pressure": 746}
    }
    p = presets.get(target_time, presets["morning"])
    return {
        "date": target_date,
        "temp": p["temp"],
        "icon": p["icon"],
        "desc": p["desc"],
        "wind": p["wind"],
        "cloud": "—",
        "rain_chance": p["rain_chance"],
        "pressure": p["pressure"]
    }

def get_wmo_description(code):
    """Перетворює WMO код у зрозумілий опис + emoji"""
    wmo = {
        0:  {"icon": "☀️", "desc": "ясно"},
        1:  {"icon": "🌤️", "desc": "переважно ясно"},
        2:  {"icon": "⛅", "desc": "малохмарно"},
        3:  {"icon": "☁️", "desc": "хмарно"},
        45: {"icon": "🌫️", "desc": "туман"},
        51: {"icon": "🌧️", "desc": "легка мряка"},
        61: {"icon": "🌦️", "desc": "невеликий дощ"},
        63: {"icon": "🌧️", "desc": "дощ"},
        71: {"icon": "❄️", "desc": "сніг"},
        80: {"icon": "⛈️", "desc": "злива"},
        95: {"icon": "⛈️", "desc": "гроза"},
    }
    return wmo.get(code, {"icon": "☁️", "desc": "хмарно"})




def get_fishing_forecast(*args, **kwargs):
    """
    Покращений реалістичний прогноз кльову з урахуванням стану річки.
    """
    import re
    
    # 1. Витягуємо дані
    weather_data = args[0] if args else kwargs.get("weather_data", {})
    river_dict = args[1] if len(args) > 1 else kwargs.get("river_dict")

    target_time = kwargs.get("target_time", "morning")
    time_names = {"morning": "🌅 РАНОК", "day": "☀️ ОБІД", "evening": "🌌 ВЕЧІР"}
    time_name = time_names.get(target_time, "🌅 РАНОК")

    try:
        pressure = int(weather_data.get("pressure", 745))
        weather_desc = weather_data.get("desc", "").lower()
    except:
        pressure = 745
        weather_desc = ""

    has_rain = any(word in weather_desc for word in ["дощ", "злива", "мряка", "гроза"])

    # --- ФАЗА МІСЯЦЯ (залишаємо) ---
    now = datetime.now()
    year, month, day = now.year, now.month, now.day
    if month < 3:
        year -= 1
        month += 12
    epact = (11 * (year % 19) + 11) % 30
    if month in [4, 5]: epact += 1
    elif month in [6, 7, 8]: epact += 2
    elif month in [9, 10, 11, 12]: epact += 3
    moon_age = (epact + day) % 30


 # Визначаємо has_rain
    has_rain = any(word in weather_desc for word in ["дощ", "злива", "мряка", "гроза"])
    
    # ВИЗНАЧАЄМО rain_mod тут, щоб вона була доступна всюди
    rain_mod_river = 0.75 if has_rain else 1.0
    rain_mod_pond = 1.35 if has_rain else 1.0


    moon_factor = 0.7 if moon_age in [0,1,2,14,15,16,28,29] else \
                  1.0 if moon_age in [6,7,8,9,21,22,23] else 0.85

    # Коефіцієнт тиску (з невеликою варіацією)
    if 742 <= pressure <= 748:
        pressure_factor = 1.0
    elif 738 <= pressure < 742 or 748 < pressure <= 752:
        pressure_factor = 0.85
    else:
        pressure_factor = 0.65

    # Час доби
    time_factor = 0.9 if target_time == "day" else 1.0   # вдень трохи гірше влітку

    # === ОСНОВНІ ФАКТОРИ ДЛЯ РІЧКИ ===
    river_level_factor = 1.0
    turbidity_factor = 1.0
    water_temp = 16.0

    clarity_text = river_dict.get("water_clarity", "") if river_dict else ""

    if river_dict:
        # Температура води
        try:
            temp_str = river_dict.get("water_temp", "16")
            cleaned_t = re.sub(r'[^\d.]', '', str(temp_str))
            water_temp = float(cleaned_t) if cleaned_t else 16.0
        except:
            water_temp = 16.0

        # Різкий підйом рівня
        h15_diff = river_dict.get("h15_diff", "")
        h9_diff = river_dict.get("h9_diff", "")
        if any(x in h15_diff or h9_diff for x in ["📈", "+", "зростає"]):
            river_level_factor = 0.25   # дуже погано

        # Аналіз каламуті
        if river_dict.get("is_muddy") or "каламутна" in clarity_text.lower() or "КАЛАМУТЬ" in clarity_text:
            turbidity_factor = 0.15
        elif "відстоюється" in clarity_text or "легка каламуть" in clarity_text:
            turbidity_factor = 0.55
        elif "ймовірно чиста" in clarity_text or "ЧИСТА" in clarity_text:
            turbidity_factor = 1.1



        month = datetime.now().month
    # Влітку (червень-серпень) в обід кльов гірший через спеку
        if 6 <= month <= 8 and target_time == "day":
         time_factor *= 0.6

# Аналіз каламуті
        if river_dict.get("is_muddy") or "каламутна" in clarity_text.lower() or "КАЛАМУТЬ" in clarity_text:
            turbidity_factor = 0.05
        elif "відстоюється" in clarity_text or "нестабільна" in clarity_text:
            turbidity_factor = 0.4

    # Температурний фактор для річки
    if water_temp >= 23.0:
        river_temp_factor = 0.25
    elif water_temp >= 20.0:
        river_temp_factor = 0.6
    elif water_temp >= 17.0:
        river_temp_factor = 0.9
    else:
        river_temp_factor = 1.05   # прохолодна вода — добре для марени/головня

    # === РІЧКОВА РИБА === 
    river_fish_base = [
        {"name": "Марена", "emoji": "🐡", "base": 68},
        {"name": "Головень", "emoji": "🐟", "base": 72},
        {"name": "Підуст", "emoji": "🐟", "base": 62},
        {"name": "Окунь", "emoji": "🐠", "base": 78}
    ]
    
    river_forecast = []

    
# Визначаємо, чи рівень піднявся незначно (1-5 см)
    is_slight_rise = False
    if river_dict:
        diff_text = river_dict.get("change", "")
        # Перевірка на "+1 см" ... "+5 см"
        if any(f"+{i} см" in diff_text for i in range(1, 6)):
            is_slight_rise = True

    for fish in river_fish_base:
        # Логіка індивідуального модифікатора для Марени
        if fish["name"] == "Марена":
            # Якщо каламутно (низький turbidity_factor) і рівень трохи піднявся - даємо бонус
            if turbidity_factor <= 0.4 and is_slight_rise:
                mod = 1.5 
            else:
                mod = 0.9 # Трохи зменшуємо стандартно
        else:
            # Інші риби не люблять каламуть
            mod = turbidity_factor 

        # Розрахунок (використовуємо вже визначену rain_mod_river)
        pct = int(fish["base"] * pressure_factor * moon_factor * river_level_factor * river_temp_factor * mod * rain_mod_river * time_factor)
        
        pct = max(5, min(95, pct))
        river_forecast.append({"name": fish["name"], "emoji": fish["emoji"], "pct": pct})

    # === СТАВКОВА РИБА ===
    pond_temp_factor = 1.15 if water_temp >= 17.0 else 0.95
    
    pond_fish_base = [
        {"name": "Короп", "emoji": "🐟", "base": 72},
        {"name": "Карась", "emoji": "🐠", "base": 78},
        {"name": "Щука", "emoji": "🐟", "base": 67},
        {"name": "Білий амур", "emoji": "🐡", "base": 68},
        {"name": "Товстолоб", "emoji": "🐋", "base": 63}
    ]
    
    pond_forecast = []

    for fish in pond_fish_base:
        # Використовуємо rain_mod_pond
        pct = int(fish["base"] * pressure_factor * moon_factor * pond_temp_factor * rain_mod_pond * time_factor)
        pct = max(8, min(95, pct))
        pond_forecast.append({"name": fish["name"], "emoji": fish["emoji"], "pct": pct})

# Сортування від більшого до меншого за відсотком (pct)
    river_forecast.sort(key=lambda x: x['pct'], reverse=True)
    pond_forecast.sort(key=lambda x: x['pct'], reverse=True)

    return {
        "pressure": pressure,
        "time_name": time_name,
        "river_fish": river_forecast,
        "pond_fish": pond_forecast,
        "water_temp": water_temp
    }

def format_fishing_msg(fish, river_dict): # Додали аргумент river_dict
    river_fish = fish.get("river_fish", [])
    pond_fish = fish.get("pond_fish", [])

    msg = (
        f"━━━━━━━━━━━━━━━━\n"
        f"🎣 <b>ПРОГНОЗ КЛЬОВУ РИБИ</b> 🎣\n"
        f"━━━━━━━━━━━━━━━━\n\n"
        f"<b>АКТИВНІСТЬ РИБИ:  <u><b>{fish.get('time_name', '🌅 РАНОК')}</b></u></b>\n\n"
    )

    is_muddy = bool(river_dict.get("is_muddy"))
    clarity = river_dict.get("water_clarity", "")
    if not is_muddy and ("каламутна" in clarity.lower() or "КАЛАМУТЬ" in clarity):
        is_muddy = True

    msg += "<b>Річка Черемош:</b> 🏞️\n"
    if is_muddy:
        # Каламуть — без відсотків кльову по річці
        msg += "⛔ <b>Сиди вдома!!</b>\nРічка каламутна!\n"
    else:
        for f in river_fish:
            msg += f"• {f['emoji']} {f['name']} — <b>{f['pct']}%</b>\n"

    msg += "\n<b>Ставки:</b> 🏡\n"
    for f in pond_fish:
        msg += f"• {f['emoji']} {f['name']} — <b>{f['pct']}%</b>\n"

    msg += (
        f"\n🎈 <b>Атмосферний тиск:</b> <code>{fish.get('pressure', 745)} мм рт.ст.</code>\n"
    )

    if is_muddy:
        msg += (
            f"\nНа річку сьогодні сенсу немає.\n"
            f"━━━━━━━━━━━━━━━━"
        )
    else:
        msg += (
            f"\n🎣 Вдалої РИБАЛКИ! 🎣\n"
            f"━━━━━━━━━━━━━━━━"
        )
    return msg

def format_weather_msg(weather, weather_tomorrow, time_label):
    return (
        f"━━━━━━━━━━━━━━━━\n"
        f"<b>Погода | ПОПЕЛЬНИКИ 🏡 </b>\n\n"
        # f"_____ | {weather['date']} | _____\n"
        f"━━━━━━━━━━━━━━━━\n\n"
        f"⏱️ <b>Період:</b> <u><b>{time_label}</b></u>\n\n"
        f"🌡️ <b>Температура:</b> <code>{weather['temp']}°C</code>\n"
        f"📝 <b>Небо:</b> {weather['icon']} <i>{weather['desc']}</i>\n"
        f"💨 <b>Вітер:</b> <code>{weather['wind']} м/с</code>\n"
        f"💧 <b>Опади:</b> <code>{weather['rain_chance']}%</code>\n\n"
        f"━━━━━━━━━━━━━━━━\n"
        f"🔮 <b>ПРОГНОЗ НА ЗАВТРА ({weather_tomorrow['date']}):</b>\n\n"
        f"🌡️ <b>Вдень:</b> <code>{weather_tomorrow['temp']}°C</code> {weather_tomorrow['icon']}\n"
        f"📝 <i>{weather_tomorrow['desc'].capitalize()}</i>\n"
        f"💨 <b>Вітер:</b> <code>{weather_tomorrow['wind']} м/с</code> | 💦 <b>Опади:</b> <code>{weather_tomorrow['rain_chance']}%</code>\n"
        f"━━━━━━━━━━━━━━━━"
    )