// Task Team — Extended Collaboration — 2026-03-29

async function collaborationRoutes(app) {

    // === SUBTASKS ===

    // List subtasks for a task
    app.get('/tasks/:taskId/subtasks', async (req) => {
        const { rows } = await app.db.query(
            'SELECT s.*, u.name as assignee_name FROM subtasks s LEFT JOIN users u ON s.assigned_to = u.id WHERE s.parent_task_id = $1 ORDER BY s.order_index',
            [req.params.taskId]
        );
        return { data: rows };
    });

    // Create subtask
    app.post('/tasks/:taskId/subtasks', async (req) => {
        const { title, description, assigned_to, order_index } = req.body;
        if (!title || typeof title !== 'string' || title.trim().length === 0) {
            throw { statusCode: 400, message: 'title is required' };
        }
        // Verify parent task exists
        const { rows: parentCheck } = await app.db.query('SELECT id FROM tasks WHERE id = $1', [req.params.taskId]);
        if (!parentCheck.length) throw { statusCode: 404, message: 'Parent task not found' };

        const { rows } = await app.db.query(
            'INSERT INTO subtasks (parent_task_id, title, description, assigned_to, order_index) VALUES ($1,$2,$3,$4,$5) RETURNING *',
            [req.params.taskId, title.trim(), description || '', assigned_to || null, order_index || 0]
        );
        return { data: rows[0] };
    });

    // Update subtask
    app.put('/tasks/:taskId/subtasks/:id', async (req) => {
        const { title, description, assigned_to, status } = req.body;
        const sets = [];
        const params = [];
        let i = 1;
        if (title !== undefined) { sets.push('title=$' + i); params.push(title); i++; }
        if (description !== undefined) { sets.push('description=$' + i); params.push(description); i++; }
        if (assigned_to !== undefined) { sets.push('assigned_to=$' + i); params.push(assigned_to); i++; }
        if (status) {
            sets.push('status=$' + i); params.push(status); i++;
            if (status === 'done' || status === 'completed') {
                sets.push('completed_at=NOW()');
            }
        }
        if (sets.length === 0) throw { statusCode: 400, message: 'No fields to update' };
        sets.push('updated_at=NOW()');
        params.push(req.params.id);
        const { rows } = await app.db.query(
            'UPDATE subtasks SET ' + sets.join(',') + ' WHERE id=$' + i + ' RETURNING *', params
        );
        if (!rows.length) throw { statusCode: 404, message: 'Subtask not found' };

        // Check if all subtasks done -> auto-complete parent
        const { rows: allSubs } = await app.db.query(
            'SELECT status FROM subtasks WHERE parent_task_id = $1', [req.params.taskId]
        );
        if (allSubs.length > 0 && allSubs.every(s => s.status === 'done' || s.status === 'completed')) {
            await app.db.query(
                "UPDATE tasks SET status='completed', completed_at=NOW(), updated_at=NOW() WHERE id=$1",
                [req.params.taskId]
            );
        }

        return { data: rows[0] };
    });

    // Delete subtask
    app.delete('/tasks/:taskId/subtasks/:id', async (req) => {
        const { rowCount } = await app.db.query('DELETE FROM subtasks WHERE id=$1 AND parent_task_id=$2', [req.params.id, req.params.taskId]);
        if (!rowCount) throw { statusCode: 404, message: 'Subtask not found' };
        return { status: 'deleted' };
    });

    // Reorder subtasks
    app.put('/tasks/:taskId/subtasks/reorder', async (req) => {
        const { order } = req.body; // [{id, order_index}]
        if (!Array.isArray(order)) throw { statusCode: 400, message: 'order must be an array of {id, order_index}' };
        const client = await app.db.connect();
        try {
            await client.query('BEGIN');
            for (const item of order) {
                await client.query(
                    'UPDATE subtasks SET order_index=$1, updated_at=NOW() WHERE id=$2 AND parent_task_id=$3',
                    [item.order_index, item.id, req.params.taskId]
                );
            }
            await client.query('COMMIT');
        } catch (e) {
            await client.query('ROLLBACK');
            throw e;
        } finally {
            client.release();
        }
        return { status: 'ok' };
    });

    // === COLLABORATION REQUESTS ===

    // Send collaboration request (assign, transfer, collaborate, claim)
    app.post('/tasks/:taskId/collaborate', async (req) => {
        const { to_user_id, from_user_id, type, message } = req.body;
        if (!['assign', 'transfer', 'collaborate', 'claim'].includes(type)) {
            throw { statusCode: 400, message: 'Invalid type. Use: assign, transfer, collaborate, claim' };
        }

        // Verify task exists
        const { rows: taskCheck } = await app.db.query('SELECT id FROM tasks WHERE id = $1', [req.params.taskId]);
        if (!taskCheck.length) throw { statusCode: 404, message: 'Task not found' };

        if (type === 'claim') {
            // Direct claim — no approval needed, user takes the task
            const claimUser = from_user_id || to_user_id;
            if (!claimUser) throw { statusCode: 400, message: 'from_user_id or to_user_id required for claim' };

            await app.db.query(
                'UPDATE tasks SET assigned_to = array_append(COALESCE(assigned_to, ARRAY[]::uuid[]), $1::uuid), updated_at=NOW() WHERE id=$2',
                [claimUser, req.params.taskId]
            );
            await app.db.query(
                'INSERT INTO task_collaboration (task_id, from_user_id, to_user_id, type, status, message) VALUES ($1,$2,$2,$3,$4,$5)',
                [req.params.taskId, claimUser, 'claim', 'accepted', message || '']
            );
            return { status: 'claimed' };
        }

        // Other types need approval — to_user_id required
        if (!to_user_id) throw { statusCode: 400, message: 'to_user_id is required' };

        const { rows } = await app.db.query(
            'INSERT INTO task_collaboration (task_id, from_user_id, to_user_id, type, message) VALUES ($1,$2,$3,$4,$5) RETURNING *',
            [req.params.taskId, from_user_id || null, to_user_id, type, message || '']
        );
        return { data: rows[0], status: 'pending' };
    });

    // Respond to collaboration request
    app.post('/collaboration/:id/respond', async (req) => {
        const { accept } = req.body;
        if (accept === undefined) throw { statusCode: 400, message: 'accept (true/false) is required' };

        const { rows } = await app.db.query(
            'UPDATE task_collaboration SET status=$1, responded_at=NOW() WHERE id=$2 AND status=$3 RETURNING *',
            [accept ? 'accepted' : 'rejected', req.params.id, 'pending']
        );
        if (!rows.length) throw { statusCode: 404, message: 'Pending request not found' };

        const collab = rows[0];
        if (accept) {
            if (collab.type === 'assign' || collab.type === 'collaborate') {
                // Add user to assigned_to array
                await app.db.query(
                    'UPDATE tasks SET assigned_to = array_append(COALESCE(assigned_to, ARRAY[]::uuid[]), $1::uuid), updated_at=NOW() WHERE id=$2',
                    [collab.to_user_id, collab.task_id]
                );
            } else if (collab.type === 'transfer') {
                // Transfer ownership: set user_id and optionally remove from assigned_to
                await app.db.query(
                    'UPDATE tasks SET user_id=$1, updated_at=NOW() WHERE id=$2',
                    [collab.to_user_id, collab.task_id]
                );
            }
        }
        return { data: collab };
    });

    // List pending collaboration requests for a user
    app.get('/collaboration/pending/:userId', async (req) => {
        const { rows } = await app.db.query(
            `SELECT tc.*, t.title as task_title, t.status as task_status, u.name as from_name
             FROM task_collaboration tc
             JOIN tasks t ON tc.task_id = t.id
             LEFT JOIN users u ON tc.from_user_id = u.id
             WHERE tc.to_user_id = $1 AND tc.status = 'pending'
             ORDER BY tc.created_at DESC`,
            [req.params.userId]
        );
        return { data: rows };
    });

    // List all collaboration history for a task
    app.get('/tasks/:taskId/collaboration', async (req) => {
        const { rows } = await app.db.query(
            `SELECT tc.*, uf.name as from_name, ut.name as to_name
             FROM task_collaboration tc
             LEFT JOIN users uf ON tc.from_user_id = uf.id
             LEFT JOIN users ut ON tc.to_user_id = ut.id
             WHERE tc.task_id = $1
             ORDER BY tc.created_at DESC`,
            [req.params.taskId]
        );
        return { data: rows };
    });

    // === ASSIGN TO GROUP ===

    // Assign task to all members of a user group
    app.post('/tasks/:taskId/assign-group', async (req) => {
        const { group_id } = req.body;
        if (!group_id) throw { statusCode: 400, message: 'group_id is required' };

        const { rows } = await app.db.query('SELECT members FROM user_groups WHERE id=$1', [group_id]);
        if (!rows.length) throw { statusCode: 404, message: 'Group not found' };

        const members = rows[0].members || [];
        if (members.length === 0) throw { statusCode: 400, message: 'Group has no members' };

        await app.db.query(
            'UPDATE tasks SET assigned_to = $1::uuid[], updated_at=NOW() WHERE id=$2',
            [members, req.params.taskId]
        );
        return { status: 'assigned', members_count: members.length };
    });

    // === USER GROUPS (Teams) ===

    app.get('/user-groups', async (req) => {
        const { rows } = await app.db.query(
            `SELECT ug.*, u.name as owner_name,
             (SELECT COUNT(*) FROM unnest(ug.members)) as member_count
             FROM user_groups ug
             LEFT JOIN users u ON ug.owner_id = u.id
             ORDER BY ug.name`
        );
        return { data: rows };
    });

    app.get('/user-groups/:id', async (req) => {
        const { rows } = await app.db.query(
            `SELECT ug.*, u.name as owner_name
             FROM user_groups ug
             LEFT JOIN users u ON ug.owner_id = u.id
             WHERE ug.id = $1`,
            [req.params.id]
        );
        if (!rows.length) throw { statusCode: 404, message: 'Group not found' };

        // Resolve member names
        const group = rows[0];
        if (group.members && group.members.length > 0) {
            const { rows: memberRows } = await app.db.query(
                'SELECT id, name, email, avatar_url FROM users WHERE id = ANY($1)',
                [group.members]
            );
            group.member_details = memberRows;
        } else {
            group.member_details = [];
        }
        return { data: group };
    });

    app.post('/user-groups', async (req) => {
        const { name, description, owner_id, members } = req.body;
        if (!name || typeof name !== 'string' || name.trim().length === 0) {
            throw { statusCode: 400, message: 'name is required' };
        }
        const { rows } = await app.db.query(
            'INSERT INTO user_groups (name, description, owner_id, members) VALUES ($1,$2,$3,$4) RETURNING *',
            [name.trim(), description || '', owner_id || null, members || []]
        );
        return { data: rows[0] };
    });

    app.put('/user-groups/:id', async (req) => {
        const { name, description } = req.body;
        const sets = [];
        const params = [];
        let i = 1;
        if (name !== undefined) { sets.push('name=$' + i); params.push(name); i++; }
        if (description !== undefined) { sets.push('description=$' + i); params.push(description); i++; }
        if (sets.length === 0) throw { statusCode: 400, message: 'No fields to update' };
        params.push(req.params.id);
        const { rows } = await app.db.query(
            'UPDATE user_groups SET ' + sets.join(',') + ' WHERE id=$' + i + ' RETURNING *', params
        );
        if (!rows.length) throw { statusCode: 404, message: 'Group not found' };
        return { data: rows[0] };
    });

    app.delete('/user-groups/:id', async (req) => {
        const { rowCount } = await app.db.query('DELETE FROM user_groups WHERE id=$1', [req.params.id]);
        if (!rowCount) throw { statusCode: 404, message: 'Group not found' };
        return { status: 'deleted' };
    });

    // Add member to group
    app.post('/user-groups/:id/members', async (req) => {
        const { user_id } = req.body;
        if (!user_id) throw { statusCode: 400, message: 'user_id is required' };

        // Check user exists
        const { rows: userCheck } = await app.db.query('SELECT id FROM users WHERE id = $1', [user_id]);
        if (!userCheck.length) throw { statusCode: 404, message: 'User not found' };

        // Prevent duplicates
        const { rows: groupCheck } = await app.db.query('SELECT members FROM user_groups WHERE id = $1', [req.params.id]);
        if (!groupCheck.length) throw { statusCode: 404, message: 'Group not found' };
        if (groupCheck[0].members && groupCheck[0].members.includes(user_id)) {
            return { status: 'already_member' };
        }

        const { rows } = await app.db.query(
            'UPDATE user_groups SET members = array_append(members, $1::uuid) WHERE id=$2 RETURNING *',
            [user_id, req.params.id]
        );
        return { data: rows[0] };
    });

    // Remove member from group
    app.delete('/user-groups/:id/members/:userId', async (req) => {
        const { rows } = await app.db.query(
            'UPDATE user_groups SET members = array_remove(members, $1::uuid) WHERE id=$2 RETURNING *',
            [req.params.userId, req.params.id]
        );
        if (!rows.length) throw { statusCode: 404, message: 'Group not found' };
        return { data: rows[0] };
    });

    // === WHO IS DOING WHAT ===

    // Get workload overview: for each user, list tasks assigned to them and their status
    app.get('/collaboration/workload', async (req) => {
        const { rows } = await app.db.query(
            `SELECT u.id, u.name, u.email, u.avatar_url,
                    (SELECT COUNT(*) FROM tasks t WHERE u.id = ANY(t.assigned_to) AND t.status NOT IN ('done','completed','cancelled')) as active_tasks,
                    (SELECT COUNT(*) FROM tasks t WHERE u.id = ANY(t.assigned_to) AND t.status IN ('done','completed')) as completed_tasks,
                    (SELECT COUNT(*) FROM subtasks s WHERE s.assigned_to = u.id AND s.status NOT IN ('done','completed')) as active_subtasks,
                    (SELECT COUNT(*) FROM task_collaboration tc WHERE tc.to_user_id = u.id AND tc.status = 'pending') as pending_requests
             FROM users u
             ORDER BY u.name`
        );
        return { data: rows };
    });

    // Get tasks for a specific user (assigned to them)
    app.get('/collaboration/user/:userId/tasks', async (req) => {
        const { rows } = await app.db.query(
            `SELECT t.*, tg.name as group_name, tg.color as group_color,
                    (SELECT COUNT(*) FROM subtasks s WHERE s.parent_task_id = t.id) as subtask_count,
                    (SELECT COUNT(*) FROM subtasks s WHERE s.parent_task_id = t.id AND s.status IN ('done','completed')) as subtask_done_count
             FROM tasks t
             LEFT JOIN task_groups tg ON t.group_id = tg.id
             WHERE $1::uuid = ANY(t.assigned_to)
             ORDER BY t.priority DESC, t.created_at DESC`,
            [req.params.userId]
        );
        return { data: rows };
    });
}

module.exports = collaborationRoutes;
