import { Controller, Get, Post, Body, Param, UseGuards, Res, Req, HttpException, Query, Put, Patch } from '@nestjs/common';
import { PlanService } from './plan.service';
import { CreatePlanDto } from './dto/create-plan.dto';
import { ApiBearerAuth, ApiBody, ApiTags } from '@nestjs/swagger';
import { AdminGuard } from '../auth/guards/admin.guard';
import { response } from 'express';
import { responseMessages } from 'src/messages/response-messages';
import { toJsonResponse } from 'src/common/response';
import { ListPlanDto } from './dto/list-plan.dto';
import { CommonGuard } from '../auth/guards/common.guard';
import { PlanIdParamDto } from './dto/plan-id-param.dto';
import { PlanSlugParamDto } from './dto/plan-slug-param.dto';

@ApiTags('plans')
@Controller('plans')
export class PlanController {
    constructor(private readonly planService: PlanService) { }

    /**
     * Handles the creation of a new plan.
     * @param createPlanDto - The data transfer object containing the details of the plan to be created.
     * @returns A success response with status 201 if the plan is created successfully.
     * @throws An error response with the corresponding status and message if plan creation fails.
     */
    @ApiBearerAuth('access-token')
    @ApiBody({ type: CreatePlanDto })
    @UseGuards(AdminGuard)
    @Post()
    async createPlan(@Body() createPlanDto: CreatePlanDto, @Req() req, @Res() response) {
        try {
            await this.planService.createPlan(createPlanDto, req.user);
            return response.status(201).json();
        } catch (error) {
            console.log(error)
            response.status(error.status).json(toJsonResponse(error.status, error.message));
        }
    }

    /**
     * Handles the retrieval of plans based on the given query parameters.
     * @param listPlanDto - The data transfer object containing the query parameters.
     * @returns A success response with status 200 if the plans are retrieved successfully.
     * @throws An error response with the corresponding status and message if plan retrieval fails.
     */
    @ApiBearerAuth('access-token')
    @UseGuards(CommonGuard)
    @Get()
    async listPlan(@Query() listPlanDto: ListPlanDto, @Req() req, @Res() response) {
        try {
            const data = await this.planService.listPlan(listPlanDto, req.user);
            return response.status(200).json(data);
        } catch (error) {
            console.log(error)
            response.status(error.status).json(toJsonResponse(error.status, error.message));
        }
    }


    /**
     * Handles the update of an existing plan.
     * @param createPlanDto - The data transfer object containing the updated details of the plan.
     * @param planIdParamDto - The parameter object containing the ID of the plan to be updated.
     * @param req - The request object, containing the authenticated user information.
     * @param response - The response object for sending the HTTP response.
     * @returns A success response with status 201 if the plan is updated successfully.
     * @throws An error response with the corresponding status and message if the update fails.
     */
    @ApiBearerAuth('access-token')
    @ApiBody({ type: CreatePlanDto })
    @UseGuards(AdminGuard)
    @Put(':id')
    async updatePlan(@Body() createPlanDto: CreatePlanDto, @Param() planIdParamDto: PlanIdParamDto, @Req() req, @Res() response) {
        try {
            console.log('dd')
            await this.planService.updatePlan(planIdParamDto, createPlanDto, req.user);
            return response.status(201).json();
        } catch (error) {
            console.log(error)
            response.status(error.status).json(toJsonResponse(error.status, error.message));
        }
    }
    /**
      * Toggles the status of a plan based on the provided plan ID.
      * @param planIdParamDto - An object containing the ID of the plan whose status is to be changed.
      * @param req - The request object, containing the authenticated user information.
      * @param response - The response object for sending the HTTP response.
      * @returns A success response with status 201 if the plan status is updated successfully.
      * @throws An error response with the corresponding status and message if the status update fails.
      */
    @ApiBearerAuth('access-token')
    @UseGuards(AdminGuard)
    @Patch('change-status/:id')
    async chageStatus(@Param() planIdParamDto: PlanIdParamDto, @Req() req, @Res() response) {
        try {
            await this.planService.chageStatus(planIdParamDto, req.user);
            return response.status(201).json();
        } catch (error) {
            response.status(error.status).json(toJsonResponse(error.status, error.message));
        }
    }

    // GET PERMISSIONS
    @ApiBearerAuth('access-token')
    @UseGuards(AdminGuard)
    @Get('permissions')
    async permissions(@Req() req, @Res() response) {
        try {
            const data = await this.planService.permissions(req.user);
            return response.status(200).json(data);

        } catch (error) {
            response.status(error.status).json(toJsonResponse(error.status, error.message));
        }
    }


    @ApiBearerAuth('access-token')
    @UseGuards(CommonGuard)
    @Get(":slug")
    async details(@Param() slug: PlanSlugParamDto, @Req() req, @Res() response) {
        try {
            const data = await this.planService.details(slug);
            return response.status(200).json(data);
        } catch (error) {
            console.log(error)
            response.status(error.status).json(toJsonResponse(error.status, error.message));
        }
    }
}
