import { Controller, Request, Post, Body, Get, Res, UseGuards, UseInterceptors, UploadedFile, Patch, Query, Param, Put } from '@nestjs/common';
import { ApiOperation, ApiQuery, ApiResponse, ApiTags, ApiBody, ApiConsumes, ApiBearerAuth, ApiParam } from '@nestjs/swagger';
import { AdminService } from './admin.services';
import { toJsonResponse } from '../../common/response';
import { AdminGuard } from '../auth/guards/admin.guard';

// DTO Files
import { UserListQueryDto } from './dtos/user-list-query.dto';
import { UserDetailsQueryDto } from './dtos/user-details-query.dto';
import { SocialMediaPostQuery } from './dtos/social-meida-list-query.dto';
import { UserSlugParamDto } from './dtos/user-slug-param.dto';
import { CommonGuard } from '../auth/guards/common.guard';
import { ImportUsersDto } from './dtos/import-users.dto';
import { AdminUpdateDto } from './dtos/admin-edit.dto';
import { CurrencyExchangeUpdateDto } from './dtos/currency-rate-update.dto';

@ApiTags('admin')
@Controller('admin')
export class AdminController {
    constructor(private adminService: AdminService) { }

    // JP-
    @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: 'role', required: true, type: 'string' })
    @UseGuards(AdminGuard)
    @Get('users')
    /**
    * Retrieves a list of users based on query parameters.
    *
    * @param queryParam - Query parameters for listing users, 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 users if successful.
    * Logs the error and responds with the error status and message if an exception occurs.
    */
    async userList(@Query() queryParam: UserListQueryDto, @Request() req, @Res() response: any) {
        try {
            const data = await this.adminService.userList(queryParam, req.user);
            response.status(200).json(data);
        } catch (error) {
            console.log(error);
            response.status(error.status).json(toJsonResponse(error.status, error.message));
        }
    }

    /**
    * Retrieves a user details based on query parameters.
    *
    * @param params - Query parameters for retrieving a user details.
    * @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 user details if successful.
    * Logs the error and responds with the error status and message if an exception occurs.
    */
    @UseGuards(CommonGuard)
    @Get('users/:slug')
    async userDetails(@Param() params: UserDetailsQueryDto, @Query() queryParam: any, @Request() req, @Res() response: any) {
        try {
            const data = await this.adminService.userDetails(params, req.user, queryParam);
            response.status(200).json(data);
        } catch (error) {
            console.log(error);
            response.status(error.status).json(toJsonResponse(error.status, error.message));
        }
    }

    @UseGuards(AdminGuard)
    @Get('dashboard')
    async dashboard(@Query() params: any, @Request() req, @Res() response: any) {
        try {
            const data = await this.adminService.dashboard(params);
            response.status(200).json(data);
        } catch (error) {
            console.log(error);
            response.status(error.status).json(toJsonResponse(error.status, error.message));
        }
    }

    @UseGuards(AdminGuard)
    @Get('dashboard/chart')
    async dashboardChart(@Query() params: any, @Request() req, @Res() response: any) {
        try {
            console.log("CHART");
            const data = await this.adminService.dashboardChart(params);
            response.status(200).json(data);
        } catch (error) {
            console.log(error);
            response.status(error.status).json(toJsonResponse(error.status, error.message));
        }
    }

    //@UseGuards(CommonGuard)
    @Get('social-media-posts')
    async getSocialMediaPosts(@Query() params: SocialMediaPostQuery, @Request() req, @Res() response: any) {
        try {
            const data = await this.adminService.getSocialMediaPosts(params, req.user);
            response.status(200).json(data);
        } catch (error) {
            console.log(error);
            response.status(error.status).json(toJsonResponse(error.status, error.message));
        }
    }

    @UseGuards(AdminGuard)
    @Get('currency-exchange-list')
    async currencyExchangeList(@Request() req, @Res() response: any) {
        try {
            const data = await this.adminService.currencyExchangeList();
            response.status(200).json(data);
        } catch (error) {
            console.log(error);
            response.status(error.status).json(toJsonResponse(error.status, error.message));
        }
    }

    @UseGuards(AdminGuard)
    @Put('currency-exchange')
    async currencyExchangeUpdate(@Body() request: CurrencyExchangeUpdateDto, @Request() req, @Res() response: any) {
        try {
            const data = await this.adminService.currencyExchangeUpdate(request);
            response.status(200).json(data);
        } catch (error) {
            console.log(error);
            response.status(error.status).json(toJsonResponse(error.status, error.message));
        }
    }

    /**
    * Retrieves a user details based on parameters.
    *
    * @param params - An instance of UserSlugParamDto containing the user slug to be updated.
    * The request, if user activation status is active than its inactive or if user activation status is inactive then its make active.
    * @param response - The response object for sending the HTTP response.
    *
    * Responds with a 201 status and the user activation status update if successful.
    * Logs the error and responds with the error status and message if an exception occurs.
    */
    @UseGuards(AdminGuard)
    @Patch('activation-status/:slug')
    async activationStatusUpdate(@Param() params: UserSlugParamDto, @Request() req, @Res() response: any) {
        try {
            const data = await this.adminService.activationStatusUpdate(params, req.user);
            response.status(201).json(data);
        } catch (error) {
            console.log(error);
            response.status(error.status).json(toJsonResponse(error.status, error.message));
        }
    }

    @ApiBearerAuth('access-token')
    @ApiParam({ name: 'slug', required: true })
    @Put('edit/:slug')
    /**
     * Updates the admin data based on the provided request data.
     *
     * @param params - An instance of adminSlugParamDto containing the admin slug to be updated.
     * @param request - An instance of adminUpdateDto containing the admin information to be updated.
     * @param response - The response object for sending the HTTP response.
     * @param req - The request object, containing the authenticated user information.
     * Responds with a 201 status if the update is successful.
     * In case of an error, logs the error and responds with the respective error status and message.
     */
    async adminUpdate(@Param() params: UserSlugParamDto, @Body() request: AdminUpdateDto, @Request() req, @Res() response: any) {
        try {
            await this.adminService.adminEdit(params, request);
            response.status(201).json();
        } catch (error) {
            response.status(error.status).json(toJsonResponse(error.status, error.message));
        }
    }
    @UseGuards(AdminGuard)
    @Post('encryption')
    async encryptionKey(@Body() request: any, @Res() response: any) {
        try {
            const data = await this.adminService.encryptionKey(request);
            response.status(201).json(data);
        } catch (error) {
            response.status(error.status).json(toJsonResponse(error.status, error.message));
        }
    }
}
