import { db } from '@sim/db'
import { workflowCheckpoints } from '@sim/db/schema'
import { createLogger } from '@sim/logger'
import { authorizeWorkflowByWorkspacePermission } from '@sim/platform-authz/workflow'
import { and, desc, eq } from 'drizzle-orm'
import { type NextRequest, NextResponse } from 'next/server'
import {
  createCopilotCheckpointContract,
  listCopilotCheckpointsContract,
} from '@/lib/api/contracts/copilot'
import { getValidationErrorMessage, parseRequest, validationErrorResponse } from '@/lib/api/server'
import { getAccessibleCopilotChatAuth } from '@/lib/copilot/chat/lifecycle'
import {
  authenticateCopilotRequestSessionOnly,
  createBadRequestResponse,
  createInternalServerErrorResponse,
  createRequestTracker,
  createUnauthorizedResponse,
} from '@/lib/copilot/request/http'
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'

const logger = createLogger('WorkflowCheckpointsAPI')

/**
 * POST /api/copilot/checkpoints
 * Create a new checkpoint with JSON workflow state
 */
export const POST = withRouteHandler(async (req: NextRequest) => {
  const tracker = createRequestTracker()

  try {
    const { userId, isAuthenticated } = await authenticateCopilotRequestSessionOnly()
    if (!isAuthenticated || !userId) {
      return createUnauthorizedResponse()
    }

    const parsed = await parseRequest(
      createCopilotCheckpointContract,
      req,
      {},
      {
        validationErrorResponse: (error) =>
          validationErrorResponse(
            error,
            getValidationErrorMessage(error, 'Invalid checkpoint payload')
          ),
      }
    )
    if (!parsed.success) return parsed.response
    const { workflowId, chatId, messageId, workflowState } = parsed.data.body

    logger.info(`[${tracker.requestId}] Creating workflow checkpoint`, {
      userId,
      workflowId,
      chatId,
      messageId,
      parsedData: { workflowId, chatId, messageId },
      messageIdType: typeof messageId,
      messageIdExists: !!messageId,
    })

    // Verify that the chat belongs to the user
    const chat = await getAccessibleCopilotChatAuth(chatId, userId)

    if (!chat) {
      return createBadRequestResponse('Chat not found or unauthorized')
    }

    if (chat.workflowId !== workflowId) {
      return createBadRequestResponse('Chat does not belong to the requested workflow')
    }

    const authorization = await authorizeWorkflowByWorkspacePermission({
      workflowId,
      userId,
      action: 'write',
    })
    if (!authorization.allowed) {
      return createUnauthorizedResponse()
    }

    // Parse the workflow state to validate it's valid JSON
    let parsedWorkflowState
    try {
      parsedWorkflowState = JSON.parse(workflowState)
    } catch (error) {
      return createBadRequestResponse('Invalid workflow state JSON')
    }

    // Create checkpoint with JSON workflow state
    const [checkpoint] = await db
      .insert(workflowCheckpoints)
      .values({
        userId,
        workflowId,
        chatId,
        messageId,
        workflowState: parsedWorkflowState, // Store as JSON object
      })
      .returning()

    logger.info(`[${tracker.requestId}] Workflow checkpoint created successfully`, {
      checkpointId: checkpoint.id,
      savedData: {
        checkpointId: checkpoint.id,
        userId: checkpoint.userId,
        workflowId: checkpoint.workflowId,
        chatId: checkpoint.chatId,
        messageId: checkpoint.messageId,
        createdAt: checkpoint.createdAt,
      },
    })

    return NextResponse.json({
      success: true,
      checkpoint: {
        id: checkpoint.id,
        userId: checkpoint.userId,
        workflowId: checkpoint.workflowId,
        chatId: checkpoint.chatId,
        messageId: checkpoint.messageId,
        createdAt: checkpoint.createdAt,
        updatedAt: checkpoint.updatedAt,
      },
    })
  } catch (error) {
    logger.error(`[${tracker.requestId}] Failed to create workflow checkpoint:`, error)
    return createInternalServerErrorResponse('Failed to create checkpoint')
  }
})

/**
 * GET /api/copilot/checkpoints?chatId=xxx
 * Retrieve workflow checkpoints for a chat
 */
export const GET = withRouteHandler(async (req: NextRequest) => {
  const tracker = createRequestTracker()

  try {
    const { userId, isAuthenticated } = await authenticateCopilotRequestSessionOnly()
    if (!isAuthenticated || !userId) {
      return createUnauthorizedResponse()
    }

    const parsed = await parseRequest(
      listCopilotCheckpointsContract,
      req,
      {},
      {
        validationErrorResponse: (error) =>
          validationErrorResponse(error, getValidationErrorMessage(error)),
      }
    )
    if (!parsed.success) return parsed.response
    const { chatId } = parsed.data.query

    logger.info(`[${tracker.requestId}] Fetching workflow checkpoints for chat`, {
      userId,
      chatId,
    })

    const chat = await getAccessibleCopilotChatAuth(chatId, userId)
    if (!chat) {
      return createBadRequestResponse('Chat not found or unauthorized')
    }

    // Fetch checkpoints for this user and chat
    const checkpoints = await db
      .select({
        id: workflowCheckpoints.id,
        userId: workflowCheckpoints.userId,
        workflowId: workflowCheckpoints.workflowId,
        chatId: workflowCheckpoints.chatId,
        messageId: workflowCheckpoints.messageId,
        createdAt: workflowCheckpoints.createdAt,
        updatedAt: workflowCheckpoints.updatedAt,
      })
      .from(workflowCheckpoints)
      .where(and(eq(workflowCheckpoints.chatId, chatId), eq(workflowCheckpoints.userId, userId)))
      .orderBy(desc(workflowCheckpoints.createdAt))

    logger.info(`[${tracker.requestId}] Retrieved ${checkpoints.length} workflow checkpoints`)

    return NextResponse.json({
      success: true,
      checkpoints,
    })
  } catch (error) {
    logger.error(`[${tracker.requestId}] Failed to fetch workflow checkpoints:`, error)
    return createInternalServerErrorResponse('Failed to fetch checkpoints')
  }
})
