import { Controller, Request, Post, Body, Get, Res, UseGuards, UseInterceptors, UploadedFile, Patch, Query, Put, Param, Delete } from "@nestjs/common"
import { ApiOperation, ApiQuery, ApiResponse, ApiTags, ApiBody, ApiConsumes, ApiBearerAuth } from "@nestjs/swagger"
import { KeywordsService } from "./keywords.services"
import { toJsonResponse } from "../../common/response"

import { AdminGuard } from "../auth/guards/admin.guard"
import { CommonGuard } from "../auth/guards/common.guard"

// DTO Files
import { CreateDto } from "./dtos/create.dto"
import { ListQueryDto } from "./dtos/list-query.dto"
import { UpdateDto } from "./dtos/update.dto"
import { KeywordIdParamDto } from "./dtos/keyword-id-param.dto"

@ApiTags("keywords")
@Controller("keywords")
export class KeywordsController {
    constructor(private keywordsService: KeywordsService) { }

    // JP-
    /**
     * Create keyword based on request parameters.
     *
     * @Body request - An instance of CreateDto containing the keyword data to process of storing data.
     * @param response - The response object for sending the HTTP response.
     *
     * Responds with a 201 status if successful.
     * Logs the error and responds with the error status and message if an exception occurs.
     */
    @ApiBearerAuth("access-token")
    @ApiBody({ type: CreateDto })
    @UseGuards(AdminGuard)
    @Post()
    async create(@Body() request: CreateDto, @Request() req, @Res() response: any) {
        console.log("request", request);
        const data = await this.keywordsService.create(request)
        response.status(201).json(data)

    }

    // JP-
    /**
     * Update keyword based on request parameters.
     * @param params - An instance of KeywordIdParamDto containing the keyword id to process of update data.
     * @Body request - An instance of UpdateDto containing the keyword data to process of update data.
     * @param response - The response object for sending the HTTP response.
     *
     * Responds with a 201 status if successful.
     * Logs the error and responds with the error status and message if an exception occurs.
     */
    @ApiBearerAuth("access-token")
    @ApiBody({ type: UpdateDto })
    @UseGuards(AdminGuard)
    @Put(":keyword_id")
    async update(@Param() params: KeywordIdParamDto, @Body() request: UpdateDto, @Request() req, @Res() response: any) {
        try {
            const data = await this.keywordsService.update(params, request)
            response.status(201).json(data)
        } catch (error) {
            console.log(error)
            response.status(error.status).json(toJsonResponse(error.status, error.message))
        }
    }

    /** JP-
     * Retrieves a list of keywords for admin with two languages (en as default and requested language).
     *
     * @param queryParam - Query parameters for listing keyword list, including pagination, sorting options, and language_code.
     * @param req - The request object, containing the authenticated user information.
     * @param response - The response object for sending the JSON response.
     *
     * Responds with a 200 status and the list of keywords with translations in two languages (en and requested language) if successful.
     * Logs the error and responds with the error status and message if an exception occurs.
     */
    @ApiBearerAuth("access-token")
    @ApiQuery({ name: "page", required: true, example: 1 })
    @ApiQuery({ name: "per_page", required: true, example: 50 })
    @ApiQuery({ name: "sort_by", required: false, type: "string" })
    @ApiQuery({ name: "sort", required: false, type: "string" })
    @ApiQuery({ name: "search", required: false, type: "string" })
    @ApiQuery({ name: "language_code", required: false, type: "string", description: "Language code for second translation (defaults to en). Returns en and requested language translations." })
    @UseGuards(AdminGuard)
    @Get("admin/list")
    async adminList(@Query() queryParam: ListQueryDto, @Request() req, @Res() response: any) {
        try {
            const data = await this.keywordsService.adminList(queryParam)
            response.status(200).json(data)
        } catch (error) {
            console.log(error)
            response.status(error.status).json(toJsonResponse(error.status, error.message))
        }
    }

    /** JP-
     * Retrieves a list of keywords on query parameters.
     *
     * @param queryParam - Query parameters for listing keyword list, including pagination and sorting options.
     * @param req - The request object, containing the authenticated user information.
     * @param response - The response object for sending the JSON response.
     *
     * Responds with a 200 status and the list of keywords if successful.
     * Logs the error and responds with the error status and message if an exception occurs.
     */
    @ApiQuery({ name: "page", required: true, example: 1 })
    @ApiQuery({ name: "per_page", required: true, example: 50 })
    @ApiQuery({ name: "sort_by", required: false, type: "string" })
    @ApiQuery({ name: "sort", required: false, type: "string" })
    @ApiQuery({ name: "search", required: false, type: "string" })
    @UseGuards(CommonGuard)
    @Get()
    async list(@Query() queryParam: ListQueryDto, @Request() req, @Res() response: any) {
        try {
            const data = await this.keywordsService.list(queryParam, req.user)
            response.status(200).json(data)
        } catch (error) {
            console.log(error)
            response.status(error.status).json(toJsonResponse(error.status, error.message))
        }
    }

    /** JP-
     * Get keyword details by ID.
     * @param params - An instance of KeywordIdParamDto containing the keyword id.
     * @param query - Query parameters including optional language_code.
     * @param req - The request object, containing the authenticated user information.
     * @param response - The response object for sending the HTTP response.
     *
     * Responds with a 200 status and the keyword details if successful.
     * Logs the error and responds with the error status and message if an exception occurs.
     */
    @ApiQuery({ name: "language_code", required: false, type: "string", description: "Language code for translations (defaults to en)" })
    @UseGuards(CommonGuard)
    @Get(":keyword_id")
    async detail(@Param() params: KeywordIdParamDto, @Request() req, @Res() response: any) {

        const data = await this.keywordsService.detail(params, req.user)
        response.status(200).json(data)

    }

    /**
     * Script: convert all English keyword translations to Korean (OpenAI).
     * Query: overwrite=true to replace existing Korean rows; limit=N for a test run.
     */
    @ApiBearerAuth("access-token")
    @ApiOperation({ summary: 'Convert English keywords to Korean (admin script)' })
    @ApiQuery({ name: 'overwrite', required: false, type: 'boolean', description: 'Replace existing Korean translations' })
    @ApiQuery({ name: 'limit', required: false, type: 'number', description: 'Max keywords to process (for testing)' })
    @UseGuards(AdminGuard)
    @Post('script/convert-english-to-korean')
    async convertEnglishToKorean(@Query() query: any, @Res() response: any) {
        try {
            const data = await this.keywordsService.convertEnglishKeywordsToKorean();
            response.status(200).json(data);
        } catch (error) {
            console.log(error);
            response.status(error.status || 500).json(toJsonResponse(error.status || 500, error.message));
        }
    }

    @Delete(":keyword_id")
    async delete(@Param() params: KeywordIdParamDto, @Request() req, @Res() response: any) {
        try {
            await this.keywordsService.delete(params)
            response.status(201).json()
        } catch (error) {
            console.log(error)
            response.status(error.status).json(toJsonResponse(error.status, error.message))
        }
    }
}

