/**
 * Uniform-format export queue consumer — uniform-format-export (wave-13, spec 180).
 *
 * Handles messages of type 'uniform-format' from the QUEUE binding.
 * Reuses the existing `export.generate` queue infrastructure (spec 28).
 *
 * Message flow:
 *  1. Receive { type: 'uniform-format', jobId, tenantId, from, to, mode, userId }
 *  2. Set job status = 'running'
 *  3. Generate BKMVDATA.txt + INI.txt via generateUniformExport
 *  4. Assemble ZIP (raw CP1255 bytes, not re-encoded)
 *  5. Upload ZIP to STORAGE at key exports/uniform-format/{tenantId}/{jobId}.zip
 *  6. Generate signed R2 URL with 24h TTL
 *  7. Set job status = 'done' with r2_key, record_counts, download_expires_at
 *
 *  On failure: set status = 'error', store error_message, ack (no poison-loop).
 */
import type { Env } from '@zync/types'
import {
  createDb,
  setUniformExportJobRunning,
  setUniformExportJobDone,
  setUniformExportJobError,
} from '@zync/db/queries'
import { generateUniformExport } from '../reports/uniform-format/generate'
import { buildZip } from '../lib/zip-builder'
import type { UniformExportJob } from '../reports/uniform-format/types'

type R2BucketWithPresign = R2Bucket & {
  createPresignedUrl?: (
    method: string,
    key: string,
    options: { expiresIn: number },
  ) => Promise<string>
}

async function presignR2Url(
  env: Env,
  r2Key: string,
  expiresIn: number,
): Promise<string> {
  const storage = env.STORAGE as R2BucketWithPresign
  if (typeof storage.createPresignedUrl === 'function') {
    return storage.createPresignedUrl('GET', r2Key, { expiresIn })
  }

  // S3-compat fallback via aws4fetch
  const { AwsClient } = await import('aws4fetch')
  const envAny = env as unknown as Record<string, string>
  const accountId = envAny['CF_ACCOUNT_ID'] ?? ''
  const accessKeyId = envAny['R2_ACCESS_KEY_ID'] ?? ''
  const secretAccessKey = envAny['R2_SECRET_ACCESS_KEY'] ?? ''
  const bucketName = envAny['R2_BUCKET_NAME'] ?? 'zync-storage'
  const endpoint = `https://${accountId}.r2.cloudflarestorage.com`
  const aws = new AwsClient({ accessKeyId, secretAccessKey, region: 'auto', service: 's3' })
  const url = new URL(`${endpoint}/${bucketName}/${r2Key}`)
  url.searchParams.set('X-Amz-Expires', String(expiresIn))
  const presigned = await aws.sign(new Request(url.toString(), { method: 'GET' }), { aws: { signQuery: true } })
  return presigned.url
}

export async function handleUniformExportJob(
  message: UniformExportJob,
  env: Env,
): Promise<void> {
  const db = createDb(env)
  const { jobId, tenantId, from, to } = message

  // Mark running
  await setUniformExportJobRunning(db, tenantId, jobId)

  const softwareRegNo = env.ZYNC_ITA_SOFTWARE_ID ?? 'ZYNC00001'

  // Generate the export
  const result = await generateUniformExport(db, {
    tenantId,
    from,
    to,
    softwareRegNo,
    env,
  })

  if (result.substitutionLog.length > 0) {
    console.info(
      `[uniform-export] ${result.substitutionLog.length} character substitutions in job ${jobId}:`,
      result.substitutionLog.slice(0, 10),
    )
  }

  // Assemble ZIP
  const zipBytes = buildZip([
    { name: 'BKMVDATA.TXT', data: result.bkmvdataBytes },
    { name: 'INI.TXT', data: result.iniBytes },
  ])

  // Upload to R2
  const r2Key = `exports/uniform-format/${tenantId}/${jobId}.zip`
  await env.STORAGE.put(r2Key, zipBytes, {
    httpMetadata: {
      contentType: 'application/zip',
      contentDisposition: `attachment; filename="uniform-format-${from}-${to}.zip"`,
    },
  })

  // Generate 24h signed URL
  const TTL_24H = 24 * 60 * 60
  const downloadUrl = await presignR2Url(env, r2Key, TTL_24H)
  const downloadExpiresAt = new Date(Date.now() + TTL_24H * 1000)

  // Mark done
  await setUniformExportJobDone(
    db,
    tenantId,
    jobId,
    r2Key,
    result.counts as Record<string, number>,
    downloadExpiresAt,
  )

  console.info(`[uniform-export] Job ${jobId} done. r2_key=${r2Key} URL TTL=${TTL_24H}s`)
  // Note: fresh signed URL is generated on each GET /api/reports/uniform-format/:id/download
  void downloadUrl
}

export async function handleUniformExportError(
  message: UniformExportJob,
  env: Env,
  error: unknown,
): Promise<void> {
  const db = createDb(env)
  const errorMsg = error instanceof Error ? error.message : String(error)
  console.error(`[uniform-export] Job ${message.jobId} failed:`, errorMsg)
  await setUniformExportJobError(db, message.tenantId, message.jobId, errorMsg)
}
