/**
 * Bank statement import route — bank-statement-import (wave-10 leaf3).
 *
 * POST /api/imports/bank-statement
 *
 * Multipart form upload:
 *   - file: CSV file (text/csv or text/plain)
 *   - format: 'leumi' | 'hapoalim' | 'discount' | 'visa-cal' | 'generic'
 *   - preview: optional '1'|'true' — return parsed rows without importing
 *
 * Returns: { imported, skipped, duplicates, preview: ParsedTransaction[], total }
 *
 * Auth: authMiddleware + expenses:write permission
 */
import { Hono } from 'hono'
import { z } from 'zod'
import type { AppEnv } from '../../types'
import { authMiddleware } from '../../middleware/auth'
import { requirePermission } from '../../middleware/guards'
import {
  parseBankStatement,
  importBankTransactions,
} from '@zync/db/queries'
import type { BankFormat } from '@zync/db/queries'

const BANK_FORMATS = ['leumi', 'hapoalim', 'discount', 'visa-cal', 'generic'] as const

const MAX_FILE_BYTES = 5 * 1024 * 1024 // 5 MB

const querySchema = z.object({
  format: z.enum(BANK_FORMATS).default('generic'),
  preview: z
    .string()
    .optional()
    .transform((v) => v === 'true' || v === '1'),
})

export const bankStatementImportRoute = new Hono<AppEnv>()

bankStatementImportRoute.use('*', authMiddleware)

bankStatementImportRoute.post('/', requirePermission('expenses:write'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) {
    return c.json({ error: 'Unauthorized' }, 401)
  }

  const tenantId = session.tid
  const userId = session.sub

  // Parse query params
  const rawQuery = {
    format: c.req.query('format'),
    preview: c.req.query('preview'),
  }
  const queryResult = querySchema.safeParse(rawQuery)
  if (!queryResult.success) {
    return c.json({ error: 'Invalid query parameters', details: queryResult.error.flatten() }, 400)
  }
  let { format, preview } = queryResult.data

  // Parse multipart form
  let csvContent: string
  let detectedFormat: BankFormat = format

  try {
    const formData = await c.req.formData()
    const file = formData.get('file')
    const formatField = formData.get('format')

    if (
      formatField &&
      typeof formatField === 'string' &&
      BANK_FORMATS.includes(formatField as BankFormat)
    ) {
      detectedFormat = formatField as BankFormat
    }

    if (!file || typeof file === 'string') {
      return c.json({ error: 'Missing file field in form data' }, 400)
    }

    // file is a Blob/File-like object (FormDataEntryValue that is not a string)
    const uploadedFile = file as Blob & { name?: string; type: string; size: number; text(): Promise<string> }

    if (uploadedFile.size > MAX_FILE_BYTES) {
      return c.json(
        { error: `File exceeds maximum size of ${MAX_FILE_BYTES / 1024 / 1024}MB` },
        413,
      )
    }

    const mimeType = uploadedFile.type.toLowerCase()
    if (
      mimeType &&
      !['text/csv', 'text/plain', 'application/csv', ''].includes(mimeType)
    ) {
      return c.json({ error: 'Only CSV files are accepted' }, 415)
    }

    // Check preview flag in form data too
    const previewField = formData.get('preview')
    if (previewField === 'true' || previewField === '1') {
      preview = true
    }

    csvContent = await uploadedFile.text()
  } catch {
    return c.json({ error: 'Failed to read uploaded file' }, 400)
  }

  if (!csvContent.trim()) {
    return c.json({ error: 'Uploaded file is empty' }, 400)
  }

  // Parse CSV → transactions
  const transactions = parseBankStatement(csvContent, detectedFormat)

  if (transactions.length === 0) {
    return c.json({
      imported: 0,
      skipped: 0,
      duplicates: 0,
      preview: [],
      total: 0,
      message: 'No transactions found in file. Check the format matches your bank.',
    })
  }

  // Preview mode: return parsed rows without importing
  if (preview) {
    return c.json({
      imported: 0,
      skipped: 0,
      duplicates: 0,
      preview: transactions.slice(0, 50),
      total: transactions.length,
    })
  }

  // Import
  const db = c.get('db')
  const summary = await importBankTransactions(db, tenantId, userId, transactions)

  return c.json({
    ...summary,
    preview: transactions.slice(0, 10),
    total: transactions.length,
  })
})
