(ns ajet-chat.e2e.debug-sse
  (:require [ajet-chat.e2e.setup :as setup]
            [ajet-chat.e2e.helpers :as h]
            [ajet-chat.e2e.config :as config]
            [promesa.core :as p]))

(-> (p/let [oauth-creds (setup/setup-gitea-and-provider!)
            browser (h/launch-browser!)
            context (h/new-context! browser)
            page (h/new-page! context)]
      (p/do
        ;; Full setup wizard (add provider + create community)
        (h/goto page "/")
        (h/wait-for-url page #"/setup" {:timeout 10000})
        (h/wait-for-selector page "select[name='provider-type']")
        (h/select-option page "select[name='provider-type']" "gitea")
        (h/fill page "input[name='display-name']" "Gitea Test")
        (h/fill page "input[name='slug']" "gitea-test")
        (h/fill page "input[name='client-id']" (:client-id oauth-creds))
        (h/fill page "input[name='client-secret']" (:client-secret oauth-creds))
        (h/fill page "input[name='base-url']" config/gitea-url)
        (h/click page "button:has-text('Add Provider')")
        (h/wait-for-url page #"/auth/login" {:timeout 10000})

        ;; Login via Gitea
        (h/click page "a[href*='provider=gitea-test']")
        (h/wait-for-selector page "#user_name" {:timeout 15000})
        (h/fill page "#user_name" (:username config/test-user-a))
        (h/fill page "#password" (:password config/test-user-a))
        (h/click page "button:has-text('Sign In')")
        (p/let [auth-btn (p/catch
                           (.waitForSelector page "button:has-text('Authorize Application'), button.ui.green.button"
                                             #js {:timeout 5000})
                           (fn [_] nil))]
          (when auth-btn (.click auth-btn)))
        (h/wait-for-url page #"/(setup|app)" {:timeout 30000})

        ;; Create community if on /setup
        (p/let [url (h/page-url page)]
          (when (re-find #"/setup" url)
            (p/do
              (h/wait-for-selector page "input[name='name']")
              (h/wait-ms 1500)
              (h/type-text page "input[name='name']" "Debug SSE Community")
              (h/type-text page "input[name='slug']" "debug-sse")
              (h/click page "button[type='submit']")
              (h/wait-ms 2000))))
        (h/wait-for-url page #"/app" {:timeout 15000})
        (js/console.log "\n=== On /app ===")

        ;; Wait for page to fully load including Datastar SDK
        (h/wait-ms 5000)

        ;; Check 1: Is Datastar loaded?
        (p/let [ds-check (h/evaluate page
                           "(() => {
                              const results = {};
                              results.hasDatastarAttr = !!document.querySelector('[data-signals]');
                              results.moduleScripts = Array.from(document.querySelectorAll('script[type=\"module\"]')).map(s => s.src);
                              results.title = document.title;
                              results.hasEventSource = typeof EventSource !== 'undefined';
                              results.resourceEntries = performance.getEntriesByType('resource')
                                .filter(r => r.name.includes('sse') || r.name.includes('datastar') || r.name.includes('tailwind'))
                                .map(r => ({name: r.name.split('/').pop(), duration: Math.round(r.duration), status: r.responseStatus}));
                              return results;
                            })()")]
          (js/console.log "Check 1 - Datastar/CDN:" (js/JSON.stringify (clj->js ds-check) nil 2)))

        ;; Check 2: App state element
        (p/let [app-state (h/evaluate page
                            "(() => {
                               const el = document.getElementById('app-state');
                               if (!el) return {found: false};
                               return {
                                 found: true,
                                 dataOnLoad: el.getAttribute('data-on-load'),
                                 children: el.childElementCount
                               };
                             })()")]
          (js/console.log "Check 2 - App state:" (js/JSON.stringify (clj->js app-state))))

        ;; Check 3: SSE manual test
        (p/let [sse-test (h/evaluate page
                           "new Promise((resolve) => {
                              const ctrl = new AbortController();
                              setTimeout(() => ctrl.abort(), 5000);
                              fetch('/sse/events', {signal: ctrl.signal, headers: {'Accept': 'text/event-stream'}})
                                .then(r => {
                                  const reader = r.body.getReader();
                                  const decoder = new TextDecoder();
                                  let data = '';
                                  function read() {
                                    reader.read().then(({done, value}) => {
                                      if (done) { resolve({status: r.status, data}); return; }
                                      data += decoder.decode(value, {stream: true});
                                      if (data.length > 500) { ctrl.abort(); resolve({status: r.status, data: data.substring(0, 500)}); return; }
                                      read();
                                    }).catch(e => resolve({status: r.status, data, aborted: true}));
                                  }
                                  read();
                                })
                                .catch(e => resolve({error: e.message}));
                            })")]
          (js/console.log "Check 3 - SSE manual:" (js/JSON.stringify (clj->js sse-test) nil 2)))

        ;; Check 4: Send a message and see if it appears
        (p/let [ch-el (.waitForSelector page "[id^='sidebar-channel-']"
                                        #js {:timeout 5000})
                ch-el-id (when ch-el (.getAttribute ch-el "id"))
                channel-id (.replace ch-el-id "sidebar-channel-" "")]
          (js/console.log "\nChannel ID:" channel-id)

          ;; Send a message
          (p/let [send-result (h/send-message! page channel-id "Debug SSE test message")]
            (js/console.log "Send result:" (js/JSON.stringify (clj->js send-result))))

          ;; Wait for message to appear via SSE
          (p/let [found (p/catch
                          (p/do
                            (h/wait-for-text page "Debug SSE test message" {:timeout 10000})
                            true)
                          (fn [_] false))]
            (js/console.log "Message visible via SSE:" found))

          ;; If not found, try page reload
          (p/let [_ (h/goto page "/app")
                  _ (h/wait-for-url page #"/app" {:timeout 5000})
                  _ (h/wait-ms 2000)
                  found-reload (p/catch
                                 (p/do
                                   (h/wait-for-text page "Debug SSE test message" {:timeout 10000})
                                   true)
                                 (fn [_] false))]
            (js/console.log "Message visible after reload:" found-reload)))

        (h/close-all! browser)))
    (.catch (fn [e]
              (js/console.error "Error:" (.-message e))))
    (.then (fn [_] (js/process.exit 0))))
