// SPDX-FileCopyrightText: 2025 Weibo, Inc.
//
// SPDX-License-Identifier: Apache-2.0

import type { Team, GitRepoInfo, GitBranch, TaskDetail, TaskType } from '@/types/api'
import { taskApis, CreateTaskRequest } from '@/apis/tasks'

/**
 * Check if a team uses Chat Shell type (supports direct streaming chat via WebSocket).
 * This function checks multiple sources to determine if the team is a Chat Shell:
 * 1. team.agent_type === 'chat' (primary check)
 * 2. team.bots[0].bot.shell_type === 'Chat' (fallback for task detail teams)
 *
 * NOTE: Chat Shell now uses WebSocket for streaming instead of SSE.
 * The streaming is handled by ChatStreamContext, not this service.
 *
 * @param team - Team to check
 * @returns true if the team uses Chat Shell
 */
export function isChatShell(team: Team | null): boolean {
  if (!team) return false

  // Primary check: agent_type field (case-insensitive)
  if (team.agent_type?.toLowerCase() === 'chat') {
    return true
  }

  // Fallback: check first bot's shell_type (for task detail teams where agent_type may be null)
  // This handles the case where team is from task detail API which may not include agent_type
  if (team.bots && team.bots.length > 0) {
    const firstBot = team.bots[0]
    // Check bot.shell_type (from BotSummary in TeamBot)
    if (firstBot.bot?.shell_type?.toLowerCase() === 'chat') {
      return true
    }
  }

  return false
}

export function canUseChatContexts(taskType: TaskType | undefined, team: Team | null): boolean {
  if (taskType === 'code') {
    return false
  }

  if (taskType === 'task') {
    return true
  }

  return isChatShell(team)
}

/**
 * Check if a team uses ClaudeCode Shell type.
 * ClaudeCode tasks do not allow skill modification after task creation.
 *
 * @param team - Team to check
 * @returns true if the team uses ClaudeCode Shell
 */
export function isClaudeCode(team: Team | null): boolean {
  if (!team) return false

  // Primary check: agent_type field (case-insensitive)
  if (team.agent_type?.toLowerCase() === 'claudecode') {
    return true
  }

  // Fallback: check first bot's shell_type (for task detail teams where agent_type may be null)
  if (team.bots && team.bots.length > 0) {
    const firstBot = team.bots[0]
    if (firstBot.bot?.shell_type?.toLowerCase() === 'claudecode') {
      return true
    }
  }

  return false
}

/**
 * Check if a task uses Chat Shell type based on team information.
 * Now relies solely on team.agent_type since subtasks are managed by TaskStateMachine.
 *
 * @param taskDetail - Task detail to check
 * @returns true if the task uses Chat Shell
 */
export function isTaskChatShell(taskDetail: TaskDetail | null): boolean {
  if (!taskDetail) return false

  // Check team's agent_type (primary source of truth)
  return isChatShell(taskDetail.team)
}

/**
 * Send message result type
 */
export interface SendMessageResult {
  error: string
  newTask: { task_id: number } | null
}

/**
 * Send message for non-Chat Shell teams.
 *
 * NOTE: For Chat Shell teams, use ChatStreamContext.startStream() instead.
 * This function is only for non-streaming task creation (e.g., code tasks, Dify, etc.)
 *
 * @param params - Message parameters
 * @returns Result with error message or new task info
 */
export async function sendMessage(params: {
  message: string
  team: Team | null
  repo: GitRepoInfo | null
  branch: GitBranch | null
  task_id?: number
  taskType?: 'chat' | 'code'
  title?: string
  model_id?: string
  force_override_bot_model?: boolean
}): Promise<SendMessageResult> {
  const {
    message,
    team,
    repo,
    branch,
    task_id,
    taskType = 'chat',
    title,
    model_id,
    force_override_bot_model,
  } = params
  const trimmed = message?.trim() ?? ''

  if (!trimmed) {
    return { error: 'Message is empty', newTask: null }
  }

  // If there is no task_id, a complete context is required for the first send
  if ((!task_id || !Number.isFinite(task_id)) && !team) {
    return { error: 'Please select Team', newTask: null }
  }

  // For code type tasks, repository is required
  if (taskType === 'code' && !repo) {
    return { error: 'Please select a repository for code tasks', newTask: null }
  }

  // Unified delegation to taskApis.sendTaskMessage (internally handles whether to create a task first)
  const payload: { task_id?: number; message: string } & CreateTaskRequest = {
    task_id: Number.isFinite(task_id as number) ? (task_id as number) : undefined,
    message: trimmed,
    title: title || trimmed.substring(0, 100),
    team_id: team?.id ?? 0,
    git_url: repo?.git_url ?? '',
    git_repo: repo?.git_repo ?? '',
    git_repo_id: repo?.git_repo_id ?? 0,
    git_domain: repo?.git_domain ?? '',
    branch_name: branch?.name ?? '',
    prompt: trimmed,
    task_type: taskType,
    batch: 0,
    user_id: 0,
    user_name: '',
    model_id: model_id,
    force_override_bot_model: force_override_bot_model,
  }

  try {
    const { task_id } = await taskApis.sendTaskMessage(payload)
    return { error: '', newTask: { task_id } }
  } catch (error) {
    return { error: (error as Error)?.message || 'Failed to send message', newTask: null }
  }
}

/**
 * Check if a team requires workspace (code repository).
 * Teams that use local_engine execution type (ClaudeCode, Agno) typically require a workspace.
 * Teams that use external_api execution type (Dify) or Chat Shell typically do not.
 *
 * This function determines requiresWorkspace based on:
 * 1. team.requires_workspace - explicit Team-level configuration (highest priority)
 * 2. team.agent_type - 'chat' or 'dify' do not require workspace
 * 3. bot.shell_type - If ANY bot has shell_type that is not 'chat'/'dify', require workspace
 *
 * @param team - Team to check
 * @returns true if the team requires a workspace
 */
export function teamRequiresWorkspace(team: Team | null): boolean {
  if (!team) return false

  // Priority 1: Check explicit Team-level configuration
  // If requires_workspace is explicitly set (true or false), use that value
  if (team.requires_workspace !== undefined && team.requires_workspace !== null) {
    return team.requires_workspace
  }

  // Priority 2: Infer from agent_type and shell_type
  // Chat Shell and Dify agent types do not require workspace
  const agentType = team.agent_type?.toLowerCase()
  if (agentType === 'chat' || agentType === 'dify') {
    return false
  }

  // Check all bots in the team - if any bot requires workspace, the team requires workspace
  // This handles mixed teams correctly
  if (team.bots && team.bots.length > 0) {
    for (const teamBot of team.bots) {
      const shellType = teamBot.bot?.shell_type?.toLowerCase()
      // If shellType is undefined/null or not 'chat'/'dify', it requires workspace
      if (!shellType || (shellType !== 'chat' && shellType !== 'dify')) {
        return true
      }
    }
    // All bots are chat/dify, no workspace required
    return false
  }

  // Default: if no bots info available, assume local_engine types require workspace
  return true
}
