"""
Dringliche Programmier-Angebote: erst verkaufen (Angebot), dann bauen, dann liefern.

1. Jam findet was dringend gebraucht wird → Angebot (Fiverr, Kleinanzeigen, Shop)
2. Kunde will es → Jam programmiert in Cursor
3. Fertig → verkaufen / ausliefern (PayPal)
"""

from __future__ import annotations

import json
import random
import re
import time
import webbrowser
from datetime import datetime
from pathlib import Path
from urllib.parse import quote_plus

from jam.brain import JamBrain, JamState
from jam.owner import owner_name
from jam.paypal_donate import PAYPAL_EMAIL

OFFERS_ROOT = Path.home() / "Documents" / "Jam-Angebote-Dringend"
AUTO_GAP_SEC = 90.0
USER_GAP_SEC = 35.0
MAX_PER_HOUR = 6

# Was oft dringend gesucht wird → passendes Jam-Produkt-Template zum Bauen
URGENT_NEEDS: tuple[dict, ...] = (
    {
        "id": "website_fix",
        "title": "Website-Fehler dringend fixen",
        "need": "Layout kaputt, Plugin, langsame Seite – schnelle Hilfe",
        "search": "website fehler beheben dringend programmierer",
        "template": "landing_page",
        "range": (49, 129),
        "delivery": "24–48 h",
    },
    {
        "id": "excel_automation",
        "title": "Excel / CSV Automatisierung",
        "need": "Tabellen automatisieren, Reports, weniger Klickarbeit",
        "search": "excel automatisierung python dringend",
        "template": "python_utility",
        "range": (35, 89),
        "delivery": "1–3 Tage",
    },
    {
        "id": "python_script",
        "title": "Kleines Python-Script (sofort)",
        "need": "Script, Bot, Dateien sortieren – heute noch",
        "search": "python script kleinauftrag dringend deutsch",
        "template": "python_utility",
        "range": (25, 69),
        "delivery": "24 h",
    },
    {
        "id": "landing_urgent",
        "title": "One-Page Webseite dringend",
        "need": "Firma braucht schnell eine professionelle Seite",
        "search": "landingpage schnell erstellen freelancer dringend",
        "template": "landing_page",
        "range": (59, 149),
        "delivery": "2–4 Tage",
    },
    {
        "id": "email_fix",
        "title": "E-Mail / Kontakt-Formular einrichten",
        "need": "Kontaktformular, Vorlagen, Newsletter-Setup",
        "search": "email vorlagen website einrichten auftrag",
        "template": "email_pack",
        "range": (29, 79),
        "delivery": "1–2 Tage",
    },
    {
        "id": "shop_helper",
        "title": "Online-Shop / PayPal-Button Hilfe",
        "need": "Verkaufen mit PayPal, einfacher Shop, digital",
        "search": "paypal shop einrichten hilfe programmierer",
        "template": "python_utility",
        "range": (39, 99),
        "delivery": "2 Tage",
    },
)

BUYER_SEARCH_SUFFIX = (
    "dringend gesucht",
    "kleinauftrag programmieren",
    "freelancer deutsch heute",
)

OFFER_LINES = (
    "{owner}, **dringend gebraucht**: {title}! Ich hab ein Angebot erstellt – "
    "wenn jemand will: sag „Jam, Kunde will programmieren“.",
    "Angebot steht! {need} – Preis ab {price} €. PayPal: {paypal}.",
    "Ich verkaufe erst das Angebot, programmiere erst wenn ein Kunde zusagt – smart, {owner}!",
)

BUILD_LINES = (
    "{owner}, Kunde will es – ich **programmiere jetzt** in Cursor: {title}!",
    "Los geht's! Ich baue {title} und stelle es danach zum Verkauf bereit.",
)

SELL_LINES = (
    "{owner}, Projekt **fertig** – ich verkaufe und liefere! PayPal {paypal}.",
)


def hears_urgent_offer(text: str) -> bool:
    h = text.lower().replace("jam", " ")
    if any(w in h for w in ("dringend", "dringlich", "eilig", "sofort", "schnell")):
        if any(w in h for w in ("angebot", "programmier", "braucht", "gebraucht", "sucht")):
            return True
    if "angebot machen" in h or "angebot erstellen" in h:
        return True
    if "was wird gebraucht" in h or "was wird dringend" in h:
        return True
    if "erst angebot" in h and any(w in h for w in ("programmier", "verkauf")):
        return True
    return False


