"""Daily 19:05 cron job — finalize variant choice, build next batch, notify group chat."""
import csv
import json
import os
import re
import sqlite3
from datetime import datetime
from pathlib import Path
from typing import Dict, List, Set, Tuple

BASE_DIR   = Path(__file__).parent.parent
VARIANTS_FILE = BASE_DIR / "data/processed/aima_pending_variants.json"
STATE_FILE    = BASE_DIR / "data/processed/aima_bot_state.json"
DB            = BASE_DIR / "data/processed/aima_conversion_shadow.sqlite"
DATASET       = "users_without_shop_202605191510"
BATCH_SIZE    = 30
CHAT_ID       = -5178178519
MARKETER      = "@anatolii_malinovskyi"

DEFAULT_ENV_FILES = [
    BASE_DIR / ".env",
    Path(r"C:\python_scripts\top_1_telegram_signals\.env"),
]

CONTACTS_FIELDS = [
    "pilot_id", "pilot_name", "lead_id", "dataset", "segment", "variant",
    "hypothesis", "gate1_text", "phone", "first_name", "last_name",
    "registered_at", "last_activity_at", "worker-do-not-send",
    "pre_contact_quality", "contamination_status", "notes",
]

LOG_FIELDS = [
    "pilot_id", "lead_id", "dataset", "hypothesis", "phone",
    "worker-do-not-send", "added_to_telegram", "telegram_contact_name",
    "gate1_message_sent", "replied", "reply_text", "next_gate", "notes",
    "sent_at_utc", "recipient_id", "message_len", "message_preview",
    "chat_started", "replied_at_utc", "reply_category",
    "pre_contact_quality", "contamination_status",
    "qualified_product_reply", "next_step_accepted", "negative_stop", "reply_class",
]


def load_env():
    for path in DEFAULT_ENV_FILES:
        if not path.exists():
            continue
        for raw in path.read_text(encoding="utf-8", errors="ignore").splitlines():
            line = raw.strip()
            if not line or line.startswith("#") or "=" not in line:
                continue
            k, v = line.split("=", 1)
            os.environ.setdefault(k.strip(), v.strip().strip('"').strip("'"))


def collect_used():
    # type: () -> Tuple[Set[str], Set[str]]
    used_leads = set()  # type: Set[str]
    used_phones = set()  # type: Set[str]
    proc = BASE_DIR / "data/processed"
    for p in sorted(proc.glob("*.csv")):
        with p.open(encoding="utf-8-sig") as f:
            for row in csv.DictReader(f):
                lid = str(row.get("lead_id", "") or "").strip()
                ph  = str(row.get("phone",   "") or "").strip()
                if lid:
                    used_leads.add(lid)
                if ph:
                    used_phones.add(ph)
    return used_leads, used_phones


def next_batch_key():
    # type: () -> str
    nums = []
    for p in (BASE_DIR / "data/processed").glob("aima_far_v*_contacts.csv"):
        m = re.search(r"v(\d+)_contacts", p.name)
        if m:
            nums.append(int(m.group(1)))
    return "v{}".format(max(nums) + 1) if nums else "v7"


def next_pilot_id_start():
    # type: () -> int
    max_id = 120
    for p in (BASE_DIR / "data/processed").glob("aima_far_v*_contacts.csv"):
        with p.open(encoding="utf-8-sig") as f:
            for row in csv.DictReader(f):
                try:
                    max_id = max(max_id, int(row.get("pilot_id", 0) or 0))
                except (ValueError, TypeError):
                    pass
    return max_id + 1


