"""Config, inbox state, and local training metadata for Superpitch."""

from __future__ import annotations

import json
from datetime import datetime

from superpitch.app_paths import CONFIG_FILE, FEEDBACK_FILE, HISTORY_FILE


def default_config():
    return {
        "onboarding_complete": False,
        "mode": "local",
        "signed_in": False,
        "auto_retrain_enabled": True,
        "auto_retrain_threshold": 20,
        "last_trained_feedback_count": 0,
    }


def load_config():
    if not CONFIG_FILE.exists():
        return default_config()
    with open(CONFIG_FILE) as f:
        data = json.load(f)
    return {**default_config(), **data}


def save_config(config):
    CONFIG_FILE.parent.mkdir(parents=True, exist_ok=True)
    with open(CONFIG_FILE, "w") as f:
        json.dump(config, f, indent=2)


def count_feedback_entries():
    if not FEEDBACK_FILE.exists():
        return 0
    with open(FEEDBACK_FILE) as f:
        return sum(1 for line in f if line.strip())


def feedback_since_last_train(config):
    return max(0, count_feedback_entries() - int(config.get("last_trained_feedback_count", 0)))


def should_auto_retrain(config):
    if not config.get("auto_retrain_enabled", True):
        return False
    return feedback_since_last_train(config) >= int(config.get("auto_retrain_threshold", 20))


def mark_train_complete(config, feedback_count=None):
    updated = {**default_config(), **config}
    updated["last_trained_feedback_count"] = count_feedback_entries() if feedback_count is None else int(feedback_count)
    save_config(updated)
    return updated


def normalize_history_item(item):
    return {
        **item,
        "opened_at": item.get("opened_at"),
        "decision_state": item.get("decision_state"),
        "decided_at": item.get("decided_at"),
        "review_reasons": item.get("review_reasons") or [],
        "signals": item.get("signals") or {"positive": [], "negative": []},
        "diagnostics": item.get("diagnostics") or {"unusual_signals": [], "outlier_count": 0},
        "sub_scores": item.get("sub_scores") or {},
        "source_label": item.get("source_label", "manual"),
    }


def load_history(limit=None):
    if not HISTORY_FILE.exists():
        return []
    items = []
    with open(HISTORY_FILE) as f:
        for line in f:
            line = line.strip()
            if line:
                items.append(normalize_history_item(json.loads(line)))
    if limit is not None:
        return items[-limit:]
    return items


def save_history(items):
    HISTORY_FILE.parent.mkdir(parents=True, exist_ok=True)
    with open(HISTORY_FILE, "w") as f:
        for item in items:
            f.write(json.dumps(item) + "\n")


def update_history_item(index, item):
    items = load_history()
    if 0 <= index < len(items):
        items[index] = item
        save_history(items)


def save_history_entry(text, inp, result, source_label):
    HISTORY_FILE.parent.mkdir(parents=True, exist_ok=True)
    record = {
        "timestamp": datetime.now().isoformat(),
        "source_label": source_label,
        "one_liner": (inp or {}).get("one_liner") or text.strip().splitlines()[0][:160],
        "text": text,
        "input": inp,
        "pred_score": round(result["pred_score"], 2),
        "final_action": result["final_action"],
        "confidence": result["confidence"]["level"],
        "review_reasons": result["review_reasons"],
        "sub_scores": {k: round(v, 2) for k, v in result["sub"].items()},
        "signals": result["signals"],
        "diagnostics": result["diagnostics"],
        "is_moonshot": result["is_moonshot"],
        "specificity": result["specificity"],
        "opened_at": None,
        "decision_state": None,
        "decided_at": None,
    }
    with open(HISTORY_FILE, "a") as f:
        f.write(json.dumps(record) + "\n")
    return record


def history_bucket(item):
    if item.get("decision_state"):
        return "decided"
    if item.get("opened_at"):
        return "seen"
    return "new"


def inbox_counts(items):
    counts = {"new": 0, "seen": 0, "decided": 0}
    for item in items:
        counts[history_bucket(item)] += 1
    return counts


def inbox_sort_key(item):
    bucket_order = {"new": 0, "seen": 1, "decided": 2}
    action_order = {"REVIEW": 0, "APPROVE": 1, "REJECT": 2}
    return (
        bucket_order[history_bucket(item)],
        action_order.get(item.get("final_action"), 9),
        -float(item.get("pred_score", 0)),
        item.get("timestamp", ""),
    )


def ordered_history(items):
    indexed = list(enumerate(items))
    indexed.sort(key=lambda pair: inbox_sort_key(pair[1]))
    return indexed


def mark_pitch_opened(real_index, item):
    if item.get("opened_at") is None:
        item["opened_at"] = datetime.now().isoformat()
        update_history_item(real_index, item)
    return item


def profile_status_line(config):
    if config.get("mode") == "cloud":
        return "Signed-in sync coming tomorrow"
    return "Local only"
