import type { SaeeolClient } from "@saeeol/sdk/v2"
import { Flag } from "@saeeol/core/flag/flag"
import { Agent } from "@/agent/agent"
import { AppRuntime } from "@/effect/app-runtime"
import { UI } from "../ui"
import { importCloudSession, validateCloudFork } from "@/saeeol/cloud-session"
import { SaeeolRunAuto } from "@/saeeol/cli/run-auto"

export type SessionDeps = {
  sdk: SaeeolClient
  args: {
    continue?: boolean
    session?: string
    cloudFork?: boolean
    fork?: boolean
    title?: string
    share?: boolean
    model?: string
    agent?: string
    variant?: string
    attach?: string
    command?: string
    format: string
    thinking: boolean
    auto: boolean
  }
  message: string
}

export async function resolveSessionID(
  sdk: SaeeolClient,
  opts: { continue?: boolean; session?: string; cloudFork?: boolean; fork?: boolean; title?: string; message: string },
) {
  const rules = [
    { permission: "question", action: "deny", pattern: "*" },
    { permission: "plan_enter", action: "deny", pattern: "*" },
    { permission: "plan_exit", action: "deny", pattern: "*" },
  ]
  const baseID = opts.continue
    ? (await sdk.session.list()).data?.find((s) => !s.parentID)?.id
    : opts.session

  if (baseID && opts.cloudFork) {
    const id = await importCloudSession(sdk, baseID).catch(() => undefined)
    if (!id) { UI.error("Failed to import session from cloud"); process.exit(1) }
    return id
  }

  if (baseID && opts.fork) {
    const forked = await sdk.session.fork({ sessionID: baseID })
    return forked.data?.id
  }

  if (baseID) return baseID

  const title = (() => {
    if (opts.title === undefined) return undefined
    if (opts.title !== "") return opts.title
    return opts.message.slice(0, 50) + (opts.message.length > 50 ? "..." : "")
  })()

  const result = await sdk.session.create({ title, permission: rules as any })
  return result.data?.id
}

export async function shareSession(sdk: SaeeolClient, sessionID: string, shouldShare?: boolean) {
  const cfg = await sdk.config.get()
  if (!cfg.data) return
  if (cfg.data.share !== "auto" && !Flag.SAEEOL_AUTO_SHARE && !shouldShare) return
  const res = await sdk.session.share({ sessionID }).catch((error) => {
    if (error instanceof Error && error.message.includes("disabled")) {
      UI.println(UI.Style.TEXT_DANGER_BOLD + "!  " + error.message)
    }
    return { error }
  })
  if (!res.error && "data" in res && res.data?.share?.url) {
    UI.println(UI.Style.TEXT_INFO_BOLD + "~  " + res.data.share.url)
  }
}

export async function resolveAgent(
  sdk: SaeeolClient | undefined,
  name: string | undefined,
  attach: string | undefined,
) {
  if (!name) return undefined

  if (attach && sdk) {
    const modes = await sdk.app
      .agents(undefined, { throwOnError: true })
      .then((x) => x.data ?? [])
      .catch(() => undefined)

    if (!modes) {
      UI.println(
        UI.Style.TEXT_WARNING_BOLD + "!",
        UI.Style.TEXT_NORMAL,
        `failed to list agents from ${attach}. Falling back to default agent`,
      )
      return undefined
    }

    const agent = modes.find((a) => a.name === name)
    if (!agent) {
      UI.println(
        UI.Style.TEXT_WARNING_BOLD + "!",
        UI.Style.TEXT_NORMAL,
        `agent "${name}" not found. Falling back to default agent`,
      )
      return undefined
    }

    if (agent.mode === "subagent") {
      UI.println(
        UI.Style.TEXT_WARNING_BOLD + "!",
        UI.Style.TEXT_NORMAL,
        `agent "${name}" is a subagent, not a primary agent. Falling back to default agent`,
      )
      return undefined
    }

    return name
  }

  const entry = await AppRuntime.runPromise(Agent.Service.use((svc) => svc.get(name)))
  if (!entry) {
    UI.println(
      UI.Style.TEXT_WARNING_BOLD + "!",
      UI.Style.TEXT_NORMAL,
      `agent "${name}" not found. Falling back to default agent`,
    )
    return undefined
  }
  if (entry.mode === "subagent") {
    UI.println(
      UI.Style.TEXT_WARNING_BOLD + "!",
      UI.Style.TEXT_NORMAL,
      `agent "${name}" is a subagent, not a primary agent. Falling back to default agent`,
    )
    return undefined
  }
  return name
}
