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

const logger = new LoggingService();

export default (_express: Application) => {
	const fileProvider = FileProvider.getInstance();
	return <Resource>{
		get: {
			middleware: [verify, attachPermissions],
			handler: async (req: Req, res: Res) => {
				try {
					// `verify` middleware guarantees req.user exists, but JWTPayload only carries
					// id/email/roles — fetch the extra profile fields in a single targeted query
					const user = await User.findByPk(req.user!.id, {
						attributes: ['id', 'email', 'username', 'first_name', 'last_name', 'status', 'avatar_id'],
					});

					if (!user) {
						return res.error(Errors.userNotFound());
					}

					let avatarUrl: string | null = null;

					// Fetch avatar URL if avatar_id exists
					if (user.avatar_id) {
						try {
							const file = await fileProvider.getById({ id: user.avatar_id });
							if (file) {
								const fileId = user.avatar_id;
								// Local storage: point to /content fallback
								if (file.provider === 'local') {
									avatarUrl = `${Config.server.backendUrl}/api/v1/files/${fileId}/content?mode=view`;
								} else {
									// Cloud storage: generate signed URL
									const storageAdapter = getStorageAdapter();
									const storagePath = file.object_key;
									const url = await storageAdapter.getSignedUrl(storagePath, 3600, 'inline');
									avatarUrl = url;
								}
							}
						} catch (error) {
							// Silently fail if avatar file not found or error occurs.
							// Log to structured logger so ops can investigate without polluting stdout.
							logger
								.logErrorAsync(
									'PROFILE',
									error instanceof Error ? error : new Error(String(error)),
									{ userId: req.user?.id, avatarId: user.avatar_id },
								)
								.catch(() => {});
						}
					}

					const responseData = {
						...user.toJSON(),
						username: user.username ?? null,
						first_name: user.first_name ?? null,
						last_name: user.last_name ?? null,
						status: user.status ?? 'active',
						avatar_url: avatarUrl,
						roles: req.user?.roles ?? [],
						permissions: req.user?.permissions ?? [],
					};
					return sendSuccess(res, responseData);
				} catch (error) {
					return res.error(error);
				}
			},
		},
	};
};
