import { api } from '../../api/client'
import { registerIslanderActionHandler } from './actionExecutor'
import { findElementByLabel } from './pageSnapshot'
import type { IslanderAction, IslanderExecutorContext } from './types'

export type OutreachDraftData = {
  id: string
  scan_post_id: string
  relevance: number
  reason: string
  drafts: Array<{ text: string; angle: string; rationale: string }>
  create_at: number
}

export const OUTREACH_DRAFT_LABEL = '獲客留言草稿'
export const OUTREACH_DRAFT_EVENT = 'haixun.outreach-draft-generated'

let brandId = ''
let generateDraft: ((scanPostId: string, count?: number) => Promise<OutreachDraftData | null>) | null =
  null
let publishOutreachFn:
  | ((scanPostId: string, text: string) => Promise<{ message: string } | null>)
  | null = null
let patchOutreachFn:
  | ((scanPostId: string, status: string) => Promise<unknown | null>)
  | null = null

export function bindOutreachIslanderActions(opts: {
  brandId: string
  generate: (scanPostId: string, count?: number) => Promise<OutreachDraftData | null>
  publish?: (scanPostId: string, text: string) => Promise<{ message: string } | null>
  patchOutreach?: (scanPostId: string, status: string) => Promise<unknown | null>
}) {
  brandId = opts.brandId
  generateDraft = opts.generate
  publishOutreachFn = opts.publish ?? null
  patchOutreachFn = opts.patchOutreach ?? null
}

export function unbindOutreachIslanderActions() {
  brandId = ''
  generateDraft = null
  publishOutreachFn = null
  patchOutreachFn = null
}

function setNativeValue(el: HTMLInputElement | HTMLTextAreaElement, value: string) {
  const proto =
    el instanceof HTMLTextAreaElement
      ? window.HTMLTextAreaElement.prototype
      : window.HTMLInputElement.prototype
  const setter = Object.getOwnPropertyDescriptor(proto, 'value')?.set
  const previous = el.value
  setter?.call(el, value)
  const tracker = (el as HTMLInputElement & { _valueTracker?: { setValue: (v: string) => void } })
    ._valueTracker
  if (tracker) {
    tracker.setValue(previous)
  }
  el.dispatchEvent(new Event('input', { bubbles: true }))
  el.dispatchEvent(new Event('change', { bubbles: true }))
}

function applyDraftToField(label: string, value: string, ctx: IslanderExecutorContext): boolean {
  const byLabel = findElementByLabel(label)
  if (byLabel instanceof HTMLTextAreaElement || byLabel instanceof HTMLInputElement) {
    byLabel.scrollIntoView({ block: 'center', behavior: 'smooth' })
    if ('focus' in byLabel && typeof byLabel.focus === 'function') byLabel.focus()
    setNativeValue(byLabel, value)
    ctx.highlight(byLabel)
    return true
  }
  return false
}

let registered = false

export function ensureOutreachActionHandlers() {
  if (registered) return
  registered = true

  registerIslanderActionHandler('generateOutreachReply', async (action, ctx) => {
    const typed = action as Extract<IslanderAction, { type: 'generateOutreachReply' }>
    if (!brandId || !generateDraft) {
      return {
        action,
        ok: false,
        detail: '請在獲客台頁面使用此操作',
      }
    }
    try {
      const data = await generateDraft(typed.scan_post_id, typed.count)
      if (!data || data.drafts.length === 0) {
        return { action, ok: false, detail: '未產生留言草稿' }
      }
      const primary = data.drafts[0]?.text ?? ''
      window.dispatchEvent(
        new CustomEvent(OUTREACH_DRAFT_EVENT, {
          detail: { scanPostId: typed.scan_post_id, draft: data },
        }),
      )
      if (primary) {
        applyDraftToField(OUTREACH_DRAFT_LABEL, primary, ctx)
      }
      return {
        action,
        ok: true,
        detail: `已產生 ${data.drafts.length} 則草稿（相關度 ${Math.round(data.relevance * 100)}%）`,
      }
    } catch (e) {
      const message = e instanceof Error ? e.message : '產生草稿失敗'
      return { action, ok: false, detail: message }
    }
  })

  registerIslanderActionHandler('applyDraft', async (action, ctx) => {
    const typed = action as Extract<IslanderAction, { type: 'applyDraft' }>
    const label = typed.label?.trim() || OUTREACH_DRAFT_LABEL
    const ok = applyDraftToField(label, typed.value, ctx)
    return {
      action,
      ok,
      detail: ok ? '已填入留言草稿' : '找不到留言草稿欄位',
    }
  })

  registerIslanderActionHandler('publishOutreach', async (action) => {
    const typed = action as Extract<IslanderAction, { type: 'publishOutreach' }>
    if (!brandId || !publishOutreachFn) {
      return { action, ok: false, detail: '請在獲客台頁面使用此操作' }
    }
    if (!typed.confirm) {
      return { action, ok: false, detail: '發送留言需 confirm=true' }
    }
    try {
      const result = await publishOutreachFn(typed.scan_post_id, typed.text)
      if (!result) {
        return { action, ok: false, detail: '發送留言失敗' }
      }
      return { action, ok: true, detail: result.message || '獲客留言已發送' }
    } catch (e) {
      const message = e instanceof Error ? e.message : '發送留言失敗'
      return { action, ok: false, detail: message }
    }
  })

  registerIslanderActionHandler('markHandled', async (action) => {
    const typed = action as Extract<IslanderAction, { type: 'markHandled' }>
    if (!brandId || !patchOutreachFn) {
      return { action, ok: false, detail: '請在獲客台頁面使用此操作' }
    }
    const status = typed.status ?? 'handled'
    try {
      await patchOutreachFn(typed.scan_post_id, status)
      return { action, ok: true, detail: `已標記為 ${status}` }
    } catch (e) {
      const message = e instanceof Error ? e.message : '更新狀態失敗'
      return { action, ok: false, detail: message }
    }
  })
}

/** Standalone generate for pages without bound handler (fallback). */
export async function generateOutreachDraftRemote(
  topicId: string,
  scanPostId: string,
  count = 2,
  voicePersonaId?: string,
  productId?: string,
): Promise<OutreachDraftData> {
  return api.post<OutreachDraftData>(
    `/api/v1/placement/topics/${encodeURIComponent(topicId)}/outreach-drafts/generate`,
    {
      scan_post_id: scanPostId,
      count,
      voice_persona_id: voicePersonaId?.trim() || undefined,
      product_id: productId?.trim() || undefined,
    },
    { auth: true },
  )
}
