/**
 * POST /api/v1/admin/workflows/import
 *
 * Import a single workflow into a workspace.
 *
 * Request Body:
 *   {
 *     workspaceId: string,           // Required: target workspace
 *     folderId?: string,             // Optional: target folder
 *     name?: string,                 // Optional: override workflow name
 *     workflow: object | string      // The workflow JSON (from export or raw state)
 *   }
 *
 * Response: { workflowId: string, name: string, success: true }
 */

import { db } from '@sim/db'
import { workflow, workspace } from '@sim/db/schema'
import { createLogger } from '@sim/logger'
import { generateId } from '@sim/utils/id'
import { and, eq, isNull } from 'drizzle-orm'
import { NextResponse } from 'next/server'
import { adminV1ImportWorkflowContract } from '@/lib/api/contracts/v1/admin'
import { parseRequest } from '@/lib/api/server'
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
import { parseWorkflowJson } from '@/lib/workflows/operations/import-export'
import { saveWorkflowToNormalizedTables } from '@/lib/workflows/persistence/utils'
import { deduplicateWorkflowName } from '@/lib/workflows/utils'
import { withAdminAuth } from '@/app/api/v1/admin/middleware'
import {
  badRequestResponse,
  internalErrorResponse,
  notFoundResponse,
} from '@/app/api/v1/admin/responses'
import {
  extractWorkflowMetadata,
  type VariableType,
  type WorkflowImportRequest,
  type WorkflowVariable,
} from '@/app/api/v1/admin/types'

const logger = createLogger('AdminWorkflowImportAPI')

interface ImportSuccessResponse {
  workflowId: string
  name: string
  success: true
}

export const POST = withRouteHandler(
  withAdminAuth(async (request) => {
    try {
      const parsed = await parseRequest(adminV1ImportWorkflowContract, request, {})
      if (!parsed.success) return parsed.response

      const body = parsed.data.body as WorkflowImportRequest
      const { workspaceId, folderId, name: overrideName } = body

      const [workspaceData] = await db
        .select({ id: workspace.id, ownerId: workspace.ownerId })
        .from(workspace)
        .where(and(eq(workspace.id, workspaceId), isNull(workspace.archivedAt)))
        .limit(1)

      if (!workspaceData) {
        return notFoundResponse('Workspace')
      }

      const workflowContent =
        typeof body.workflow === 'string' ? body.workflow : JSON.stringify(body.workflow)

      const { data: workflowData, errors } = parseWorkflowJson(workflowContent)

      if (!workflowData || errors.length > 0) {
        return badRequestResponse(`Invalid workflow: ${errors.join(', ')}`)
      }

      const parsedWorkflow =
        typeof body.workflow === 'string'
          ? (() => {
              try {
                return JSON.parse(body.workflow)
              } catch {
                return null
              }
            })()
          : body.workflow

      const {
        name: workflowName,
        color: workflowColor,
        description: workflowDescription,
      } = extractWorkflowMetadata(parsedWorkflow, overrideName)

      const workflowId = generateId()
      const now = new Date()
      const dedupedName = await deduplicateWorkflowName(workflowName, workspaceId, folderId || null)

      await db.insert(workflow).values({
        id: workflowId,
        userId: workspaceData.ownerId,
        workspaceId,
        folderId: folderId || null,
        name: dedupedName,
        description: workflowDescription,
        color: workflowColor,
        lastSynced: now,
        createdAt: now,
        updatedAt: now,
        isDeployed: false,
        runCount: 0,
        variables: {},
      })

      const saveResult = await saveWorkflowToNormalizedTables(workflowId, workflowData)

      if (!saveResult.success) {
        await db.delete(workflow).where(eq(workflow.id, workflowId))
        return internalErrorResponse(`Failed to save workflow state: ${saveResult.error}`)
      }

      if (
        workflowData.variables &&
        typeof workflowData.variables === 'object' &&
        !Array.isArray(workflowData.variables)
      ) {
        const variablesRecord: Record<string, WorkflowVariable> = {}
        const vars = workflowData.variables as Record<
          string,
          { id?: string; name: string; type?: VariableType; value: unknown }
        >
        Object.entries(vars).forEach(([key, v]) => {
          const varId = v.id || key
          variablesRecord[varId] = {
            id: varId,
            name: v.name,
            type: v.type ?? 'string',
            value: v.value,
          }
        })

        await db
          .update(workflow)
          .set({ variables: variablesRecord, updatedAt: new Date() })
          .where(eq(workflow.id, workflowId))
      } else if (workflowData.variables && Array.isArray(workflowData.variables)) {
        const variablesRecord: Record<string, WorkflowVariable> = {}
        workflowData.variables.forEach((v) => {
          const varId = v.id || generateId()
          variablesRecord[varId] = {
            id: varId,
            name: v.name,
            type: (v.type as VariableType) ?? 'string',
            value: v.value,
          }
        })

        await db
          .update(workflow)
          .set({ variables: variablesRecord, updatedAt: new Date() })
          .where(eq(workflow.id, workflowId))
      }

      logger.info(
        `Admin API: Imported workflow ${workflowId} (${dedupedName}) into workspace ${workspaceId}`
      )

      const response: ImportSuccessResponse = {
        workflowId,
        name: dedupedName,
        success: true,
      }

      return NextResponse.json(response)
    } catch (error) {
      logger.error('Admin API: Failed to import workflow', { error })
      return internalErrorResponse('Failed to import workflow')
    }
  })
)
