import { PutObjectCommand } from "@aws-sdk/client-s3"
import { s3 } from "./s3"
import { secrets } from "./secrets"

// Drizzle schema
import { files } from "../../db/schema"
import { eq } from "drizzle-orm"
import { FastifyInstance } from "fastify"
import { storeExtractedTextForFile } from "./documentText"
import { sanitizeFilename } from "./filename"

export const saveFile = async (
    server: FastifyInstance,
    tenant: number,
    messageId: string | number | null, // Typ angepasst (oft null bei manueller Gen)
    attachment: any, // Kann File, Buffer oder Mailparser-Objekt sein
    folder: string | null,
    type: string | null,
    other: Record<string, any> = {}
) => {
    try {
        const {
            filename: providedFilename,
            filesize: _providedFilesize,
            mimeType: providedMimeType,
            ...dbFields
        } = other

        // ---------------------------------------------------
        // 1️⃣ FILE ENTRY ANLEGEN
        // ---------------------------------------------------
        const insertRes = await server.db
            .insert(files)
            .values({
                tenant,
                folder,
                type,
                ...dbFields
            })
            .returning()

        const created = insertRes?.[0]
        if (!created) {
            console.error("File creation failed (no row returned)")
            return null
        }

        // Name ermitteln (Fallback Logik)
        // Wenn attachment ein Buffer ist, muss der Name in 'other' stehen oder generiert werden
        const filename = sanitizeFilename(
            attachment.filename || providedFilename || `${created.id}.pdf`,
            `${created.id}.pdf`
        )

        // ---------------------------------------------------
        // 2️⃣ BODY & CONTENT TYPE ERMITTELN
        // ---------------------------------------------------
        let body: Buffer | Uint8Array | string
        let contentType = providedMimeType || "application/octet-stream"

        if (Buffer.isBuffer(attachment)) {
            // FALL 1: RAW BUFFER (von finishManualGeneration)
            body = attachment
            // ContentType wurde oben schon über 'type' Parameter gesetzt (z.B. application/pdf)
        } else if (typeof File !== "undefined" && attachment instanceof File) {
            // FALL 2: BROWSER FILE
            body = Buffer.from(await attachment.arrayBuffer())
            contentType = attachment.type || contentType
        } else if (attachment.content) {
            // FALL 3: MAILPARSER OBJECT
            body = attachment.content
            contentType = attachment.contentType || contentType
        } else {
            console.error("saveFile: Unknown attachment format")
            return null
        }

        // ---------------------------------------------------
        // 3️⃣ S3 UPLOAD
        // ---------------------------------------------------
        const key = `${tenant}/filesbyid/${created.id}/${filename}`

        await s3.send(
            new PutObjectCommand({
                Bucket: secrets.S3_BUCKET,
                Key: key,
                Body: body,
                ContentType: contentType,
                ContentLength: body.length // <--- WICHTIG: Behebt den AWS Fehler
            })
        )

        // ---------------------------------------------------
        // 4️⃣ PATH IN DB SETZEN
        // ---------------------------------------------------
        await server.db
            .update(files)
            .set({
                path: key,
                mimeType: contentType,
                name: filename,
                size: body.length
            })
            .where(eq(files.id, created.id))

        await storeExtractedTextForFile(
            server,
            created.id,
            Buffer.isBuffer(body) ? body : Buffer.from(body),
            contentType,
            filename
        )

        console.log(`File saved: ${key}`)
        return { id: created.id, key, filename }
    } catch (err) {
        console.error("saveFile error:", err)
        return null
    }
}
