'use strict';

const usersService = require('./service');
const { UnauthorizedError } = require('../../shared/errors');
const { getAuthenticatedUserId } = require('../../utils/request-utils');
const { logError } = require('../../services/logService');
const fs = require('fs').promises;
const path = require('path');
const { getConfig } = require('../../config/config');

const config = getConfig();

function requireUserId(req) {
    const userId = getAuthenticatedUserId(req);
    if (!userId) {
        throw new UnauthorizedError('Authentication required');
    }
    return userId;
}

async function safeDeleteFile(filePath) {
    if (!filePath) return;

    const uploadDir = path.resolve(config.uploadPath);
    const resolvedPath = path.resolve(filePath);
    const relativePath = path.relative(uploadDir, resolvedPath);

    if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
        logError('Attempt to delete file outside upload directory:', filePath);
        return;
    }

    await fs.unlink(resolvedPath).catch(() => {});
}

/**
 * Users controller - handles HTTP requests/responses.
 */
const usersController = {
    /**
     * GET /api/users
     * List all users.
     */
    async list(req, res, next) {
        try {
            const users = await usersService.listUsers();
            res.json(users);
        } catch (error) {
            next(error);
        }
    },

    /**
     * GET /api/profile
     * Get current user profile.
     */
    async getProfile(req, res, next) {
        try {
            const userId = requireUserId(req);
            const profile = await usersService.getProfile(userId);
            res.json(profile);
        } catch (error) {
            next(error);
        }
    },

    /**
     * PATCH /api/profile
     * Update current user profile.
     */
    async updateProfile(req, res, next) {
        try {
            const userId = requireUserId(req);
            const profile = await usersService.updateProfile(userId, req.body);
            res.json(profile);
        } catch (error) {
            next(error);
        }
    },

    /**
     * POST /api/profile/avatar
     * Upload avatar.
     */
    async uploadAvatar(req, res, next) {
        try {
            const userId = requireUserId(req);
            const result = await usersService.uploadAvatar(userId, req.file);
            res.json(result);
        } catch (error) {
            if (req.file?.path) {
                await safeDeleteFile(req.file.path);
            }
            next(error);
        }
    },

    /**
     * DELETE /api/profile/avatar
     * Delete avatar.
     */
    async deleteAvatar(req, res, next) {
        try {
            const userId = requireUserId(req);
            const result = await usersService.deleteAvatar(userId);
            res.json(result);
        } catch (error) {
            next(error);
        }
    },

    /**
     * POST /api/profile/change-password
     * Change password.
     */
    async changePassword(req, res, next) {
        try {
            const userId = requireUserId(req);
            const { currentPassword, newPassword } = req.body;
            const result = await usersService.changePassword(
                userId,
                currentPassword,
                newPassword
            );
            res.json(result);
        } catch (error) {
            next(error);
        }
    },

    /**
     * GET /api/profile/api-keys
     * List API keys.
     */
    async listApiKeys(req, res, next) {
        try {
            const userId = requireUserId(req);
            const keys = await usersService.listApiKeys(userId);
            res.json(keys);
        } catch (error) {
            next(error);
        }
    },

    /**
     * POST /api/profile/api-keys
     * Create API key.
     */
    async createApiKey(req, res, next) {
        try {
            const userId = requireUserId(req);
            const { name, expires_at } = req.body || {};
            const result = await usersService.createApiKey(
                userId,
                name,
                expires_at
            );
            res.status(201).json(result);
        } catch (error) {
            next(error);
        }
    },

    /**
     * POST /api/profile/api-keys/:id/revoke
     * Revoke API key.
     */
    async revokeApiKey(req, res, next) {
        try {
            const userId = requireUserId(req);
            const result = await usersService.revokeApiKey(
                userId,
                req.params.id
            );
            res.json(result);
        } catch (error) {
            next(error);
        }
    },

    /**
     * DELETE /api/profile/api-keys/:id
     * Delete API key.
     */
    async deleteApiKey(req, res, next) {
        try {
            const userId = requireUserId(req);
            await usersService.deleteApiKey(userId, req.params.id);
            res.status(204).send();
        } catch (error) {
            next(error);
        }
    },

    /**
     * POST /api/profile/task-summary/toggle
     * Toggle task summary.
     */
    async toggleTaskSummary(req, res, next) {
        try {
            const userId = requireUserId(req);
            const result = await usersService.toggleTaskSummary(userId);
            res.json(result);
        } catch (error) {
            next(error);
        }
    },

    /**
     * POST /api/profile/task-summary/frequency
     * Update task summary frequency.
     */
    async updateTaskSummaryFrequency(req, res, next) {
        try {
            const userId = requireUserId(req);
            const { frequency } = req.body;
            const result = await usersService.updateTaskSummaryFrequency(
                userId,
                frequency
            );
            res.json(result);
        } catch (error) {
            next(error);
        }
    },

    /**
     * POST /api/profile/task-summary/send-now
     * Send task summary now.
     */
    async sendTaskSummaryNow(req, res, next) {
        try {
            const userId = requireUserId(req);
            const result = await usersService.sendTaskSummaryNow(userId);
            res.json(result);
        } catch (error) {
            next(error);
        }
    },

    /**
     * GET /api/profile/task-summary/status
     * Get task summary status.
     */
    async getTaskSummaryStatus(req, res, next) {
        try {
            const userId = requireUserId(req);
            const result = await usersService.getTaskSummaryStatus(userId);
            res.json(result);
        } catch (error) {
            next(error);
        }
    },

    /**
     * PUT /api/profile/today-settings
     * Update today settings.
     */
    async updateTodaySettings(req, res, next) {
        try {
            const userId = requireUserId(req);
            const result = await usersService.updateTodaySettings(
                userId,
                req.body
            );
            res.json(result);
        } catch (error) {
            next(error);
        }
    },

    /**
     * PUT /api/profile/sidebar-settings
     * Update sidebar settings.
     */
    async updateSidebarSettings(req, res, next) {
        try {
            const userId = requireUserId(req);
            const result = await usersService.updateSidebarSettings(
                userId,
                req.body
            );
            res.json(result);
        } catch (error) {
            next(error);
        }
    },

    /**
     * PUT /api/profile/ui-settings
     * Update UI settings.
     */
    async updateUiSettings(req, res, next) {
        try {
            const userId = requireUserId(req);
            const result = await usersService.updateUiSettings(
                userId,
                req.body
            );
            res.json(result);
        } catch (error) {
            next(error);
        }
    },
};

module.exports = usersController;
