import {apiFetch} from "./config.js";
import {WORKSTREAM_STATUSES} from "./workplan-status.js";

const STYLE_ID = "status-control-styles";

export const TASK_STATUSES = ["wait", "todo", "progress", "done", "cancel"];
export {WORKSTREAM_STATUSES};

function ensureStyles() {
  if (typeof document === "undefined" || document.getElementById(STYLE_ID)) return;
  const style = document.createElement("style");
  style.id = STYLE_ID;
  style.textContent = `
.status-control {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  max-width: 100%;
}
.status-control-select {
  min-width: 8.5rem;
  max-width: 100%;
  height: 1.85rem;
  border: 1px solid var(--theme-foreground-faint, #d1d5db);
  border-radius: 6px;
  background: var(--theme-background, #fff);
  color: var(--theme-foreground, #111);
  font: inherit;
  font-size: 0.82rem;
  padding: 0.18rem 0.45rem;
}
.status-control-select:disabled {
  opacity: 0.65;
}
.status-control-message {
  min-width: 3.5rem;
  font-size: 0.72rem;
  color: var(--theme-foreground-muted, #6b7280);
  white-space: nowrap;
}
.status-control-message.status-control-error {
  color: #dc2626;
}
.status-control-message.status-control-ok {
  color: #16a34a;
}
.status-control-message.status-control-review {
  color: #b45309;
}
`;
  document.head.append(style);
}

function labelForStatus(status) {
  return String(status ?? "").replace(/_/g, " ");
}

async function readError(response) {
  try {
    const body = await response.json();
    if (Array.isArray(body?.detail)) return body.detail.map(d => d.msg ?? String(d)).join("; ");
    return body?.detail ?? `HTTP ${response.status}`;
  } catch {
    return `HTTP ${response.status}`;
  }
}

async function reconcileStatusChange({
  entity,
  type,
  currentStatus,
  nextStatus,
  blockingReason = null,
}) {
  const response = await apiFetch("/reconciliation/state-change", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
      target_type: type,
      target_id: entity.id,
      target_status: nextStatus,
      actor: "dashboard",
      intent: `${type} status change via dashboard`,
      expected_current_status: currentStatus,
      blocking_reason: blockingReason,
      apply: true,
    }),
  });
  if (!response.ok) throw new Error(await readError(response));
  return response.json();
}

function messageForReconciliation(result) {
  if (result.conflict) return {text: "out of sync", kind: "review"};
  if (result.write_through_result === "applied") return {text: "synced", kind: "ok"};
  if (result.reconciliation_class === "human_confirmation") return {text: "needs review", kind: "review"};
  if (result.reconciliation_class === "deferred") return {text: "queued", kind: ""};
  return {text: "unchanged", kind: ""};
}

export function statusControl({
  entity,
  type,
  statuses = type === "task" ? TASK_STATUSES : WORKSTREAM_STATUSES,
  onSaved = null,
} = {}) {
  ensureStyles();

  let currentStatus = entity?.status ?? "";
  const root = document.createElement("span");
  root.className = "status-control";
  root.addEventListener("click", event => event.stopPropagation());
  root.addEventListener("mousedown", event => event.stopPropagation());

  const select = document.createElement("select");
  select.className = "status-control-select";
  select.setAttribute("aria-label", "Status");
  for (const status of statuses) {
    const option = document.createElement("option");
    option.value = status;
    option.textContent = labelForStatus(status);
    select.append(option);
  }
  select.value = currentStatus;

  const message = document.createElement("span");
  message.className = "status-control-message";

  function setMessage(text, kind = "") {
    message.textContent = text;
    message.classList.toggle("status-control-error", kind === "error");
    message.classList.toggle("status-control-ok", kind === "ok");
    message.classList.toggle("status-control-review", kind === "review");
  }

  select.addEventListener("change", async () => {
    const nextStatus = select.value;
    if (nextStatus === currentStatus) return;

    let blockingReason = null;
    if (type === "task" && nextStatus === "wait") {
      const existingReason = entity?.blocking_reason ?? "";
      const reason = existingReason || window.prompt("Reason this task is waiting:");
      if (!reason) {
        select.value = currentStatus;
        setMessage("unchanged");
        return;
      }
      blockingReason = reason;
    }

    if (type === "task" && nextStatus === "done" && currentStatus !== "done") {
      const ok = window.confirm(
        "Mark this task done? State Hub will reconcile the workplan file before updating cached state."
      );
      if (!ok) {
        select.value = currentStatus;
        setMessage("unchanged");
        return;
      }
    }

    select.disabled = true;
    setMessage("saving");
    try {
      const result = await reconcileStatusChange({
        entity,
        type,
        currentStatus,
        nextStatus,
        blockingReason,
      });
      const messageResult = messageForReconciliation(result);
      if (result.write_through_result === "applied") {
        Object.assign(entity, {status: result.target_status});
        if (blockingReason !== null) entity.blocking_reason = blockingReason;
        currentStatus = result.target_status;
        select.value = currentStatus;
        if (typeof onSaved === "function") onSaved(entity, result);
      } else {
        select.value = currentStatus;
      }
      setMessage(messageResult.text, messageResult.kind);
      setTimeout(() => {
        if (message.textContent === messageResult.text) setMessage("");
      }, 2200);
    } catch (error) {
      select.value = currentStatus;
      setMessage(error?.message ?? "save failed", "error");
    } finally {
      select.disabled = false;
    }
  });

  root.append(select, message);
  return root;
}