def hears_customer_wants_build(text: str) -> bool:
    h = text.lower().replace("jam", " ")
    if any(
        w in h
        for w in (
            "kunde will",
            "kunde da",
            "auftrag annehmen",
            "jetzt programmier",
            "fang an zu programmier",
            "fang an zu programmier",
            "bau das",
            "mach das projekt",
            "hat bestellt",
            "will das haben",
            "programmier es",
        )
    ):
        return True
    if "will programmieren" in h or "will es programmiert" in h:
        return True
    return False


def hears_sell_built(text: str) -> bool:
    h = text.lower().replace("jam", " ")
    return any(
        w in h
        for w in (
            "jetzt verkauf",
            "fertig verkauf",
            "verkauf das angebot",
            "ausliefern",
        )
    ) and any(w in h for w in ("angebot", "projekt", "fertig", "programmier"))


def _can_offer(state: JamState, *, user: bool) -> tuple[bool, str]:
    if state.stage < 1:
        return False, "Ich muss noch wachsen, bevor ich Angebote mache!"
    gap = USER_GAP_SEC if user else AUTO_GAP_SEC
    if time.time() - getattr(state, "last_urgent_offer_at", 0.0) < gap:
        wait = int(gap - (time.time() - state.last_urgent_offer_at))
        return False, f"Nächstes Angebot in {wait} Sek."
    return True, ""


def _research_need(need: dict) -> str:
    from jam.internet_learn import fetch_from_internet

    try:
        label, sentences, _url = fetch_from_internet(need["search"])
        if sentences:
            return f"{label}: {sentences[0][:200]}"
    except Exception:
        pass
    return f"Viele suchen gerade: {need['need']}"


def _offer_html(title: str, owner: str, price: float, need: str, delivery: str) -> str:
    return f"""<!DOCTYPE html>
<html lang="de"><head><meta charset="utf-8"><title>{title} – Angebot</title>
<style>body{{font-family:Segoe UI;background:#1a0a2e;color:#f0e6ff;max-width:720px;margin:2rem auto;padding:1.5rem}}
h1{{color:#ce93d8}}.urgent{{color:#ff8a80;font-weight:bold}}.price{{font-size:1.8rem;color:#69f0ae}}
.btn{{display:inline-block;margin-top:1rem;padding:12px 24px;background:#0070ba;color:#fff;text-decoration:none;border-radius:8px}}</style></head>
<body>
<p class="urgent">⚡ DRINGEND – Programmierung von Jam / {owner}</p>
<h1>{title}</h1>
<p>{need}</p>
<p><strong>Lieferzeit:</strong> {delivery}</p>
<p class="price">ab {price:.0f} € (Festpreis nach Absprache)</p>
<p>Code wird <strong>erst nach Bestellung</strong> in Cursor gebaut – kein leeres Versprechen.</p>
<p>Bezahlung: PayPal <strong>{PAYPAL_EMAIL}</strong></p>
<a class="btn" href="mailto:{PAYPAL_EMAIL}?subject=Angebot%20{quote_plus(title)}">Jetzt anfragen</a>
</body></html>"""


