import axios from 'axios'
import { z } from 'zod/v4'
import { getOauthConfig } from '../../constants/oauth.js'
import { getFeatureValue_CACHED_MAY_BE_STALE } from '../../services/analytics/growthbook.js'
import { getOrganizationUUID } from '../../services/oauth/client.js'
import { isPolicyAllowed } from '../../services/policyLimits/index.js'
import type { ToolUseContext } from '../../Tool.js'
import { buildTool, type ToolDef } from '../../Tool.js'
import {
  checkAndRefreshOAuthTokenIfNeeded,
  getClaudeAIOAuthTokens,
} from '../../utils/auth.js'
import { lazySchema } from '../../utils/lazySchema.js'
import { jsonStringify } from '../../utils/slowOperations.js'
import { DESCRIPTION, PROMPT, REMOTE_TRIGGER_TOOL_NAME } from './prompt.js'
import { renderToolResultMessage, renderToolUseMessage } from './UI.js'

const inputSchema = lazySchema(() =>
  z.strictObject({
    action: z.enum(['list', 'get', 'create', 'update', 'run']),
    trigger_id: z
      .string()
      .regex(/^[\w-]+$/)
      .optional()
      .describe('Required for get, update, and run'),
    body: z
      .record(z.string(), z.unknown())
      .optional()
      .describe('JSON body for create and update'),
  }),
)
type InputSchema = ReturnType<typeof inputSchema>
export type Input = z.infer<InputSchema>

const outputSchema = lazySchema(() =>
  z.object({
    status: z.number(),
    json: z.string(),
  }),
)
type OutputSchema = ReturnType<typeof outputSchema>
export type Output = z.infer<OutputSchema>

const TRIGGERS_BETA = 'ccr-triggers-2026-01-30'

export const RemoteTriggerTool = buildTool({
  name: REMOTE_TRIGGER_TOOL_NAME,
  searchHint: 'manage scheduled remote agent triggers',
  maxResultSizeChars: 100_000,
  shouldDefer: true,
  get inputSchema(): InputSchema {
    return inputSchema()
  },
  get outputSchema(): OutputSchema {
    return outputSchema()
  },
  isEnabled() {
    return (
      getFeatureValue_CACHED_MAY_BE_STALE('tengu_surreal_dali', false) &&
      isPolicyAllowed('allow_remote_sessions')
    )
  },
  isConcurrencySafe() {
    return true
  },
  isReadOnly(input: Input) {
    return input.action === 'list' || input.action === 'get'
  },
  toAutoClassifierInput(input: Input) {
    return `RemoteTrigger ${input.action}${input.trigger_id ? ` ${input.trigger_id}` : ''}`
  },
  async description() {
    return DESCRIPTION
  },
  async prompt() {
    return PROMPT
  },
  async call(input: Input, context: ToolUseContext) {
    await checkAndRefreshOAuthTokenIfNeeded()
    const accessToken = getClaudeAIOAuthTokens()?.accessToken
    if (!accessToken) {
      throw new Error(
        'Not authenticated with a sandcode.sh account. Run /login and try again.',
      )
    }
    const orgUUID = await getOrganizationUUID()
    if (!orgUUID) {
      throw new Error('Unable to resolve organization UUID.')
    }

    const base = `${getOauthConfig().BASE_API_URL}/v1/code/triggers`
    const headers = {
      Authorization: `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
      'anthropic-version': '2023-06-01',
      'anthropic-beta': TRIGGERS_BETA,
      'x-organization-uuid': orgUUID,
    }

    const { action, trigger_id, body } = input
    let method: 'GET' | 'POST'
    let url: string
    let data: unknown
    switch (action) {
      case 'list':
        method = 'GET'
        url = base
        break
      case 'get':
        if (!trigger_id) throw new Error('get requires trigger_id')
        method = 'GET'
        url = `${base}/${trigger_id}`
        break
      case 'create':
        if (!body) throw new Error('create requires body')
        method = 'POST'
        url = base
        data = body
        break
      case 'update':
        if (!trigger_id) throw new Error('update requires trigger_id')
        if (!body) throw new Error('update requires body')
        method = 'POST'
        url = `${base}/${trigger_id}`
        data = body
        break
      case 'run':
        if (!trigger_id) throw new Error('run requires trigger_id')
        method = 'POST'
        url = `${base}/${trigger_id}/run`
        data = {}
        break
    }

    const res = await axios.request({
      method,
      url,
      headers,
      data,
      timeout: 20_000,
      signal: context.abortController.signal,
      validateStatus: () => true,
    })

    return {
      data: {
        status: res.status,
        json: jsonStringify(res.data),
      },
    }
  },
  mapToolResultToToolResultBlockParam(output, toolUseID) {
    return {
      tool_use_id: toolUseID,
      type: 'tool_result',
      content: `HTTP ${output.status}\n${output.json}`,
    }
  },
  renderToolUseMessage,
  renderToolResultMessage,
} satisfies ToolDef<InputSchema, Output>)
