// src/server/features/tasks/tasks.routes.ts
// HTTP handlers for tasks routes

import { FastifyInstance } from 'fastify';
import { ZodTypeProvider } from 'fastify-type-provider-zod';
import { z } from 'zod';
import { requireAuth } from '@serverShared/lib/auth';
import { AppPermission } from '@shared/contracts/permissions';
import * as tasksService from './tasks.service';
import {
  tasksListResponseSchema,
  taskResponseSchema,
  errorResponseSchema,
  createTaskSchema,
  updateTaskSchema,
  updateTaskPositionsSchema,
  reorderTasksSchema,
} from './tasks.schema';
import { notifyUser } from '@serverShared/plugins/socket';

export const tasksRoutes = async (fastify: FastifyInstance) => {
  const server = fastify.withTypeProvider<ZodTypeProvider>();

  // Get all tasks
  server.get('/', {
    preHandler: [requireAuth(), fastify.can(AppPermission.TASKS_ACCESS)],
    schema: {
      response: {
        200: tasksListResponseSchema,
      },
    },
  }, async (request) => {
    const userId = (request.user as any)?.id;
    if (!userId) {
      throw new Error('Unauthorized');
    }
    return tasksService.getTasks(userId);
  });

  // Get task by ID
  server.get('/:id', {
    preHandler: [requireAuth(), fastify.can(AppPermission.TASKS_ACCESS)],
    schema: {
      params: z.object({
        id: z.string().uuid(),
      }),
      response: {
        200: taskResponseSchema,
        404: errorResponseSchema,
      },
    },
  }, async (request) => {
    const { id } = request.params;
    const userId = (request.user as any)?.id;
    if (!userId) {
      throw new Error('Unauthorized');
    }
    const task = await tasksService.getTaskById(id, userId);
    if (!task) {
      throw new Error('Task not found');
    }
    return task;
  });

  // Create task
  server.post('/', {
    preHandler: [requireAuth(), fastify.can(AppPermission.TASKS_ACCESS)],
    schema: {
      body: createTaskSchema,
      response: {
        201: taskResponseSchema,
      },
    },
  }, async (request) => {
    const userId = (request.user as any)?.id;
    if (!userId) {
      throw new Error('Unauthorized');
    }
    const task = await tasksService.createTask(userId, request.body);
    // Emit socket event to user's personal room
    await notifyUser(userId, 'tasks:created', task);
    return task;
  });

  // Update task
  server.patch('/:id', {
    preHandler: [requireAuth(), fastify.can(AppPermission.TASKS_ACCESS)],
    schema: {
      params: z.object({
        id: z.string().uuid(),
      }),
      body: updateTaskSchema,
      response: {
        200: taskResponseSchema,
        404: errorResponseSchema,
      },
    },
  }, async (request) => {
    const { id } = request.params;
    const userId = (request.user as any)?.id;
    if (!userId) {
      throw new Error('Unauthorized');
    }
    const task = await tasksService.updateTask(id, userId, request.body);
    if (!task) {
      throw new Error('Task not found');
    }
    // Emit socket event to user's personal room
    await notifyUser(userId, 'tasks:updated', task);
    return task;
  });

  // Delete task
  server.delete('/:id', {
    preHandler: [requireAuth(), fastify.can(AppPermission.TASKS_ACCESS)],
    schema: {
      params: z.object({
        id: z.string().uuid(),
      }),
      response: {
        200: z.object({
          success: z.boolean(),
          message: z.string(),
        }),
      },
    },
  }, async (request) => {
    const { id } = request.params;
    const userId = (request.user as any)?.id;
    if (!userId) {
      throw new Error('Unauthorized');
    }
    await tasksService.deleteTask(id, userId);
    // Emit socket event to user's personal room
    await notifyUser(userId, 'tasks:deleted', { id });
    return {
      success: true,
      message: 'Task deleted successfully',
    };
  });

  // Toggle task completion
  server.patch('/:id/toggle', {
    preHandler: [requireAuth(), fastify.can(AppPermission.TASKS_ACCESS)],
    schema: {
      params: z.object({
        id: z.string().uuid(),
      }),
      response: {
        200: taskResponseSchema,
        404: errorResponseSchema,
      },
    },
  }, async (request) => {
    const { id } = request.params;
    const userId = (request.user as any)?.id;
    if (!userId) {
      throw new Error('Unauthorized');
    }
    const task = await tasksService.toggleTask(id, userId);
    if (!task) {
      throw new Error('Task not found');
    }
    // Emit socket event to user's personal room
    await notifyUser(userId, 'tasks:toggled', task);
    return task;
  });

  // Update task positions (batch)
  server.post('/positions', {
    preHandler: [requireAuth(), fastify.can(AppPermission.TASKS_ACCESS)],
    schema: {
      body: updateTaskPositionsSchema,
      response: {
        200: z.object({
          success: z.boolean(),
          message: z.string(),
        }),
      },
    },
  }, async (request) => {
    const userId = (request.user as any)?.id;
    if (!userId) {
      throw new Error('Unauthorized');
    }
    const success = await tasksService.updateTaskPositions(userId, request.body.tasks);
    if (success) {
      // Emit socket event to user's personal room
      await notifyUser(userId, 'tasks:updated', { tasks: request.body.tasks });
    }
    return {
      success,
      message: success ? 'Positions updated successfully' : 'Failed to update positions',
    };
  });

  // Reorder tasks with hierarchy support (batch update for order and parentId)
  server.post('/reorder', {
    preHandler: [requireAuth(), fastify.can(AppPermission.TASKS_ACCESS)],
    schema: {
      body: reorderTasksSchema,
      response: {
        200: z.object({
          success: z.boolean(),
          message: z.string(),
        }),
        400: errorResponseSchema,
      },
    },
  }, async (request) => {
    const userId = (request.user as any)?.id;
    if (!userId) {
      throw new Error('Unauthorized');
    }
    const { rootId, tasks } = request.body;
    await tasksService.reorderTasks(userId, rootId, tasks);
    // Emit socket event to user's personal room
    await notifyUser(userId, 'tasks:reordered', { rootId, tasks });
    return { success: true, message: 'Tasks reordered successfully' };
  });
};