def build_next_batch(batch_key, variant_texts, pilot_id_start):
    # type: (str, Dict[str, str], int) -> Tuple[Path, Path]
    used_leads, used_phones = collect_used()

    conn = sqlite3.connect(str(DB))
    cur = conn.cursor()
    cur.execute(
        """SELECT lead_id, first_name, last_name, phone, registered_at, last_activity_at
           FROM aima_imported_contacts
           WHERE dataset = ?
           ORDER BY row_index DESC""",
        (DATASET,),
    )
    all_rows = cur.fetchall()
    conn.close()

    candidates = [
        r for r in all_rows
        if r[3] and str(r[0]) not in used_leads and r[3] not in used_phones
    ]
    if len(candidates) < BATCH_SIZE:
        raise RuntimeError("Not enough contacts: {} available, need {}".format(
            len(candidates), BATCH_SIZE))

    selected = candidates[:BATCH_SIZE]
    v_keys = list(variant_texts.keys())
    half = BATCH_SIZE // 2
    pilot_name = "manual_far_{}".format(batch_key)

    contacts_csv = BASE_DIR / "data/processed/aima_far_{}_contacts.csv".format(batch_key)
    log_csv      = BASE_DIR / "data/processed/aima_far_{}_telegram_log.csv".format(batch_key)

    contact_rows = []
    log_rows = []

    for i, (lead_id, first_name, last_name, phone, registered_at, last_activity_at) in enumerate(selected):
        pilot_id = pilot_id_start + i
        variant  = v_keys[0] if i < half else v_keys[1 % len(v_keys)]
        gate1_text = variant_texts[variant]

        contact_rows.append({
            "pilot_id": pilot_id,
            "pilot_name": pilot_name,
            "lead_id": lead_id,
            "dataset": DATASET,
            "segment": "opened_no_store",
            "variant": variant,
            "hypothesis": variant,
            "gate1_text": gate1_text,
            "phone": phone,
            "first_name": first_name or "",
            "last_name": last_name or "",
            "registered_at": registered_at or "",
            "last_activity_at": last_activity_at or "",
            "worker-do-not-send": "",
            "pre_contact_quality": "unknown",
            "contamination_status": "unknown",
            "notes": "FAR candidate batch {}".format(batch_key),
        })

        log_row = {k: "" for k in LOG_FIELDS}
        log_row.update({
            "pilot_id": pilot_id,
            "lead_id": lead_id,
            "dataset": DATASET,
            "hypothesis": variant,
            "phone": phone,
            "worker-do-not-send": "",
            "pre_contact_quality": "unknown",
            "contamination_status": "unknown",
        })
        log_rows.append(log_row)

    with contacts_csv.open("w", encoding="utf-8", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=CONTACTS_FIELDS)
        writer.writeheader()
        writer.writerows(contact_rows)

    with log_csv.open("w", encoding="utf-8", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=LOG_FIELDS)
        writer.writeheader()
        writer.writerows(log_rows)

    return contacts_csv, log_csv


def write_send_script(batch_key):
    # type: (str) -> None
    """Generate send script for next batch by substituting v6 template."""
    src_path = BASE_DIR / "src/aima_batch_send_{}.py".format(batch_key)
    v6_path  = BASE_DIR / "src/aima_batch_send_v6.py"
    if not v6_path.exists():
        print("[warn] v6 send script not found, cannot generate {}".format(src_path.name))
        return
    src = v6_path.read_text(encoding="utf-8")
    src = src.replace("aima_far_v6_contacts.csv", "aima_far_{}_contacts.csv".format(batch_key))
    src = src.replace("aima_far_v6_telegram_log.csv", "aima_far_{}_telegram_log.csv".format(batch_key))
    src = src.replace("batch_send_v6", "batch_send_{}".format(batch_key))
    src = src.replace("AIMA FAR v6 pilot", "AIMA FAR {} pilot".format(batch_key))
    src_path.write_text(src, encoding="utf-8")
    print("[script] wrote {}".format(src_path.name))


def send_telegram(token, chat_id, text):
    import requests
    r = requests.post(
        "https://api.telegram.org/bot{}/sendMessage".format(token),
        json={"chat_id": chat_id, "text": text, "parse_mode": "HTML"},
        timeout=30,
    )
    return r.json()


