import { Body, Controller, Get, HttpCode, Param, ParseUUIDPipe, Post, Put, Query, UseFilters, UseInterceptors } from "@nestjs/common";
import { SearchService } from "../../core/services/common/search.service";
import { PageInterceptor } from "../../core/interceptors/page.interceptor";
import { ApiExtraModels, ApiGatewayTimeoutResponse, ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
import { EsHitDto, EsResponseDto, PageDto, PaperDto, SearchQueryDto } from "../../core/domain";
import { HttpExceptionFilter } from "../../core/filters/http-exception.filter";
import { UploadService } from "../../core/services/common/upload.service";

/**
 * /papers/ route controller
 */
@UseFilters(HttpExceptionFilter)
@Controller({
    version: '1',
    path: 'papers',
})
@ApiExtraModels(EsHitDto, EsResponseDto)
export class PapersController {
    constructor(
        private searchService: SearchService,
        private uploadService: UploadService
    ) {}

    /**
     * Request handler for: GET /papers/search
     * @param query 
     * @param response 
     * @returns a response with a set of matching papers
     */
    @ApiTags('Search')
    @ApiOperation({ 
        summary: 'Finds papers by context based on the query',
    })
    @ApiResponse({
        status: 200,
        description: 'Returns back a page with acquired papers',
        type: PageDto
    })
    @ApiGatewayTimeoutResponse({
        description: 'Elasticsearch request timed out'
    })
    @Get('search')
    @HttpCode(200)
    @UseInterceptors(PageInterceptor)
    getByContext(@Query() request: SearchQueryDto): Promise<EsResponseDto> {
        return this.searchService.findByContext(request).then(
            (response) => {
                return response;
            },
            (error) => {
                throw error;
            }
        );
    }

    /**
     * Request handler for GET /papers/{uuid}
     * @param uuid 
     * @param response 
     * @returns a response with a requested object
     */
    @ApiTags('Search')
    @ApiOperation({ 
        summary: 'Finds paper by its UUID',
        tags: ['Search']
    })
    @ApiResponse({
        status: 200,
        description: 'Returns back a paper',
        type: PaperDto
    })
    @ApiGatewayTimeoutResponse({
        description: 'Elasticsearch request timed out'
    })
    @Get(':uuid')
    @HttpCode(200)
    getByID(@Param('uuid', ParseUUIDPipe) uuid: string): Promise<PaperDto> {
        return this.searchService.findByID(uuid).then(
            (response: EsResponseDto) => {
                return response.hits.hits[0]?._source;
            },
            (error) => {
                throw error;
            }
        );
    }

    /**
     * Request handler for PUT /papers/upload
     * @param uuid 
     * @param response 
     * @returns a response with a requested object
     */
    @ApiTags('Upload')
    @ApiOperation({ 
        summary: 'Uploads paper',
        tags: ['Upload']
    })
    @Put('upload')
    uploadPaper(@Body() paperData: PaperDto) {
        console.log('gdgdgdgd')
       return this.uploadService.upload(paperData).then(
            (response) => {
                return response;
            },
            (error) => {
                throw error;
            }
       )
    }
}