/**
 * Adapter System — Auto-detect AI platform and provide DOM interaction methods
 * Slim port from MCP-SuperAssistant adapter pattern
 */
import type { AdapterPlugin, AdapterCapability } from "./types"
import { createLogger } from "./logger"

const logger = createLogger("Adapter")

// ─── Base Adapter ───────────────────────────────────────────────────

export abstract class BaseAdapter implements AdapterPlugin {
  abstract readonly name: string
  abstract readonly version: string
  abstract readonly hostnames: (string | RegExp)[]
  abstract readonly capabilities: AdapterCapability[]

  protected status: AdapterPlugin["getStatus"] extends () => infer R ? R : never = "pending"

  async initialize(): Promise<void> {
    this.status = "initializing"
    logger.info(`Initializing adapter: ${this.name}`)
    this.status = "inactive"
  }

  async activate(): Promise<void> {
    this.status = "active"
    logger.info(`Adapter activated: ${this.name}`)
  }

  async deactivate(): Promise<void> {
    this.status = "inactive"
  }

  async cleanup(): Promise<void> {
    this.status = "disabled"
  }

  async insertText(_text: string, _options?: { targetElement?: HTMLElement }): Promise<boolean> {
    return false
  }

  async submitForm(_options?: { formElement?: HTMLFormElement }): Promise<boolean> {
    return false
  }

  getStatus() {
    return this.status
  }

  isSupported(): boolean {
    return true
  }
}

// ─── ChatGPT Adapter ────────────────────────────────────────────────

export class ChatGPTAdapter extends BaseAdapter {
  readonly name = "ChatGPT"
  readonly version = "1.0.0"
  readonly hostnames = ["chatgpt.com", "chat.openai.com"]
  readonly capabilities: AdapterCapability[] = ["text-insertion", "form-submission"]

  async insertText(text: string): Promise<boolean> {
    try {
      // ChatGPT uses a contenteditable div with id="prompt-textarea" or similar
      const textarea =
        document.querySelector<HTMLElement>("#prompt-textarea") ||
        document.querySelector<HTMLElement>('[contenteditable="true"]') ||
        document.querySelector<HTMLTextAreaElement>("textarea")

      if (!textarea) {
        logger.error("ChatGPT textarea not found")
        return false
      }

      if (textarea instanceof HTMLTextAreaElement) {
        // Standard textarea
        const nativeSet = Object.getOwnPropertyDescriptor(
          HTMLTextAreaElement.prototype, "value"
        )?.set
        nativeSet?.call(textarea, text)
        textarea.dispatchEvent(new Event("input", { bubbles: true }))
      } else {
        // Contenteditable div
        textarea.focus()
        textarea.innerHTML = ""
        // Use execCommand for contenteditable (triggers React state update)
        document.execCommand("insertText", false, text)
      }

      logger.info("Text inserted into ChatGPT")
      return true
    } catch (err) {
      logger.error("insertText failed:", err)
      return false
    }
  }

  async submitForm(): Promise<boolean> {
    try {
      // ChatGPT send button
      const sendBtn =
        document.querySelector<HTMLButtonElement>('[data-testid="send-button"]') ||
        document.querySelector<HTMLButtonElement>('button[aria-label="Send prompt"]') ||
        document.querySelector<HTMLButtonElement>("form button:last-of-type")

      if (sendBtn && !sendBtn.disabled) {
        sendBtn.click()
        logger.info("ChatGPT form submitted")
        return true
      }

      // Fallback: press Enter in textarea
      const textarea = document.querySelector<HTMLElement>("#prompt-textarea")
      if (textarea) {
        textarea.dispatchEvent(
          new KeyboardEvent("keydown", { key: "Enter", bubbles: true })
        )
        return true
      }

      return false
    } catch (err) {
      logger.error("submitForm failed:", err)
      return false
    }
  }
}

// ─── Gemini Adapter ─────────────────────────────────────────────────

export class GeminiAdapter extends BaseAdapter {
  readonly name = "Gemini"
  readonly version = "1.0.0"
  readonly hostnames = ["gemini.google.com"]
  readonly capabilities: AdapterCapability[] = ["text-insertion", "form-submission"]

  async insertText(text: string): Promise<boolean> {
    try {
      const editor =
        document.querySelector<HTMLElement>(".ql-editor") ||
        document.querySelector<HTMLElement>('[contenteditable="true"]') ||
        document.querySelector<HTMLTextAreaElement>("textarea")

      if (!editor) return false

      if (editor instanceof HTMLTextAreaElement) {
        editor.value = text
        editor.dispatchEvent(new Event("input", { bubbles: true }))
      } else {
        editor.focus()
        editor.innerHTML = `<p>${text}</p>`
        editor.dispatchEvent(new Event("input", { bubbles: true }))
      }

      return true
    } catch {
      return false
    }
  }

  async submitForm(): Promise<boolean> {
    try {
      const btn =
        document.querySelector<HTMLButtonElement>('button[aria-label="Send message"]') ||
        document.querySelector<HTMLButtonElement>(".send-button")

      if (btn) {
        btn.click()
        return true
      }
      return false
    } catch {
      return false
    }
  }
}

// ─── Registry ───────────────────────────────────────────────────────

const ADAPTERS: BaseAdapter[] = [
  new ChatGPTAdapter(),
  new GeminiAdapter(),
]

/** Auto-detect which adapter matches the current hostname */
export function detectAdapter(): BaseAdapter | null {
  const hostname = window.location.hostname.toLowerCase()

  for (const adapter of ADAPTERS) {
    for (const pattern of adapter.hostnames) {
      if (typeof pattern === "string") {
        if (hostname.includes(pattern)) return adapter
      } else if (pattern.test(hostname)) {
        return adapter
      }
    }
  }

  logger.info(`No adapter found for hostname: ${hostname}`)
  return null
}

/** Get all registered adapter names */
export function getAdapterNames(): string[] {
  return ADAPTERS.map((a) => a.name)
}
