import { z } from 'zod'
import {
  pikkuMCPToolFunc,
  pikkuMCPResourceFunc,
  pikkuMCPPromptFunc,
  wireMCPResource,
  wireMCPPrompt,
} from '#pikku'
import { randomUUID } from 'node:crypto'

export const listCardsTool = pikkuMCPToolFunc({
  description: 'List all kanban cards on the board.',
  tags: ['kanban', 'cards'],
  func: async ({ kysely }) => {
    const cards = await kysely
      .selectFrom('kanbanCard')
      .selectAll()
      .orderBy('position', 'asc')
      .execute()
    return [{ type: 'text' as const, text: JSON.stringify(cards, null, 2) }]
  },
})

export const CreateCardToolInput = z.object({
  title: z.string().min(1),
  status: z.enum(['todo', 'doing', 'done']).default('todo'),
})

export const createCardTool = pikkuMCPToolFunc({
  input: CreateCardToolInput,
  description: 'Create a new kanban card on the board.',
  tags: ['kanban', 'cards'],
  func: async ({ kysely, queueService }, { title, status }) => {
    const cardId = randomUUID()
    const createdAt = new Date().toISOString()
    const max = await kysely
      .selectFrom('kanbanCard')
      .select(({ fn }) => fn.max<number>('position').as('max'))
      .where('status', '=', status)
      .executeTakeFirst()
    const position = (max?.max ?? 0) + 1
    await kysely
      .insertInto('kanbanCard')
      .values({ cardId, title, status, position, createdAt })
      .execute()
    await queueService!.add('process-card-event', { cardId, action: 'created', status, createdAt })
    return [{ type: 'text' as const, text: `Created card ${cardId}: "${title}" (${status})` }]
  },
})

const kanbanCardsResource = pikkuMCPResourceFunc<void>(async ({ kysely }) => {
  const cards = await kysely
    .selectFrom('kanbanCard')
    .selectAll()
    .orderBy('position', 'asc')
    .execute()
  return [{ uri: 'kanban://cards', text: JSON.stringify(cards, null, 2) }]
})

const kanbanStatusPrompt = pikkuMCPPromptFunc<void>(async ({ kysely }) => {
  const cards = await kysely.selectFrom('kanbanCard').selectAll().execute()
  const byStatus = cards.reduce<Record<string, number>>((acc, c) => {
    acc[c.status] = (acc[c.status] ?? 0) + 1
    return acc
  }, {})
  return [
    {
      role: 'user' as const,
      content: {
        type: 'text' as const,
        text: `Board has ${cards.length} cards: ${JSON.stringify(byStatus)}. Summarise the state.`,
      },
    },
  ]
})

wireMCPResource({
  uri: 'kanban://cards',
  title: 'Kanban Board Cards',
  description: 'All cards currently on the kanban board',
  func: kanbanCardsResource,
  tags: ['kanban'],
})

wireMCPPrompt({
  name: 'kanbanStatus',
  description: 'Get a prompt summarising the current kanban board state',
  func: kanbanStatusPrompt,
  tags: ['kanban'],
})
