import { Agent, AdapterType, SandboxType } from '@/lib/types'
import { agentService } from '@/services/agent-service'
import { modelService } from '@/services/model-service'

const PATCHFLOW_AGENT_NAME = 'Patchflow-Agent'
const PATCHFLOW_AGENT_STORAGE_KEY = 'polymind:patchflow-agent-id'
const LEGACY_PATCHFLOW_AGENT_STORAGE_KEYS = ['polymind:cve:patchflow-agent-id']

class PatchflowAgentService {
  private rememberedPatchflowAgentId: string | null = null

  public async getOrCreatePatchflowAgent(): Promise<string> {
    const models = await modelService.getModels()
    const selectedModel =
      models.find(model => model.enabled && model.isDefault) ?? models.find(model => model.enabled)
    if (!selectedModel) {
      throw new Error('没有可用的模型配置,请先在设置中创建并启用模型')
    }

    let agents: Agent[] = []
    try {
      agents = await agentService.getAgents()
    } catch (error) {
      console.error('Failed to get agents:', error)
    }

    const running = agents
      .filter(agent => this.isReusablePatchflowAgent(agent, selectedModel.id))
      .sort((l, r) => Date.parse(r.updatedAt) - Date.parse(l.updatedAt))

    const rememberedId = this.getRememberedPatchflowAgentId()
    const remembered = rememberedId ? running.find(agent => agent.id === rememberedId) : undefined
    if (remembered) {
      this.rememberPatchflowAgent(remembered.id)
      await this.cleanupStalePatchflowAgents(agents, selectedModel.id, remembered.id)
      return remembered.id
    }

    const reusable = running[0]
    if (reusable) {
      this.rememberPatchflowAgent(reusable.id)
      await this.cleanupStalePatchflowAgents(agents, selectedModel.id, reusable.id)
      return reusable.id
    }

    await this.cleanupStalePatchflowAgents(agents, selectedModel.id)
    const newAgent = await agentService.createAgent({
      name: PATCHFLOW_AGENT_NAME,
      adapterType: AdapterType.OPENCLAW,
      sandboxType: SandboxType.LOCAL_PROCESS,
      idleTimeoutSeconds: 1800,
      modelId: selectedModel.id,
    })
    this.rememberPatchflowAgent(newAgent.id)
    return newAgent.id
  }

  private isPatchflowAgent(agent: Agent): boolean {
    return (
      agent.name === PATCHFLOW_AGENT_NAME &&
      String(agent.adapterType) === AdapterType.OPENCLAW &&
      String(agent.sandboxType) === SandboxType.LOCAL_PROCESS
    )
  }

  private isReusablePatchflowAgent(agent: Agent, modelId: string): boolean {
    return (
      this.isPatchflowAgent(agent) &&
      String(agent.status).toLowerCase() === 'running' &&
      Number(agent.processPort || 0) > 0 &&
      agent.modelId === modelId
    )
  }

  private async cleanupStalePatchflowAgents(
    agents: Agent[],
    modelId: string,
    keepAgentId?: string
  ) {
    const staleAgents = agents.filter(
      agent =>
        this.isPatchflowAgent(agent) &&
        agent.id !== keepAgentId &&
        !this.isReusablePatchflowAgent(agent, modelId)
    )

    for (const agent of staleAgents) {
      try {
        await agentService.deleteAgent(agent.id)
      } catch (error) {
        console.error(`Failed to delete stale Patchflow agent ${agent.id}:`, error)
      }
    }
  }

  private getRememberedPatchflowAgentId(): string | null {
    if (this.rememberedPatchflowAgentId) return this.rememberedPatchflowAgentId
    if (typeof window === 'undefined') return null

    const stored = window.sessionStorage.getItem(PATCHFLOW_AGENT_STORAGE_KEY)
    if (stored) {
      this.rememberedPatchflowAgentId = stored
      return stored
    }

    for (const key of LEGACY_PATCHFLOW_AGENT_STORAGE_KEYS) {
      const legacyStored = window.sessionStorage.getItem(key)
      if (legacyStored) {
        this.rememberPatchflowAgent(legacyStored)
        return legacyStored
      }
    }

    return null
  }

  private rememberPatchflowAgent(agentId: string) {
    this.rememberedPatchflowAgentId = agentId
    if (typeof window !== 'undefined') {
      window.sessionStorage.setItem(PATCHFLOW_AGENT_STORAGE_KEY, agentId)
    }
  }
}

export const patchflowAgentService = new PatchflowAgentService()