const {
  plugin: { store, scoped },
  ui: {
    openModal,
    Button,
    ButtonColors,
    ButtonLooks,
    TextBox,
    TextArea,
    ModalRoot,
    ModalHeader,
    ModalBody,
    ModalFooter,
    Header,
    HeaderTags,
    Text,
    TextTags,
    Divider,
    showToast,
    ToastColors,
    injectCss,
  },
} = shelter;

const UNSLOTH_DEFAULT_URL = "http://localhost:8000";
const UNSLOTH_MODEL = "default";

// ── Default settings ────────────────────────────────────────────
store.apiUrl ??= UNSLOTH_DEFAULT_URL;
store.apiKey ??= "";
store.model ??= UNSLOTH_MODEL;
store.maxTokens ??= 1024;
store.temperature ??= 0.7;

// ── Injected CSS for the button ─────────────────────────────────
const removeCss = injectCss(`
  [data-unsloth-chat-btn] {
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    width: 32px !important;
    height: 32px !important;
    min-width: 32px !important;
    border-radius: 8px !important;
    cursor: pointer !important;
    font-size: 16px !important;
    font-weight: 700 !important;
    color: var(--interactive-normal) !important;
    background: transparent !important;
    border: none !important;
    padding: 0 !important;
    transition: color 0.15s ease, background 0.15s ease !important;
    line-height: 1 !important;
    margin: 0 2px !important;
    order: 10 !important;
  }
  [data-unsloth-chat-btn]:hover {
    color: var(--interactive-hover) !important;
    background: var(--background-modifier-hover) !important;
  }
  [data-unsloth-chat-btn] svg {
    width: 20px !important;
    height: 20px !important;
  }
`);
scoped.onDispose(() => removeCss());

// ── Helper: find and fill the message input ─────────────────────
function setMessageInput(text) {
  // Find the Discord chat textarea
  const textarea = document.querySelector(
    'main [class*="channelTextArea"] textarea, ' +
    'main [class*="channelTextArea"] [role="textbox"], ' +
    '[class*="chat"] [class*="channelTextArea"] textarea, ' +
    '[class*="chat"] [class*="channelTextArea"] [role="textbox"]'
  );
  if (!textarea) return false;

  // The native textarea (or contenteditable div) inside
  const nativeInput = textarea.tagName === "TEXTAREA"
    ? textarea
    : textarea.querySelector("textarea");

  if (!nativeInput) return false;

  // Set the native value
  nativeInput.focus();
  nativeInput.value = text;

  // Dispatch an input event so React picks up the change
  const nativeInputEv = new Event("input", { bubbles: true, cancelable: true });
  nativeInput.dispatchEvent(nativeInputEv);

  // Also dispatch on the outer element if it's a contenteditable
  if (textarea !== nativeInput && textarea.isContentEditable) {
    textarea.textContent = text;
    textarea.dispatchEvent(new Event("input", { bubbles: true }));
  }

  return true;
}

// ── API call ────────────────────────────────────────────────────
async function callUnsloth(prompt) {
  const url = `${store.apiUrl.replace(/\/+$/, "")}/v1/chat/completions`;

  const headers = { "Content-Type": "application/json" };
  if (store.apiKey) {
    headers["Authorization"] = `Bearer ${store.apiKey}`;
  }

  const body = {
    model: store.model,
    messages: [{ role: "user", content: prompt }],
    stream: false,
    max_tokens: store.maxTokens,
    temperature: store.temperature,
  };

  const res = await fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
  });

  if (!res.ok) {
    let detail = `API returned ${res.status}`;
    try {
      const err = await res.json();
      detail = err.error?.message || err.detail || detail;
    } catch {}
    throw new Error(detail);
  }

  const data = await res.json();
  const text = data?.choices?.[0]?.message?.content || "";
  return text;
}

// ── The prompt modal ────────────────────────────────────────────
function PromptModal(props) {
  const [prompt, setPrompt] = shelter.solid.createSignal("");
  const [loading, setLoading] = shelter.solid.createSignal(false);
  const [error, setError] = shelter.solid.createSignal("");

  let inputRef = undefined;
  let confirmRef = undefined;

  shelter.solid.onMount(() => {
    if (inputRef) inputRef.focus();
  });

  async function handleSubmit() {
    const p = prompt().trim();
    if (!p) return;

    setLoading(true);
    setError("");

    try {
      const result = await callUnsloth(p);

      if (result) {
        const ok = setMessageInput(result);
        if (ok) {
          showToast({
            title: "Unsloth Chat",
            content: "Response inserted into message input!",
            color: ToastColors.SUCCESS,
          });
        } else {
          showToast({
            title: "Unsloth Chat",
            content: "Could not find message input. Response copied to clipboard.",
            color: ToastColors.WARNING,
          });
          try {
            await navigator.clipboard.writeText(result);
          } catch {}
        }
      } else {
        setError("The model returned an empty response.");
      }

      props.close();
    } catch (e) {
      setError(e.message || "An error occurred");
    } finally {
      setLoading(false);
    }
  }

  function handleKeyDown(e) {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault();
      handleSubmit();
    }
    if (e.key === "Escape") {
      props.close();
    }
  }

  return (
    <ModalRoot>
      <ModalHeader close={props.close}>Unsloth Studio</ModalHeader>
      <ModalBody>
        <Header tag={HeaderTags.HeadingSM} margin={false}>
          Prompt
        </Header>
        <div style={{ marginTop: "8px" }}>
          <TextArea
            ref={(el) => { inputRef = el; }}
            value={prompt()}
            placeholder="Ask the local LLM something..."
            onInput={(v) => setPrompt(v)}
            onKeyDown={handleKeyDown}
            resize-y={true}
            mono={false}
          />
        </div>
        {error() && (
          <div style={{
            marginTop: "8px",
            padding: "8px 12px",
            background: "var(--info-danger-background)",
            color: "var(--text-danger)",
            borderRadius: "4px",
            fontSize: "14px",
          }}>
            {error()}
          </div>
        )}
      </ModalBody>
      <ModalFooter>
        <div style={{ display: "flex", gap: "8px", justifyContent: "flex-end", width: "100%" }}>
          <Button
            look={ButtonLooks.FILLED}
            color={ButtonColors.PRIMARY}
            onClick={handleSubmit}
            disabled={loading() || !prompt().trim()}
          >
            {loading() ? "Generating..." : "Generate & Insert"}
          </Button>
        </div>
      </ModalFooter>
    </ModalRoot>
  );
}

