"""
Evaluate LyraSense JTBD Relevance using OpenAI GPT-5 (Resumable Version)

This script:
1. Reads a CSV file with columns: situation, struggle, outcome.
2. Optionally filters rows using a single column=value argument.
3. Sends each row to GPT-5 for classification.
4. Receives structured JSON output (Relevance, Reasoning, Potential Use Case).
5. Saves results incrementally and resumes if restarted.

Usage:
  python script.py input.csv
  python script.py input.csv job_cluster=0
"""

from openai import OpenAI
import csv
import json
import time
import os
import sys

# === CONFIGURATION ===

if len(sys.argv) < 2:
    print("Usage: python script.py <input_file> [column=value]")
    sys.exit(1)

INPUT_FILE = sys.argv[1]

FILTER_COLUMN = None
FILTER_VALUE = None

if len(sys.argv) >= 3:
    if "=" not in sys.argv[2]:
        print("Filter must be in the form column=value (e.g., job_cluster=0)")
        sys.exit(1)
    FILTER_COLUMN, FILTER_VALUE = sys.argv[2].split("=", 1)

base, ext = os.path.splitext(INPUT_FILE)

if FILTER_COLUMN:
    safe_value = FILTER_VALUE.replace(" ", "_")
    OUTPUT_FILE = f"{base}_evaluated_{FILTER_COLUMN}-{safe_value}{ext}"
else:
    OUTPUT_FILE = f"{base}_evaluated{ext}"

print(f"Input: {INPUT_FILE}")
print(f"Output: {OUTPUT_FILE}")

MODEL_NAME = "gpt-5"
TEMPERATURE = 0.2
DELAY_BETWEEN_CALLS = 1.5

# === OPENAI CLIENT ===

client = OpenAI()

# === SYSTEM PROMPT ===

SYSTEM_PROMPT = """
You are an expert in secure code execution, sandboxed compute, and AI agent runtime infrastructure.
You are evaluating "Jobs to Be Done" (JTBD) statements for their relevance to the real, concrete capabilities of Hopx.

Hopx is:
- A secure code execution and runtime platform built on fast, isolated micro-VMs (Firecracker-style).
- Designed to safely execute untrusted, user-submitted, or AI-generated code.
- Optimized for low-latency sandbox startup (~100ms) and per-execution isolation.
- A runtime layer for:
  - AI agents that need to write, execute, test, or iterate on code.
  - Validating AI-generated code via execution, tests, or analysis.
  - Running long-running or background compute jobs without serverless timeouts.
  - Executing arbitrary scripts in a full Linux environment with resource limits.
- Focused on execution primitives: isolation, resource control, lifecycle management, stdout/stderr streaming, and filesystem access.

Your task:
Given a JTBD statement (situation, struggle, outcome), assess whether solving that job would realistically require:
- Secure execution of code,
- Isolation of untrusted or AI-generated programs,
- A sandboxed runtime for agents, scripts, or long-running compute.

Classification guidelines:
- "✅ Directly relevant":
  The JTBD clearly maps to running code in isolated sandboxes (e.g., AI agents executing code, validating AI outputs, running user code, background jobs).
- "⚙️ Partially relevant":
  The JTBD involves broader systems, but Hopx could serve as a supporting execution layer (not the primary solution).
- "❌ Not relevant":
  The JTBD is about business workflows, human processes, integrations, UI automation, or data management without a core need for sandboxed code execution.

Return your output as JSON with the exact keys:
{
  "Relevance": "✅ Directly relevant" | "⚙️ Partially relevant" | "❌ Not relevant",
  "Reasoning": "<concise explanation explicitly tied to Hopx’s execution and sandboxing capabilities>",
  "potential_use_case": "<concrete example of how Hopx sandboxes would be used, or null if not applicable>"
}

Be strict. If a JTBD can be solved without executing arbitrary or untrusted code in isolation, it is likely not directly relevant to Hopx.
"""

# === FUNCTIONS ===

def load_existing_results(output_file):
    """Load already-processed rows to allow resuming."""
    if not os.path.exists(output_file):
        return set()
    processed = set()
    with open(output_file, newline='', encoding='utf-8') as f:
        reader = csv.DictReader(f)
        for row in reader:
            processed.add(row["situation"])
    return processed


def evaluate_jtbd_row(row):
    """Send a JTBD row to the GPT model and return parsed JSON result."""
    user_prompt = f"""
Situation: {row['situation']}
Struggle: {row['struggle']}
Outcome: {row['outcome']}
"""
    try:
        params = {
            "model": MODEL_NAME,
            "messages": [
                {"role": "system", "content": SYSTEM_PROMPT},
                {"role": "user", "content": user_prompt}
            ],
            "response_format": {"type": "json_object"},
        }

        if MODEL_NAME not in {"gpt-4.1", "gpt-5"}:
            params["temperature"] = TEMPERATURE

        response = client.chat.completions.create(**params)

        content = response.choices[0].message.content.strip()
        data = json.loads(content)

        return {
            "situation": row["situation"],
            "relevance": data.get("Relevance", ""),
            "reasoning": data.get("Reasoning", ""),
            "potential_use_case": data.get("potential_use_case", "")
        }

    except Exception as e:
        print(f"⚠️ Error processing row '{row.get('situation', '')[:60]}...': {e}")
        return {
            "situation": row["situation"],
            "relevance": "ERROR",
            "reasoning": str(e),
            "potential_use_case": ""
        }


def main():
    print(f"🚀 Starting JTBD evaluation with model: {MODEL_NAME}")
    print(f"Input file: {INPUT_FILE}")

    with open(INPUT_FILE, newline='', encoding='utf-8') as csvfile:
        reader = csv.DictReader(csvfile)
        rows = list(reader)

        if FILTER_COLUMN:
            if FILTER_COLUMN not in reader.fieldnames:
                print(f"❌ Column '{FILTER_COLUMN}' not found in CSV")
                sys.exit(1)

            rows = [
                row for row in rows
                if str(row.get(FILTER_COLUMN, "")).strip() == FILTER_VALUE
            ]

            print(
                f"🔍 Applied filter: {FILTER_COLUMN}={FILTER_VALUE} "
                f"→ {len(rows)} rows selected"
            )

    processed = load_existing_results(OUTPUT_FILE)
    print(f"🔄 Found {len(processed)} rows already processed. Will skip them.\n")

    file_exists = os.path.exists(OUTPUT_FILE)
    with open(OUTPUT_FILE, "a", newline='', encoding='utf-8') as f:
        fieldnames = ["situation", "relevance", "reasoning", "potential_use_case"]
        writer = csv.DictWriter(f, fieldnames=fieldnames)
        if not file_exists:
            writer.writeheader()

        for i, row in enumerate(rows, 1):
            if row["situation"] in processed:
                continue

            print(f"[{i}/{len(rows)}] Processing: {row['situation'][:80]}...")
            result = evaluate_jtbd_row(row)
            writer.writerow(result)
            f.flush()
            time.sleep(DELAY_BETWEEN_CALLS)

    print(f"\n✅ Done! Results saved to {OUTPUT_FILE}")


if __name__ == "__main__":
    main()
