/**
 * Shared helpers for Playwright E2E tests.
 *
 * Usage:
 *   import { setup, ws, panelSR, cleanup } from "./e2e-helpers.mjs";
 *   const { browser, page } = await setup({ mobile: false });
 */
import { chromium } from "playwright";

const HA = "http://homeassistant-dev:8123";

export async function getRefreshToken() {
  const http = await import("http");
  function post(path, body, contentType = "application/json") {
    return new Promise((resolve, reject) => {
      const data = typeof body === "string" ? body : JSON.stringify(body);
      const opts = {
        hostname: "localhost", port: 8125, path, method: "POST",
        headers: { "Content-Type": contentType, "Content-Length": Buffer.byteLength(data) },
      };
      const req = http.request(opts, (res) => {
        let d = "";
        res.on("data", (c) => (d += c));
        res.on("end", () => resolve(JSON.parse(d)));
      });
      req.on("error", reject);
      req.write(data);
      req.end();
    });
  }
  const flow = await post("/auth/login_flow", { client_id: `${HA}/`, handler: ["homeassistant", null], redirect_uri: `${HA}/` });
  const auth = await post(`/auth/login_flow/${flow.flow_id}`, { client_id: `${HA}/`, username: "dev", password: "dev" });
  const tokens = await post("/auth/token", `grant_type=authorization_code&code=${auth.result}&client_id=${HA}/`, "application/x-www-form-urlencoded");
  return tokens.refresh_token;
}

export async function setup({ mobile = false, timezone = undefined } = {}) {
  const refreshToken = process.env.HA_REFRESH_TOKEN || await getRefreshToken();
  const browser = await chromium.connect("ws://localhost:3000");
  const ctxOpts = {
    viewport: mobile ? { width: 375, height: 812 } : { width: 1280, height: 900 },
    locale: "en-US",
    colorScheme: "dark",
    ...(mobile ? { isMobile: true } : {}),
    ...(timezone ? { timezoneId: timezone } : {}),
  };
  const ctx = await browser.newContext(ctxOpts);
  const page = await ctx.newPage();

  await page.goto(HA);
  await page.waitForTimeout(1000);
  await page.evaluate((args) => {
    localStorage.setItem("hassTokens", JSON.stringify({
      hassUrl: args.ha, clientId: args.ha + "/",
      refresh_token: args.r, access_token: "",
      token_type: "Bearer", expires_in: 1800, expires: 0,
    }));
  }, { ha: HA, r: refreshToken });
  await page.goto(HA + "/maintenance-supporter");
  await page.waitForTimeout(7000);

  return { browser, ctx, page };
}

export async function ws(page, cmd) {
  return page.evaluate(async (c) => {
    const ha = document.querySelector("home-assistant");
    if (!ha?.hass?.connection) throw new Error("no hass connection");
    try {
      return await ha.hass.connection.sendMessagePromise(c);
    } catch (e) {
      // Surface backend errors as readable JSON
      throw new Error("WS error: " + JSON.stringify(e));
    }
  }, cmd);
}

export function panelSR(page) {
  return page.evaluate(() => {
    const ha = document.querySelector("home-assistant");
    const main = ha?.shadowRoot?.querySelector("home-assistant-main");
    const drawer = main?.shadowRoot?.querySelector("ha-drawer");
    const resolver = drawer?.querySelector("partial-panel-resolver");
    const custom = resolver?.querySelector("ha-panel-custom");
    const panel = custom?.querySelector("maintenance-supporter-panel");
    return !!panel?.shadowRoot;
  });
}

const PANEL_EVAL = "window._ha=document.querySelector('home-assistant');window._main=_ha.shadowRoot.querySelector('home-assistant-main');window._drawer=_main.shadowRoot.querySelector('ha-drawer');window._resolver=_drawer.querySelector('partial-panel-resolver');window._custom=_resolver.querySelector('ha-panel-custom');window._panel=_custom.querySelector('maintenance-supporter-panel');window._sr=_panel.shadowRoot;";

export async function openEditDialog(page, entryId, task) {
  await page.evaluate(({ eid, task, fn }) => {
    eval(fn);
    window._sr.querySelector("maintenance-task-dialog").openEdit(eid, task);
  }, { eid: entryId, task, fn: PANEL_EVAL });
  await page.waitForTimeout(1500);
}

export async function readDialogSelects(page) {
  return page.evaluate(({ fn }) => {
    eval(fn);
    const dlgSr = window._sr?.querySelector("maintenance-task-dialog")?.shadowRoot;
    if (!dlgSr) return [];
    return [...dlgSr.querySelectorAll("select")].map((sel) => {
      const label = sel.closest(".select-row")?.querySelector("label")?.textContent?.trim() || "unknown";
      const selected = [...sel.options].find((o) => o.selected);
      return { label, value: sel.value, selectedValue: selected?.value, match: sel.value === selected?.value };
    });
  }, { fn: PANEL_EVAL });
}

export async function readDialogFields(page) {
  return page.evaluate(({ fn }) => {
    eval(fn);
    const dlgSr = window._sr?.querySelector("maintenance-task-dialog")?.shadowRoot;
    if (!dlgSr) return [];
    return [...dlgSr.querySelectorAll("ha-textfield")].map((f) => ({
      label: f.getAttribute("label"), type: f.getAttribute("type"), value: f.value,
    }));
  }, { fn: PANEL_EVAL });
}

export async function cleanup(browser, ctx) {
  try { await ctx.close(); } catch { /* ignore */ }
  try { await browser.close(); } catch { /* ignore */ }
}
