<?php
// public/api/agent.php
declare(strict_types=1);

header("Content-Type: application/json; charset=utf-8");

require_once __DIR__ . "/../../app/db.php"; // your DB helper (smm_db)

function j($ok, $data = [], $code = 200) {
  http_response_code($code);
  echo json_encode(array_merge(["ok"=>$ok], $data), JSON_PRETTY_PRINT);
  exit;
}

function read_json_body(): array {
  $raw = file_get_contents("php://input");
  $b = json_decode($raw ?: "{}", true);
  return is_array($b) ? $b : [];
}

function state_path(string $sid): string {
  $safe = preg_replace('/[^a-zA-Z0-9_\-]/', '', $sid);
  return __DIR__ . "/../../storage/agent_state_" . ($safe ?: "default") . ".json";
}

function load_state(string $sid): array {
  $p = state_path($sid);
  if (!file_exists($p)) return ["last_article_id" => null];
  $d = json_decode(file_get_contents($p), true);
  return is_array($d) ? $d : ["last_article_id" => null];
}

function save_state(string $sid, array $s): void {
  $p = state_path($sid);
  @file_put_contents($p, json_encode($s, JSON_PRETTY_PRINT));
}

function db(): SQLite3 {
  return smm_db();
}

function db_get_tool(string $key): ?array {
  $q = db()->prepare("SELECT tool_key, name, type, description, enabled, config_json FROM tools WHERE tool_key = :k LIMIT 1");
  $q->bindValue(":k", $key, SQLITE3_TEXT);
  $r = $q->execute();
  $row = $r ? $r->fetchArray(SQLITE3_ASSOC) : false;
  return $row ? $row : null;
}

function db_get_default_site(): ?array {
  // first enabled site becomes default
  $r = db()->query("SELECT site_key, name, base_url, publish_dir, posts_json_path, enabled FROM sites WHERE enabled=1 ORDER BY id ASC LIMIT 1");
  $row = $r ? $r->fetchArray(SQLITE3_ASSOC) : false;
  return $row ? $row : null;
}

function slugify(string $s): string {
  $s = strtolower(trim($s));
  $s = preg_replace('/[^a-z0-9\s\-]/', '', $s);
  $s = preg_replace('/\s+/', '-', $s);
  $s = preg_replace('/\-+/', '-', $s);
  return trim($s, "-") ?: "post";
}

function create_article(string $title, string $body, array $meta = []): int {
  $q = db()->prepare("INSERT INTO articles(title, body, meta_json, created_at) VALUES (:t,:b,:m,:c)");
  $q->bindValue(":t", $title, SQLITE3_TEXT);
  $q->bindValue(":b", $body, SQLITE3_TEXT);
  $q->bindValue(":m", json_encode($meta), SQLITE3_TEXT);
  $q->bindValue(":c", date("c"), SQLITE3_TEXT);
  $ok = $q->execute();
  if (!$ok) return 0;
  return (int)db()->lastInsertRowID();
}

function get_article(int $id): ?array {
  $q = db()->prepare("SELECT id, title, body, meta_json FROM articles WHERE id=:id LIMIT 1");
  $q->bindValue(":id", $id, SQLITE3_INTEGER);
  $r = $q->execute();
  $row = $r ? $r->fetchArray(SQLITE3_ASSOC) : false;
  if (!$row) return null;
  $row["meta"] = json_decode($row["meta_json"] ?: "{}", true);
  if (!is_array($row["meta"])) $row["meta"] = [];
  return $row;
}

function update_article_meta(int $id, array $meta): void {
  $q = db()->prepare("UPDATE articles SET meta_json=:m WHERE id=:id");
  $q->bindValue(":m", json_encode($meta), SQLITE3_TEXT);
  $q->bindValue(":id", $id, SQLITE3_INTEGER);
  $q->execute();
}

