import type { ClaudeJobKind, ClaudeJobStatus, VerifyResult } from '@prisma/client'

export type JobWithRelations = {
  id: string
  kind: ClaudeJobKind
  status: ClaudeJobStatus
  taskCode: string | null
  taskTitle: string | null
  ideaCode: string | null
  ideaTitle: string | null
  sprintGoal: string | null
  sprintCode: string | null
  productName: string
  productCode: string | null
  storyCode: string | null
  pbiCode: string | null
  modelId: string | null
  inputTokens: number | null
  outputTokens: number | null
  cacheReadTokens: number | null
  cacheWriteTokens: number | null
  costUsd: number | null
  branch: string | null
  prUrl: string | null
  error: string | null
  summary: string | null
  description: string | null
  verifyResult: VerifyResult | null
  startedAt: Date | null
  finishedAt: Date | null
  createdAt: Date
  sprintRunId: string | null
}

export const JOB_INCLUDE = {
  task: {
    select: {
      code: true,
      title: true,
      description: true,
      implementation_plan: true,
      story: { select: { code: true, pbi: { select: { code: true } } } },
    },
  },
  idea: { select: { code: true, title: true, description: true, grill_md: true, plan_md: true } },
  product: { select: { name: true, code: true } },
  sprint_run: { include: { sprint: { select: { sprint_goal: true, code: true } } } },
} as const

export type RawJob = {
  id: string
  kind: ClaudeJobKind
  status: ClaudeJobStatus
  model_id: string | null
  input_tokens: number | null
  output_tokens: number | null
  cache_read_tokens: number | null
  cache_write_tokens: number | null
  branch: string | null
  pr_url: string | null
  error: string | null
  summary: string | null
  verify_result: VerifyResult | null
  started_at: Date | null
  finished_at: Date | null
  created_at: Date
  sprint_run_id: string | null
  task: {
    code: string | null
    title: string
    description: string | null
    implementation_plan: string | null
    story: { code: string; pbi: { code: string } } | null
  } | null
  idea: {
    code: string | null
    title: string
    description: string | null
    grill_md: string | null
    plan_md: string | null
  } | null
  product: { name: string; code: string | null }
  sprint_run: { sprint: { sprint_goal: string; code: string } } | null
}

export type PriceRow = {
  model_id: string
  input_price_per_1m: { toString: () => string }
  output_price_per_1m: { toString: () => string }
  cache_read_price_per_1m: { toString: () => string }
  cache_write_price_per_1m: { toString: () => string }
}

export function buildPriceMap(prices: PriceRow[]): Map<string, PriceRow> {
  return new Map(prices.map((p) => [p.model_id, p]))
}

export function pickDescription(j: RawJob): string | null {
  switch (j.kind) {
    case 'TASK_IMPLEMENTATION':
      return j.task?.implementation_plan ?? j.task?.description ?? null
    case 'IDEA_GRILL':
      return j.idea?.grill_md ?? j.idea?.description ?? null
    case 'IDEA_MAKE_PLAN':
      return j.idea?.plan_md ?? j.idea?.description ?? null
    case 'PLAN_CHAT':
      return j.idea?.description ?? null
    case 'SPRINT_IMPLEMENTATION':
      return null
    default:
      return null
  }
}

export function computeCost(j: RawJob, priceMap: Map<string, PriceRow>): number | null {
  if (!j.model_id) return null
  const p = priceMap.get(j.model_id)
  if (!p || j.input_tokens == null) return null
  return (
    ((j.input_tokens ?? 0) * Number(p.input_price_per_1m.toString())) / 1_000_000 +
    ((j.output_tokens ?? 0) * Number(p.output_price_per_1m.toString())) / 1_000_000 +
    ((j.cache_read_tokens ?? 0) * Number(p.cache_read_price_per_1m.toString())) / 1_000_000 +
    ((j.cache_write_tokens ?? 0) * Number(p.cache_write_price_per_1m.toString())) / 1_000_000
  )
}

export function mapJob(j: RawJob, priceMap: Map<string, PriceRow>): JobWithRelations {
  return {
    id: j.id,
    kind: j.kind,
    status: j.status,
    taskCode: j.task?.code ?? null,
    taskTitle: j.task?.title ?? null,
    ideaCode: j.idea?.code ?? null,
    ideaTitle: j.idea?.title ?? null,
    sprintGoal: j.sprint_run?.sprint.sprint_goal ?? null,
    sprintCode: j.sprint_run?.sprint.code ?? null,
    productName: j.product.name,
    productCode: j.product.code ?? null,
    storyCode: j.task?.story?.code ?? null,
    pbiCode: j.task?.story?.pbi?.code ?? null,
    modelId: j.model_id,
    inputTokens: j.input_tokens,
    outputTokens: j.output_tokens,
    cacheReadTokens: j.cache_read_tokens,
    cacheWriteTokens: j.cache_write_tokens,
    costUsd: computeCost(j, priceMap),
    branch: j.branch,
    prUrl: j.pr_url,
    error: j.error,
    summary: j.summary,
    description: pickDescription(j),
    verifyResult: j.verify_result,
    startedAt: j.started_at,
    finishedAt: j.finished_at,
    createdAt: j.created_at,
    sprintRunId: j.sprint_run_id,
  }
}
