import { createLogger } from '@sim/logger'
import { getErrorMessage } from '@sim/utils/errors'
import { type NextRequest, NextResponse } from 'next/server'
import { jiraAddAttachmentContract } from '@/lib/api/contracts/selectors/jira'
import { parseRequest } from '@/lib/api/server'
import { checkInternalAuth } from '@/lib/auth/hybrid'
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
import { downloadServableFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
import { docNotReadyResponse } from '@/lib/uploads/utils/servable-file-response'
import { assertToolFileAccess } from '@/app/api/files/authorization'
import { getJiraCloudId, parseAtlassianErrorMessage } from '@/tools/jira/utils'

const logger = createLogger('JiraAddAttachmentAPI')

export const dynamic = 'force-dynamic'

export const POST = withRouteHandler(async (request: NextRequest) => {
  const requestId = `jira-attach-${Date.now()}`

  try {
    const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
    if (!authResult.success || !authResult.userId) {
      return NextResponse.json(
        { success: false, error: authResult.error || 'Unauthorized' },
        { status: 401 }
      )
    }

    const parsed = await parseRequest(jiraAddAttachmentContract, request, {})
    if (!parsed.success) return parsed.response
    const validatedData = parsed.data.body

    const userFiles = processFilesToUserFiles(validatedData.files, requestId, logger)
    if (userFiles.length === 0) {
      return NextResponse.json(
        { success: false, error: 'No valid files provided for upload' },
        { status: 400 }
      )
    }

    const cloudId =
      validatedData.cloudId ||
      (await getJiraCloudId(validatedData.domain, validatedData.accessToken))

    const formData = new FormData()

    for (const file of userFiles) {
      const denied = await assertToolFileAccess(file.key, authResult.userId, requestId, logger)
      if (denied) return denied
      let buffer: Buffer
      let downloadedContentType = ''
      try {
        const result = await downloadServableFileFromStorage(file, requestId, logger)
        buffer = result.buffer
        downloadedContentType = result.contentType
      } catch (error) {
        const notReady = docNotReadyResponse(error)
        if (notReady) return notReady
        throw error
      }
      const blob = new Blob([new Uint8Array(buffer)], {
        type: downloadedContentType || file.type || 'application/octet-stream',
      })
      formData.append('file', blob, file.name)
    }

    const url = `https://api.atlassian.com/ex/jira/${cloudId}/rest/api/3/issue/${validatedData.issueKey}/attachments`

    const response = await fetch(url, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${validatedData.accessToken}`,
        'X-Atlassian-Token': 'no-check',
      },
      body: formData,
    })

    if (!response.ok) {
      const errorText = await response.text()
      logger.error(`[${requestId}] Jira attachment upload failed`, {
        status: response.status,
        statusText: response.statusText,
        error: errorText,
      })
      return NextResponse.json(
        {
          success: false,
          error: parseAtlassianErrorMessage(response.status, response.statusText, errorText),
        },
        { status: response.status }
      )
    }

    const jiraAttachments = await response.json()
    const attachmentsList = Array.isArray(jiraAttachments) ? jiraAttachments : []

    const attachmentIds = attachmentsList.map((att: any) => att.id).filter(Boolean)
    const attachments = attachmentsList.map((att: any) => ({
      id: att.id ?? '',
      filename: att.filename ?? '',
      mimeType: att.mimeType ?? '',
      size: att.size ?? 0,
      content: att.content ?? '',
    }))

    return NextResponse.json({
      success: true,
      output: {
        ts: new Date().toISOString(),
        issueKey: validatedData.issueKey,
        attachments,
        attachmentIds,
        files: userFiles,
      },
    })
  } catch (error) {
    logger.error(`[${requestId}] Jira attachment upload error`, error)
    return NextResponse.json(
      { success: false, error: getErrorMessage(error, 'Internal server error') },
      { status: 500 }
    )
  }
})