// ---------- Tool runners ----------
function http_post_json(string $url, array $headers, array $payload): array {
  $ch = curl_init($url);
  $h = [];
  foreach ($headers as $k => $v) $h[] = $k . ": " . $v;

  curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => $h,
    CURLOPT_POSTFIELDS => json_encode($payload),
    CURLOPT_TIMEOUT => 60
  ]);
  $resp = curl_exec($ch);
  $code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
  $err = curl_error($ch);
  curl_close($ch);

  if ($resp === false) return ["ok"=>false, "error"=>$err ?: "HTTP error", "code"=>$code];
  $json = json_decode($resp, true);
  return ["ok"=>($code>=200 && $code<300), "code"=>$code, "raw"=>$resp, "json"=>$json];
}

function run_openai_chat(array $tool, string $prompt): array {
  $cfg = json_decode($tool["config_json"] ?: "{}", true);
  if (!is_array($cfg)) $cfg = [];
  $model = $cfg["model"] ?? "gpt-4.1-mini";
  $system = $cfg["system"] ?? "Write a helpful article.";
  $temp = $cfg["temperature"] ?? 0.7;
  $max = $cfg["max_tokens"] ?? 1200;

  // Your tool config should store the key inside config_json or you can centralize it.
  $apiKey = $cfg["api_key"] ?? "";
  if (!$apiKey) return ["ok"=>false, "error"=>"openai_chat missing api_key in tool config_json"];

  $r = http_post_json(
    "https://api.openai.com/v1/chat/completions",
    ["Content-Type"=>"application/json", "Authorization"=>"Bearer ".$apiKey],
    [
      "model"=>$model,
      "temperature"=>$temp,
      "max_tokens"=>$max,
      "messages"=>[
        ["role"=>"system","content"=>$system],
        ["role"=>"user","content"=>$prompt]
      ]
    ]
  );

  if (!$r["ok"]) return ["ok"=>false, "error"=>"OpenAI chat failed", "details"=>$r];

  $text = $r["json"]["choices"][0]["message"]["content"] ?? "";
  return ["ok"=>true, "text"=>trim($text), "raw"=>$r["json"]];
}

function run_tagx(array $tool, string $text): array {
  $cfg = json_decode($tool["config_json"] ?: "{}", true);
  if (!is_array($cfg)) $cfg = [];
  $max = (int)($cfg["max_tags"] ?? 12);

  // If you have a TagX API endpoint:
  $url = $cfg["url"] ?? "https://studio1live.com/linkstorm/api/tagx.php";
  $headers = ["Content-Type"=>"application/json"];
  if (!empty($cfg["x_tagx_key"])) $headers["X-TagX-Key"] = $cfg["x_tagx_key"];

  $payload = [
    "text" => $text,
    "mode" => $cfg["mode"] ?? "hashtags",
    "max_tags" => $max
  ];

  $r = http_post_json($url, $headers, $payload);
  if (!$r["ok"]) return ["ok"=>false, "error"=>"TagX failed", "details"=>$r];

  // Expecting response like { tags: [...], tags_line:"#a #b" }
  $tagsLine = $r["json"]["tags_line"] ?? "";
  $tags = $r["json"]["tags"] ?? [];
  return ["ok"=>true, "tags_line"=>$tagsLine, "tags"=>$tags, "raw"=>$r["json"]];
}

// ---------- Publish to static site (uses your Site config) ----------
function publish_static(array $site, array $article): array {
  $slug = $article["meta"]["slug"] ?? slugify($article["title"]);
  $title = $article["title"];
  $body  = $article["body"];
  $tagsLine = $article["meta"]["tags_line"] ?? "";

  $dir = rtrim($site["publish_dir"], "/") . "/" . $slug;
  if (!is_dir($dir)) @mkdir($dir, 0755, true);

  $html = "<!doctype html><html><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'>".
          "<title>".htmlspecialchars($title)."</title></head><body style='font-family:system-ui;padding:20px;max-width:900px;margin:auto'>".
          "<h1>".htmlspecialchars($title)."</h1>".
          ($tagsLine ? "<p><strong>Tags:</strong> ".htmlspecialchars($tagsLine)."</p>" : "").
          "<div>".nl2br(htmlspecialchars($body))."</div>".
          "</body></html>";

  @file_put_contents($dir . "/index.html", $html);

  $url = rtrim($site["base_url"], "/") . "/" . $slug . "/";

  // update posts.json if configured
  $postsPath = $site["posts_json_path"] ?: "";
  if ($postsPath) {
    $posts = [];
    if (file_exists($postsPath)) {
      $posts = json_decode(file_get_contents($postsPath), true);
      if (!is_array($posts)) $posts = [];
    }
    $posts[] = [
      "id" => (int)$article["id"],
      "title" => $title,
      "slug" => $slug,
      "url" => $url,
      "created_at" => date("c")
    ];
    @file_put_contents($postsPath, json_encode($posts, JSON_PRETTY_PRINT));
  }

  return ["ok"=>true, "url"=>$url, "slug"=>$slug];
}

