import { db } from '@sim/db'
import { workflowExecutionLogs, workflowExecutionSnapshots } from '@sim/db/schema'
import { createLogger } from '@sim/logger'
import { eq } from 'drizzle-orm'
import { type NextRequest, NextResponse } from 'next/server'
import { v1GetExecutionContract } from '@/lib/api/contracts/v1/logs'
import { parseRequest } from '@/lib/api/server'
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
import { createApiResponse, getUserLimits } from '@/app/api/v1/logs/meta'
import {
  checkRateLimit,
  createRateLimitResponse,
  validateWorkspaceAccess,
} from '@/app/api/v1/middleware'

const logger = createLogger('V1ExecutionAPI')

export const GET = withRouteHandler(
  async (request: NextRequest, context: { params: Promise<{ executionId: string }> }) => {
    try {
      const rateLimit = await checkRateLimit(request, 'logs-detail')
      if (!rateLimit.allowed) {
        return createRateLimitResponse(rateLimit)
      }

      const userId = rateLimit.userId!
      const parsed = await parseRequest(v1GetExecutionContract, request, context, {
        validationErrorResponse: () =>
          NextResponse.json({ error: 'Invalid execution ID' }, { status: 400 }),
      })
      if (!parsed.success) return parsed.response

      const { executionId } = parsed.data.params

      logger.debug(`Fetching execution data for: ${executionId}`)

      const rows = await db
        .select()
        .from(workflowExecutionLogs)
        .where(eq(workflowExecutionLogs.executionId, executionId))
        .limit(1)

      if (rows.length === 0) {
        return NextResponse.json({ error: 'Workflow execution not found' }, { status: 404 })
      }

      const workflowLog = rows[0]

      const accessError = await validateWorkspaceAccess(rateLimit, userId, workflowLog.workspaceId)
      if (accessError) {
        return NextResponse.json({ error: 'Workflow execution not found' }, { status: 404 })
      }

      const [snapshot] = await db
        .select()
        .from(workflowExecutionSnapshots)
        .where(eq(workflowExecutionSnapshots.id, workflowLog.stateSnapshotId))
        .limit(1)

      if (!snapshot) {
        return NextResponse.json({ error: 'Workflow state snapshot not found' }, { status: 404 })
      }

      const response = {
        executionId,
        workflowId: workflowLog.workflowId,
        workflowState: snapshot.stateData,
        executionMetadata: {
          trigger: workflowLog.trigger,
          startedAt: workflowLog.startedAt.toISOString(),
          endedAt: workflowLog.endedAt?.toISOString(),
          totalDurationMs: workflowLog.totalDurationMs,
          // Sourced from the cost_total projection of the usage_log ledger
          // (the deprecated cost jsonb column was dropped).
          cost: workflowLog.costTotal != null ? { total: Number(workflowLog.costTotal) } : null,
        },
      }

      logger.debug(`Successfully fetched execution data for: ${executionId}`)
      logger.debug(
        `Workflow state contains ${Object.keys((snapshot.stateData as any)?.blocks || {}).length} blocks`
      )

      // Get user's workflow execution limits and usage
      const limits = await getUserLimits(userId)

      // Create response with limits information
      const apiResponse = createApiResponse(
        {
          ...response,
        },
        limits,
        rateLimit
      )

      return NextResponse.json(apiResponse.body, { headers: apiResponse.headers })
    } catch (error) {
      logger.error('Error fetching execution data:', error)
      return NextResponse.json({ error: 'Failed to fetch execution data' }, { status: 500 })
    }
  }
)
