import { TaskService } from './task.service';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { TaskQueryDTO, TaskDTO } from './dto/task-dto';
import { ColumnDTO, ColumnQueryDTO, ColumnWhereParams } from './dto/column-dto';
import {
  ApiOkResponseListWithTotal,
  ApiResultListWithTotal,
} from 'src/common/types/api-result';
import {
  Controller,
  Get,
  UsePipes,
  ValidationPipe,
  Query,
  Post,
  Body,
  Patch,
  Delete,
  Param,
  UseInterceptors,
  UseGuards,
} from '@nestjs/common';
import {
  ProjectAccess,
  ProjectAccessInterceptor,
  RequestProjectAccess,
} from '../utils/project-access';
import { ColumnEntity } from 'src/entities/column.entity';
import { OptTokenOrJwtAuthGuard } from '../guards/opt-token-or-jwt.auth.guard';
import { convertAssetQueryToSelectionBase } from '../asset/asset-utils';

@ApiTags('task')
@Controller('tasks')
@UseInterceptors(ProjectAccessInterceptor)
@UseGuards(OptTokenOrJwtAuthGuard)
@ApiBearerAuth()
export class TaskController {
  constructor(private readonly taskService: TaskService) {}

  @Get('columns')
  @ApiOperation({
    summary: 'Get columns',
  })
  @ApiOkResponseListWithTotal(ColumnEntity)
  @UsePipes(
    new ValidationPipe({
      transform: true,
      transformOptions: { enableImplicitConversion: true },
    }),
  )
  @UseInterceptors(ProjectAccessInterceptor)
  async getColumns(
    @RequestProjectAccess() projectAccess: ProjectAccess,
    @Query() filterData: ColumnQueryDTO,
  ): Promise<ApiResultListWithTotal<ColumnEntity>> {
    const res = await this.taskService.getColumns(filterData, projectAccess);
    return res;
  }

  @Post('columns')
  @ApiOperation({
    summary: 'Create column',
  })
  @UseInterceptors(ProjectAccessInterceptor)
  async createColumn(
    @Body() column: ColumnDTO,
    @RequestProjectAccess() projectAccess: ProjectAccess,
  ): Promise<ColumnEntity> {
    const res = await this.taskService.createColumn(
      column.title,
      projectAccess,
    );
    return res;
  }

  @Post('columns/reorder')
  @ApiOperation({
    summary: 'Reorder columns',
  })
  @UseInterceptors(ProjectAccessInterceptor)
  async reorderColumns(
    @Body() param: ColumnWhereParams,
    @RequestProjectAccess() projectAccess: ProjectAccess,
  ): Promise<any> {
    return await this.taskService.reorderColumns(param.ids, projectAccess);
  }

  @Patch('columns/:id')
  @ApiOperation({
    summary: 'Change column',
  })
  @UseInterceptors(ProjectAccessInterceptor)
  async editColumn(
    @Param('id') id: string,
    @Body() column: ColumnDTO,
    @RequestProjectAccess() projectAccess: ProjectAccess,
  ): Promise<ColumnEntity> {
    return await this.taskService.editColumn(id, column, projectAccess);
  }

  @Delete('columns/:id')
  @ApiOperation({
    summary: 'Delete column',
  })
  @UseInterceptors(ProjectAccessInterceptor)
  async deleteColumn(
    @Param('id') id: string,
    @RequestProjectAccess() projectAccess: ProjectAccess,
  ): Promise<void> {
    return await this.taskService.deleteColumn(id, projectAccess);
  }

  @Get('list')
  @ApiOperation({
    summary: 'Get task list',
  })
  @ApiOkResponseListWithTotal(TaskDTO)
  @UsePipes(
    new ValidationPipe({
      transform: true,
      transformOptions: { enableImplicitConversion: true },
    }),
  )
  async getTasks(
    @Query() filterData: TaskQueryDTO,
    @RequestProjectAccess() projectAccess: ProjectAccess,
  ): Promise<ApiResultListWithTotal<TaskDTO>> {
    const selection = convertAssetQueryToSelectionBase(filterData);
    return await this.taskService.getTasks(selection, projectAccess);
  }
}