def main():
    load_env()
    token = os.environ.get("AIMA_BOT_TOKEN")
    if not token:
        raise SystemExit("AIMA_BOT_TOKEN missing")

    if not VARIANTS_FILE.exists():
        print("[warn] {} not found — run aima_agent_prepare.py first".format(VARIANTS_FILE.name))
        return

    data = json.loads(VARIANTS_FILE.read_text(encoding="utf-8"))
    status   = data.get("status", "pending_choice")
    variants = data.get("variants", [])  # type: List[dict]
    chosen   = data.get("chosen", [])    # type: List[str]

    if not variants:
        print("[warn] no variants in file")
        return

    # Resolve chosen labels
    if status == "chosen" and len(chosen) >= 2:
        chosen_labels = chosen[:2]
        auto_picked = False
    else:
        # Auto-pick A and C (indices 0 and 2), or A and B if only 2 available
        if len(variants) >= 3:
            chosen_labels = [variants[0]["label"], variants[2]["label"]]
        else:
            chosen_labels = [v["label"] for v in variants[:2]]
        auto_picked = True

    chosen_variants = [v for v in variants if v["label"] in chosen_labels]
    if len(chosen_variants) < 2:
        chosen_variants = variants[:2]

    print("[pick] {}: {}".format("auto" if auto_picked else "user",
                                  [v["label"] for v in chosen_variants]))

    # Build variant_texts dict keyed by hypothesis name
    variant_texts = {}  # type: Dict[str, str]
    for v in chosen_variants:
        key = "FAR_{}_agent_gen".format(v["label"])
        variant_texts[key] = v["text"]

    batch_key      = next_batch_key()
    pilot_id_start = next_pilot_id_start()

    # Build batch CSVs
    try:
        contacts_csv, log_csv = build_next_batch(batch_key, variant_texts, pilot_id_start)
        print("[batch] {} -> {}".format(batch_key, contacts_csv.name))
    except RuntimeError as exc:
        print("[error] {}".format(exc))
        send_telegram(token, CHAT_ID,
                      "⚠️ AIMA агент: не вдалося побудувати батч {}: {}".format(batch_key, exc))
        return

    # Generate send script
    write_send_script(batch_key)

    # Update bot state
    state = {}
    if STATE_FILE.exists():
        state = json.loads(STATE_FILE.read_text(encoding="utf-8"))

    send_script = str(BASE_DIR / "src/aima_batch_send_{}.py".format(batch_key))
    gdrive_url  = (state.get("proposals", {}).get("v6") or {}).get("gdrive_url", "")
    state.setdefault("proposals", {})[batch_key] = {
        "name": "FAR {} — 30 контактів (агент)".format(batch_key),
        "contacts_csv": str(contacts_csv),
        "log_csv":      str(log_csv),
        "send_script":  send_script,
        "gdrive_url":   gdrive_url,
    }
    state["active_batch"] = batch_key
    state["pending"]      = batch_key
    state["daily"] = {
        "date": "", "status": "idle", "morning_msg_id": None,
        "send_triggered": False, "sent_count": None,
        "approved_by": None, "approved_at": None, "sent_at": None,
    }
    STATE_FILE.write_text(json.dumps(state, ensure_ascii=False, indent=2), encoding="utf-8")
    print("[state] active_batch={}".format(batch_key))

    # Finalize variants file
    data["status"]           = "finalized"
    data["finalized_labels"] = [v["label"] for v in chosen_variants]
    data["finalized_at"]     = datetime.now().isoformat()
    VARIANTS_FILE.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")

    # Send group message
    auto_note = " (автовибір)" if auto_picked else ""
    chosen_info = "\n".join(
        "  <b>{}:</b> {}".format(v["label"], v["text"][:160])
        for v in chosen_variants
    )
    msg = (
        "\U0001f514 {}, підготовка наступної розсилки!\n\n"
        "Батч: <b>FAR {}</b> | Контактів: <b>30</b>\n"
        "Гіпотези{}:\n{}\n\n"
        "Завтра о <b>08:00</b> бот нагадає для підтвердження.\n"
        "/status — поточний стан"
    ).format(MARKETER, batch_key, auto_note, chosen_info)

    result = send_telegram(token, CHAT_ID, msg)
    if result.get("ok"):
        print("[sent] group proposal for {}".format(batch_key))
    else:
        print("[warn] telegram error: {}".format(result))


if __name__ == "__main__":
    main()