def _write_offer_files(
    project: Path,
    *,
    need: dict,
    owner: str,
    price: float,
    price_reason: str,
    research: str,
) -> None:
    title = need["title"]
    (project / "STATUS.json").write_text(
        json.dumps(
            {
                "status": "wartet_auf_kunde",
                "offer_id": need["id"],
                "title": title,
                "price_eur": price,
                "created_at": time.time(),
            },
            indent=2,
        ),
        encoding="utf-8",
    )
    (project / "ANGEBOT.md").write_text(
        f"# ⚡ DRINGEND – {title}\n\n"
        f"## Was gebraucht wird\n{need['need']}\n\n"
        f"## Recherche ({datetime.now().strftime('%d.%m.%Y %H:%M')})\n{research}\n\n"
        f"## Mein Angebot (Jam für {owner})\n"
        f"- **Preis ab:** {price:.0f} €\n"
        f"- **Lieferzeit:** {need['delivery']}\n"
        f"- **PayPal:** {PAYPAL_EMAIL}\n"
        f"- **Status:** Wartet auf Kunde – Code wird erst nach Zusage gebaut.\n\n"
        f"### Preis-Begründung\n{price_reason}\n\n"
        f"### Wenn Kunde zusagt\n"
        f"Sag Jam: **„Kunde will programmieren“** – dann baut Jam in Cursor.\n"
        f"Danach: **„Jetzt verkaufen“** – alle Kanäle + Auslieferung.\n",
        encoding="utf-8",
    )
    (project / "PLATZHALTER.md").write_text(
        "# Noch kein Code\n\n"
        "Jam erstellt den Quellcode **erst wenn ein Kunde das Angebot annimmt**.\n"
        f"Template: `{need['template']}`\n",
        encoding="utf-8",
    )
    (project / "index.html").write_text(
        _offer_html(title, owner, price, need["need"], need["delivery"]),
        encoding="utf-8",
    )
    try:
        from jam.fiverr_connect import write_gig_listing

        write_gig_listing(
            project,
            title=f"⚡ {title}",
            owner=owner,
            price=int(price) if price >= 1 else 5,
            reason=price_reason,
        )
        gig = project / "FIVERR_GIG.txt"
        if gig.is_file():
            extra = (
                "\n\n=== WICHTIG ===\n"
                "I build AFTER order – message me first. Fast delivery.\n"
                f"PayPal: {PAYPAL_EMAIL}\n"
            )
            gig.write_text(gig.read_text(encoding="utf-8") + extra, encoding="utf-8")
    except Exception:
        (project / "FIVERR_GIG.txt").write_text(
            f"{title}\nab {price} EUR\n{need['need']}\nPayPal: {PAYPAL_EMAIL}\n",
            encoding="utf-8",
        )
    (project / "KLEINANZEIGEN.txt").write_text(
        f"⚡ DRINGEND: {title}\n\n"
        f"{need['need']}\n"
        f"Ab {price:.0f} € | Lieferung {need['delivery']}\n"
        f"PayPal: {PAYPAL_EMAIL}\n"
        f"Programmierung mit Cursor – {owner}\n",
        encoding="utf-8",
    )


def _publish_offer_search(need: dict, title: str, *, state: JamState | None = None) -> None:
    queries = [
        need["search"],
        f"{title} {random.choice(BUYER_SEARCH_SUFFIX)}",
    ]
    for q in queries[:2]:
        try:
            webbrowser.open(
                f"https://www.google.com/search?q={quote_plus(q)}",
                new=2,
            )
        except OSError:
            break
    try:
        from jam.fiverr_connect import get_username, is_connected, new_gig_url

        if state and is_connected(state):
            webbrowser.open(new_gig_url(get_username(state)), new=2)
    except Exception:
        pass


def create_urgent_offer(
    brain: JamBrain,
    *,
    need_id: str | None = None,
    user_initiated: bool = False,
) -> str:
    """Schritt 1: Angebot ohne Code – wer will, bestellt erst."""
    state = brain.state
    owner = owner_name(state)
    ok, wait = _can_offer(state, user=user_initiated)
    if not ok:
        return wait

    recent = [
        e.get("offer_id")
        for e in (getattr(state, "jam_urgent_offers_log", []) or [])[-4:]
        if isinstance(e, dict)
    ]
    pool = [n for n in URGENT_NEEDS if n["id"] not in recent] or list(URGENT_NEEDS)
    need = next((n for n in pool if n["id"] == need_id), None) if need_id else None
    need = need or random.choice(pool)

    research = _research_need(need)
    lo, hi = need["range"]
    from jam.sales_engine import jam_decide_price

    price, price_reason = jam_decide_price(
        state,
        lo=float(lo),
        hi=float(hi),
        title=need["title"],
        difficulty=3,
        research=research,
    )

    stamp = datetime.now().strftime("%Y%m%d-%H%M%S")
    slug = re.sub(r"[^a-z0-9]+", "-", need["id"])[:24]
    project = OFFERS_ROOT / f"{stamp}-{slug}"
    project.mkdir(parents=True, exist_ok=True)
    _write_offer_files(
        project,
        need=need,
        owner=owner,
        price=price,
        price_reason=price_reason,
        research=research,
    )

    _publish_offer_search(need, need["title"], state=state)
    try:
        import os
        import subprocess

        if os.name == "nt":
            subprocess.run(["explorer", str(project)], check=False, timeout=5)
        webbrowser.open((project / "index.html").as_uri(), new=2)
    except OSError:
        pass

    entry = {
        "offer_id": need["id"],
        "title": need["title"],
        "path": str(project),
        "price": price,
        "status": "wartet_auf_kunde",
        "template": need["template"],
        "at": time.time(),
    }
    log = list(getattr(state, "jam_urgent_offers_log", []) or [])
    log.append(entry)
    state.jam_urgent_offers_log = log[-30:]
    state.urgent_offers_count = getattr(state, "urgent_offers_count", 0) + 1
    state.last_urgent_offer_at = time.time()
    state.last_action = "urgent_offer"
    state.remember(f"Dringendes Angebot: {need['title']} ({price:.0f} €)")
    brain.add_xp(14)
    brain.save()

    try:
        from jam.earn_report import record_earning

        record_earning(
            brain,
            method="urgent_offer",
            title=need["title"],
            detail=f"Angebot erstellt – wartet auf Kunde. {research[:120]}",
            amount_eur=price,
            path=str(project),
            background=not user_initiated,
        )
    except Exception:
        pass

    line = random.choice(OFFER_LINES).format(
        owner=owner,
        title=need["title"],
        need=need["need"],
        price=price,
        paypal=PAYPAL_EMAIL,
    )
    return (
        f"{line} Ordner: {project.name}. "
        f"Wenn jemand zusagt: „Jam, Kunde will programmieren“ – dann baue ich. "
        f"Danach: „Jam, jetzt verkaufen“."
    )[:520]