// ---------- Command router ----------
$b = read_json_body();
$msg = trim((string)($b["message"] ?? ""));
$sid = trim((string)($b["session_id"] ?? "default"));
if ($msg === "") j(false, ["error"=>"message required"], 400);

$state = load_state($sid);

// Commands:
// - write post about <topic>
// - publish latest
// - make share pack for latest (placeholder)
$lower = strtolower($msg);

if (preg_match('/^(write|write post|write a post|write an article|write article)\s+about\s+(.+)$/i', $msg, $m)) {
  $topic = trim($m[2]);

  $writer = db_get_tool("openai_writer");
  if (!$writer || (int)$writer["enabled"] !== 1) j(false, ["error"=>"openai_writer tool missing/disabled"], 400);

  // Generate full article body
  $prompt = "Write a publish-ready blog post about: ".$topic.". ".
            "Use headings, bullet points where helpful, and end with a short CTA. ".
            "Return plain text (no markdown fences).";

  $w = run_openai_chat($writer, $prompt);
  if (!$w["ok"]) j(false, ["error"=>"writer failed", "details"=>$w], 500);

  $title = "Quick Post: " . ucwords(substr($topic, 0, 80));
  $body  = $w["text"];

  // Create draft
  $meta = ["topic"=>$topic];
  $articleId = create_article($title, $body, $meta);
  if (!$articleId) j(false, ["error"=>"failed to create article"], 500);

  // Run TagX automatically (10 tags default)
  $tagx = db_get_tool("tagx_main");
  if ($tagx && (int)$tagx["enabled"] === 1) {
    $t = run_tagx($tagx, $body);
    $a = get_article($articleId);
    if ($a) {
      $a["meta"]["tags_line"] = $t["ok"] ? ($t["tags_line"] ?: "") : "";
      $a["meta"]["slug"] = slugify($topic);
      update_article_meta($articleId, $a["meta"]);
    }
  } else {
    // still set slug
    $a = get_article($articleId);
    if ($a) {
      $a["meta"]["slug"] = slugify($topic);
      update_article_meta($articleId, $a["meta"]);
    }
  }

  $state["last_article_id"] = $articleId;
  save_state($sid, $state);

  j(true, [
    "message" => "Created draft article #{$articleId} with full content ✅\nNext: say 'publish latest' or 'make share pack for latest'.",
    "article_id" => $articleId
  ]);
}

if ($lower === "publish latest" || $lower === "publish last" || $lower === "publish") {
  $id = (int)($state["last_article_id"] ?? 0);
  if (!$id) j(false, ["error"=>"No article found (write a post first)."], 400);

  $site = db_get_default_site();
  if (!$site) j(false, ["error"=>"No default site found. Add a Site first."], 400);

  $a = get_article($id);
  if (!$a) j(false, ["error"=>"Latest article id not found."], 400);

  $p = publish_static($site, $a);
  if (!$p["ok"]) j(false, ["error"=>"Publish failed", "details"=>$p], 500);

  j(true, [
    "message" => "Published article #{$id} ✅\nURL: ".$p["url"],
    "url" => $p["url"]
  ]);
}

if (strpos($lower, "help") === 0) {
  j(true, ["message" =>
    "Try:\n".
    "- write post about <topic>\n".
    "- publish latest\n".
    "- make share pack for latest (coming next)\n"
  ]);
}

// fallback: treat as a write request
j(true, ["message"=>"Try: 'write post about <topic>' or 'publish latest'. Type 'help' for commands."]);
