import { Application } from 'express';
import { Resource } from 'express-automatic-routes';
import { FileProvider } from '#providers/FileProvider';
import { Req, Res } from '#interfaces/IApi';
import verify from '#middlewares/auth';
import { validateId } from '#middlewares/validators';
import { getStorageAdapter } from '#services/storage/adapters/StorageFactory';
import { Errors } from '#interfaces/error';
import { sendSuccess } from '#utils/responseUtils';
import Config from '#config';

export default (_express: Application) => {
	const fileProvider = FileProvider.getInstance();
	return <Resource>{
		get: {
			middleware: [verify, validateId],
			handler: async (req: Req, res: Res) => {
				try {
					const file = await fileProvider.getById({ id: req.params.id! });

					if (!file || false) {
						throw Errors.fileNotFound();
					}

					const isAdmin = req.user?.roles?.some((r) => ['admin', 'system_admin'].includes(r));
					if (!isAdmin && file.owner_user_id !== req.user?.id) {
						throw Errors.forbidden();
					}

					const fileId = req.params.id!;

					// Get mode from query param (default: view for preview)
					const mode = req.query.mode === 'download' ? 'download' : 'view';
					const disposition = mode === 'download' ? 'attachment' : 'inline';

					// Local storage: point to /content fallback
					if (file.provider === 'local') {
						const fallback = `${Config.server.backendUrl}/api/v1/files/${fileId}/content?mode=${mode}`;
						return sendSuccess(res, { url: null, fallback_endpoint: fallback, expires_in: null });
					}

					const parsed = parseInt(String(req.query.expires || '3600'), 10);
					const expiresIn = Number.isNaN(parsed) || parsed <= 0 ? 3600 : Math.min(parsed, 86400);

					const storageAdapter = getStorageAdapter();
					const storagePath = file.object_key;
					const url = await storageAdapter.getSignedUrl(storagePath, expiresIn, disposition);

					return sendSuccess(res, { url, fallback_endpoint: null, expires_in: expiresIn });
				} catch (error) {
					return res.error(error);
				}
			},
		},
	};
};