def _latest_pending_offer(state: JamState) -> dict | None:
    log = getattr(state, "jam_urgent_offers_log", []) or []
    for entry in reversed(log):
        if not isinstance(entry, dict):
            continue
        if entry.get("status") == "wartet_auf_kunde":
            return entry
        path = Path(entry.get("path", ""))
        status_file = path / "STATUS.json"
        if status_file.is_file():
            try:
                st = json.loads(status_file.read_text(encoding="utf-8"))
                if st.get("status") == "wartet_auf_kunde":
                    return entry
            except (OSError, json.JSONDecodeError):
                pass
    return log[-1] if log and isinstance(log[-1], dict) else None


def build_for_customer(
    brain: JamBrain,
    *,
    user_initiated: bool = True,
) -> str:
    """Schritt 2: Kunde will es → programmieren in Cursor."""
    from jam.cursor_lab import cursor_available, open_in_cursor
    from jam.sales_engine import (
        TEMPLATES,
        _implement_files,
        _shop_html,
        _write_listings,
        jam_decide_price,
    )

    state = brain.state
    owner = owner_name(state)
    entry = _latest_pending_offer(state)
    if not entry:
        return (
            f"{owner}, es gibt noch kein Angebot – sag zuerst "
            f"„Jam, mach ein dringendes Angebot“!"
        )

    project = Path(entry["path"])
    if not project.is_dir():
        return f"{owner}, Angebots-Ordner fehlt – neues Angebot erstellen!"

    tid = entry.get("template") or "python_utility"
    info = TEMPLATES.get(tid) or TEMPLATES["python_utility"]
    title = entry.get("title") or info["title"]
    lo, hi = info.get("range", (15, 50))
    price = float(entry.get("price", 0))
    if price <= 0:
        price, price_reason = jam_decide_price(
            state,
            lo=float(lo),
            hi=float(hi),
            title=title,
            difficulty=int(info.get("difficulty", 2)),
        )
    else:
        price_reason = f"Fest aus Angebot: {price:.0f} €"

    _implement_files(project, tid, owner, int(price) if price >= 1 else price)
    (project / "PLATZHALTER.md").unlink(missing_ok=True)
    (project / "PROJEKT.md").write_text(
        f"# {title}\n\n**Gebaut nach Kundenwunsch** am "
        f"{datetime.now().strftime('%d.%m.%Y %H:%M')}.\n\n{price_reason}\n",
        encoding="utf-8",
    )
    from jam.paypal_donate import paypal_donate_url

    (project / "index.html").write_text(
        _shop_html(title, owner, int(price) if price >= 1 else price, price_reason, paypal_donate_url()),
        encoding="utf-8",
    )
    _write_listings(project, title, owner, int(price) if price >= 1 else 5, price_reason)

    cursor_open = False
    if cursor_available():
        cursor_open, _ = open_in_cursor(project)

    status = {
        "status": "gebaut",
        "offer_id": entry.get("offer_id"),
        "title": title,
        "price_eur": price,
        "built_at": time.time(),
    }
    (project / "STATUS.json").write_text(json.dumps(status, indent=2), encoding="utf-8")
    entry["status"] = "gebaut"
    entry["price"] = price
    state.jam_urgent_offers_log = list(getattr(state, "jam_urgent_offers_log", []) or [])
    state.last_action = "urgent_build"
    state.remember(f"Programmiert für Kunde: {title}")
    brain.add_xp(25)
    brain.save()

    line = random.choice(BUILD_LINES).format(owner=owner, title=title)
    cursor_bit = " Cursor ist offen!" if cursor_open else " Ordner in Cursor öffnen!"
    return (
        f"{line}{cursor_bit} "
        f"Sag „Jam, jetzt verkaufen“ – dann pushe ich Fiverr, PayPal & alle Kanäle."
    )[:480]


