import { Router, Request, Response } from 'express';
import multer from 'multer';
import path from 'path';
import fs from 'fs';
import { PluginContext } from '../../../backend/src/core/types';

export function createUploadRoutes(ctx: PluginContext): Router {
    const router = Router();
    const uploadDir = process.env.UPLOAD_DIR || path.join(process.cwd(), 'uploads');
    if (!fs.existsSync(uploadDir)) fs.mkdirSync(uploadDir, { recursive: true });

    const storage = multer.diskStorage({
        destination: (_req, _file, cb) => cb(null, uploadDir),
        filename: (_req, file, cb) => cb(null, `${Date.now()}-${file.originalname}`),
    });
    const upload = multer({ storage, limits: { fileSize: 5 * 1024 * 1024 } });

    // POST / — Upload file
    router.post('/', upload.single('file'), async (req: Request, res: Response) => {
        try {
            if (!req.file) return res.status(400).json({ error: 'Nenhum arquivo enviado' });

            const destination = req.query.destination as string;
            const category = req.query.category as any || 'media';

            let fileBuffer = fs.readFileSync(req.file.path);
            let mimetype = req.file.mimetype;

            // Emit transformation hook
            const transformResults = await ctx.hooks.emit('upload:transform', {
                buffer: fileBuffer,
                mimetype: mimetype,
                category: category,
                originalname: req.file.originalname,
                partnerId: req.body.partnerId
            });

            // If a plugin transformed the file, use the last result
            if (transformResults && transformResults.length > 0) {
                const lastResult = transformResults[transformResults.length - 1];
                if (lastResult && lastResult.buffer) {
                    fileBuffer = lastResult.buffer;
                    mimetype = lastResult.mimetype || mimetype;
                }
            }

            if (destination === 'cloud') {
                if (fs.existsSync(req.file.path)) fs.unlinkSync(req.file.path);

                // Use a more robust import for the singleton (conditional for production Docker)
                const storageCore = process.env.NODE_ENV === 'production'
                    ? require('../../../../dist/core/StorageProvider')
                    : require('../../../../backend/src/core/StorageProvider');
                const provider = storageCore.storageProvider || (storageCore.default && storageCore.default.storageProvider);

                if (!provider) {
                    ctx.logger.error('[Uploads] StorageProvider not found in core');
                    return res.status(500).json({ error: 'Storage core unavailable' });
                }

                const cloudResult = await provider.uploadFile({
                    category,
                    partnerId: req.body.partnerId,
                    benefitId: req.body.benefitId,
                    postId: req.body.postId,
                    whatsappId: req.body.whatsappId,
                    file: {
                        originalname: req.file.originalname,
                        buffer: fileBuffer,
                        mimetype: mimetype
                    }
                });

                return res.json({
                    url: `https://${process.env.WASABI_BUCKET}.s3.wasabisys.com/${cloudResult.path}`,
                    filename: req.file.filename,
                    provider: 'wasabi'
                });
            }

            // Local storage fallback: save the potentially transformed buffer
            if (transformResults && transformResults.length > 0) {
                fs.writeFileSync(req.file.path, fileBuffer);
            }

            const url = `/uploads/${req.file.filename}`;
            await ctx.hooks.emit('upload:completed', { filename: req.file.filename, url });
            res.json({ url, filename: req.file.filename, size: fileBuffer.length });
        } catch (err: any) {
            console.error('[Uploads] Error:', err);
            res.status(500).json({ error: 'Erro no upload' });
        }
    });

    // POST /logo — Upload partner logo
    router.post('/logo', upload.single('logo'), async (req: Request, res: Response) => {
        try {
            if (!req.file) return res.status(400).json({ error: 'Nenhum logo enviado' });

            let fileBuffer = fs.readFileSync(req.file.path);
            let mimetype = req.file.mimetype;

            // Emit transformation hook
            const transformResults = await ctx.hooks.emit('upload:transform', {
                buffer: fileBuffer,
                mimetype: mimetype,
                category: 'partners',
                originalname: req.file.originalname
            });

            if (transformResults && transformResults.length > 0) {
                const lastResult = transformResults[transformResults.length - 1];
                if (lastResult && lastResult.buffer) {
                    fileBuffer = lastResult.buffer;
                    mimetype = lastResult.mimetype || mimetype;
                    // Overwrite local file with optimized version
                    fs.writeFileSync(req.file.path, fileBuffer);
                }
            }

            const url = `/uploads/${req.file.filename}`;
            res.json({ url, filename: req.file.filename });
        } catch (err: any) {
            console.error('[Uploads] Logo Error:', err);
            res.status(500).json({ error: 'Erro no upload do logo' });
        }
    });

    // DELETE /:filename — Delete file
    router.delete('/:filename', async (req: Request, res: Response) => {
        try {
            const filePath = path.join(uploadDir, req.params.filename);
            if (fs.existsSync(filePath)) {
                fs.unlinkSync(filePath);
                await ctx.hooks.emit('upload:deleted', { filename: req.params.filename });
                res.json({ message: 'Arquivo removido' });
            } else {
                res.status(404).json({ error: 'Arquivo não encontrado' });
            }
        } catch (err: any) { res.status(500).json({ error: 'Erro ao remover' }); }
    });

    // GET /:filename — Legacy access with Washabi Fallback 🛡️
    router.get('/:filename', async (req: Request, res: Response) => {
        const { filename } = req.params;
        const localPath = path.join(uploadDir, filename);

        // 🛡️ If exists locally, serve normally
        if (fs.existsSync(localPath)) {
            return res.sendFile(localPath);
        }

        // 🚀 If NOT local, redirect or proxy to UnifiedStorageProvider
        // We know most legacy uploads go to the 'media' category in the proxy
        const storageProxyUrl = `/api/storage/view/media/${filename}`;
        ctx.logger.info(`[Uploads:Fallback] Redirecting legacy file ${filename} -> ${storageProxyUrl}`);
        res.redirect(storageProxyUrl);
    });

    return router;
}