// ── Insert the button into the chat bar ─────────────────────────
function injectButton() {
  // Look for the button row in the chat bar
  const buttonRow = document.querySelector(
    '[class*="channelTextArea"] [class*="buttons"], ' +
    '[class*="chat"] [class*="channelTextArea"] [class*="buttons"]'
  );

  if (!buttonRow || buttonRow.querySelector("[data-unsloth-chat-btn]")) return;

  const btn = document.createElement("button");
  btn.setAttribute("data-unsloth-chat-btn", "");
  btn.setAttribute("aria-label", "Unsloth Studio - Generate with AI");
  btn.setAttribute("tabindex", "0");
  btn.innerHTML = `
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
      <path d="M12 2a10 10 0 0 1 10 10c0 5-4 8-10 8S2 17 2 12 7 2 12 2z"/>
      <path d="M8 12h8"/>
      <path d="M12 8v8"/>
    </svg>
  `;
  btn.addEventListener("click", () => {
    openModal((p) => <PromptModal close={p.close} />);
  });

  buttonRow.appendChild(btn);
}

// ── DOM observer ────────────────────────────────────────────────
scoped.observeDom(
  '[class*="channelTextArea"] [class*="buttons"]',
  injectButton,
);

// ── Export settings component ───────────────────────────────────
export function settings() {
  const [apiUrl, setApiUrl] = shelter.solid.createSignal(store.apiUrl);
  const [apiKey, setApiKey] = shelter.solid.createSignal(store.apiKey);
  const [model, setModel] = shelter.solid.createSignal(store.model);
  const [maxTokens, setMaxTokens] = shelter.solid.createSignal(String(store.maxTokens));
  const [temperature, setTemperature] = shelter.solid.createSignal(String(store.temperature));

  function saveApiUrl(v) {
    setApiUrl(v);
    store.apiUrl = v;
  }
  function saveApiKey(v) {
    setApiKey(v);
    store.apiKey = v;
  }
  function saveModel(v) {
    setModel(v);
    store.model = v;
  }
  function saveMaxTokens(v) {
    setMaxTokens(v);
    const n = Number(v);
    if (!isNaN(n) && n > 0) store.maxTokens = n;
  }
  function saveTemperature(v) {
    setTemperature(v);
    const n = Number(v);
    if (!isNaN(n) && n >= 0 && n <= 2) store.temperature = n;
  }

  return (
    <div style={{ padding: "16px 0" }}>
      <Header tag={HeaderTags.HeadingLG}>Unsloth Studio Connection</Header>
      <Divider mt mb />

      <div style={{ marginBottom: "16px" }}>
        <Text tag={TextTags.textSM} style={{ marginBottom: "4px", display: "block" }}>
          API URL
        </Text>
        <TextBox
          value={apiUrl()}
          placeholder="http://localhost:8000"
          onInput={saveApiUrl}
        />
        <Text tag={TextTags.textXS} style={{ marginTop: "4px", color: "var(--text-muted)", display: "block" }}>
          The URL of your running Unsloth Studio instance.
        </Text>
      </div>

      <div style={{ marginBottom: "16px" }}>
        <Text tag={TextTags.textSM} style={{ marginBottom: "4px", display: "block" }}>
          API Key (optional)
        </Text>
        <TextBox
          value={apiKey()}
          placeholder="Leave blank if no auth required"
          onInput={saveApiKey}
        />
        <Text tag={TextTags.textXS} style={{ marginTop: "4px", color: "var(--text-muted)", display: "block" }}>
          Your Unsloth Studio API key/token for authenticated access.
        </Text>
      </div>

      <div style={{ marginBottom: "16px" }}>
        <Text tag={TextTags.textSM} style={{ marginBottom: "4px", display: "block" }}>
          Model
        </Text>
        <TextBox
          value={model()}
          placeholder="default"
          onInput={saveModel}
        />
      </div>

      <div style={{ marginBottom: "16px" }}>
        <Text tag={TextTags.textSM} style={{ marginBottom: "4px", display: "block" }}>
          Max Tokens
        </Text>
        <TextBox
          value={maxTokens()}
          placeholder="1024"
          onInput={saveMaxTokens}
        />
      </div>

      <div style={{ marginBottom: "16px" }}>
        <Text tag={TextTags.textSM} style={{ marginBottom: "4px", display: "block" }}>
          Temperature (0.0 - 2.0)
        </Text>
        <TextBox
          value={temperature()}
          placeholder="0.7"
          onInput={saveTemperature}
        />
      </div>
    </div>
  );
}