def sell_built_offer(brain: JamBrain, *, user_initiated: bool = True) -> str:
    """Schritt 3: Fertiges Projekt verkaufen."""
    from jam.active_sell import push_product_sale
    from jam.sales_engine import _publish

    state = brain.state
    owner = owner_name(state)
    log = getattr(state, "jam_urgent_offers_log", []) or []
    entry = None
    for e in reversed(log):
        if isinstance(e, dict) and e.get("status") in ("gebaut", "wartet_auf_kunde"):
            entry = e
            break
    if not entry:
        return f"{owner}, nichts zum Verkaufen – erst Angebot + Programmieren!"

    project = Path(entry["path"])
    title = entry.get("title", "Projekt")
    price = float(entry.get("price", 19))
    if not project.is_dir():
        return f"{owner}, Projekt-Ordner fehlt!"

    sale_log = list(getattr(state, "jam_sales_log", []) or [])
    sale_log.append(
        {
            "title": title,
            "price": price,
            "path": str(project),
            "template": entry.get("template", ""),
            "reason": "Dringendes Angebot – nach Kundenwunsch gebaut",
            "at": time.time(),
        }
    )
    state.jam_sales_log = sale_log[-40:]
    state.last_jam_sale_at = time.time()
    state.last_action = "urgent_sell"

    _publish(title, int(price) if price >= 1 else price, project)
    push_msg = push_product_sale(
        brain, project, title, price, user_initiated=user_initiated
    )
    entry["status"] = "verkauft"
    st_path = project / "STATUS.json"
    if st_path.is_file():
        try:
            st = json.loads(st_path.read_text(encoding="utf-8"))
            st["status"] = "verkauft"
            st_path.write_text(json.dumps(st, indent=2), encoding="utf-8")
        except (OSError, json.JSONDecodeError, TypeError):
            pass
    brain.save()

    line = random.choice(SELL_LINES).format(owner=owner, paypal=PAYPAL_EMAIL)
    return f"{line} {push_msg or ''}"[:520]


def run_full_commission_flow(brain: JamBrain, *, user_initiated: bool = True) -> str:
    """Angebot → (simuliert: sofort bauen für Demo) → verkaufen."""
    owner = owner_name(brain.state)
    o = create_urgent_offer(brain, user_initiated=user_initiated)
    b = build_for_customer(brain, user_initiated=user_initiated)
    s = sell_built_offer(brain, user_initiated=user_initiated)
    return (
        f"{owner}, voller Ablauf! 1) Angebot 2) Programmiert 3) Verkauf. "
        f"{o[:100]}… {b[:80]}… {s[:80]}…"
    )[:620]


def handle_speech(brain: JamBrain, heard: str) -> str | None:
    if hears_customer_wants_build(heard):
        return build_for_customer(brain, user_initiated=True)
    if hears_sell_built(heard):
        return sell_built_offer(brain, user_initiated=True)
    if hears_urgent_offer(heard):
        if any(w in heard.lower() for w in ("alles", "komplett", "dann programmier", "und verkauf")):
            return run_full_commission_flow(brain, user_initiated=True)
        return create_urgent_offer(brain, user_initiated=True)
    return None


def stats_line(state: JamState) -> str:
    n = getattr(state, "urgent_offers_count", 0)
    pending = sum(
        1
        for e in (getattr(state, "jam_urgent_offers_log", []) or [])
        if isinstance(e, dict) and e.get("status") == "wartet_auf_kunde"
    )
    return f"Dringende Angebote: {n} erstellt, {pending} warten auf Kunde"


def maybe_auto_offer(brain: JamBrain) -> str | None:
    if brain.state.stage < 1:
        return None
    if random.random() > 0.42:
        return None
    ok, _ = _can_offer(brain.state, user=False)
    if not ok:
        return None
    return create_urgent_offer(brain, user_initiated=False)
