import {
  Controller,
  Get,
  Post,
  Put,
  Patch,
  Delete,
  Body,
  Param,
  Query,
  Res,
  UseGuards,
  Request,
} from '@nestjs/common';
import { ApiTags, ApiBody, ApiParam, ApiQuery, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
import { PaymentMethodService } from './payment-method.service';
import { toJsonResponse } from '../../common/response';
import { AdminGuard } from '../auth/guards/admin.guard';
import { CommonGuard } from '../auth/guards/common.guard';
import { PaymentMethodCreateDto } from './dtos/payment-method-create.dto';
import { PaymentMethodUpdateDto } from './dtos/payment-method-update.dto';
import { PaymentMethodIdParamDto } from './dtos/payment-method-id-param.dto';
import { PaymentMethodListQueryDto } from './dtos/payment-method-list-query.dto';
import { AssignPaymentMethodDto } from './dtos/assign-payment-method.dto';
import { CountryPaymentMethodListQueryDto } from './dtos/country-payment-method-list-query.dto';
import { CountryIdParamDto } from './dtos/country-id-param.dto';
import { InfluencerPaymentMethodCreateDto } from './dtos/influencer-payment-method-create.dto';

@ApiTags('payment-method')
@Controller('payment-method')
export class PaymentMethodController {
  constructor(private readonly paymentMethodService: PaymentMethodService) { }

  @ApiBody({ type: PaymentMethodCreateDto })
  @UseGuards(AdminGuard)
  @Post()
  async create(@Body() request: PaymentMethodCreateDto, @Res() response: any) {
    try {
      const data = await this.paymentMethodService.create(request);
      response.status(201).json(data);
    } catch (error) {
      console.log(error);
      response.status(error.status || 500).json(toJsonResponse(error.status || 500, error.message));
    }
  }

  @ApiQuery({ name: 'page', required: false, example: 1 })
  @ApiQuery({ name: 'per_page', required: false, example: 50 })
  @ApiQuery({ name: 'sort_by', required: false })
  @ApiQuery({ name: 'sort', required: false })
  @ApiQuery({ name: 'search', required: false })
  @ApiQuery({ name: 'is_active', required: false, type: Boolean })
  @UseGuards(CommonGuard)
  @Get()
  async list(@Query() queryParam: PaymentMethodListQueryDto, @Res() response: any) {
    try {
      const data = await this.paymentMethodService.list(queryParam);
      response.status(200).json(data);
    } catch (error) {
      console.log(error);
      response.status(error.status || 500).json(toJsonResponse(error.status || 500, error.message));
    }
  }

  @ApiParam({ name: 'payment_method_id', required: true })
  @UseGuards(AdminGuard)
  @Patch('change-status/:payment_method_id')
  async changeStatus(@Param() params: PaymentMethodIdParamDto, @Res() response: any) {
    try {
      const data = await this.paymentMethodService.changeStatus(params);
      response.status(200).json(data);
    } catch (error) {
      console.log(error);
      response.status(error.status || 500).json(toJsonResponse(error.status || 500, error.message));
    }
  }

  @ApiBody({ type: AssignPaymentMethodDto })
  @UseGuards(AdminGuard)
  @Post('assigned-countries')
  async assignPaymentMethods(@Body() request: AssignPaymentMethodDto, @Res() response: any) {
    try {
      const data = await this.paymentMethodService.assignPaymentMethods(request);
      response.status(201).json(data);
    } catch (error) {
      console.log(error);
      response.status(error.status || 500).json(toJsonResponse(error.status || 500, error.message));
    }
  }

  @ApiQuery({ name: 'page', required: false, example: 1 })
  @ApiQuery({ name: 'per_page', required: false, example: 50 })
  @ApiQuery({ name: 'sort_by', required: false })
  @ApiQuery({ name: 'sort', required: false })
  @ApiQuery({ name: 'search', required: false })
  @UseGuards(CommonGuard)
  @Get('assigned-countries')
  async listCountriesWithPaymentMethods(@Query() queryParam: CountryPaymentMethodListQueryDto, @Res() response: any) {
    try {
      const data = await this.paymentMethodService.listCountriesWithPaymentMethods(queryParam);
      response.status(200).json(data);
    } catch (error) {
      console.log(error);
      response.status(error.status || 500).json(toJsonResponse(error.status || 500, error.message));
    }
  }

  @ApiParam({ name: 'country_id', required: true })
  @UseGuards(CommonGuard)
  @Get('assigned-countries/:country_id')
  async getCountryDetails(@Param() params: CountryIdParamDto, @Res() response: any) {
    try {
      const data = await this.paymentMethodService.getCountryDetails(params);
      response.status(200).json(data);
    } catch (error) {
      console.log(error);
      response.status(error.status || 500).json(toJsonResponse(error.status || 500, error.message));
    }
  }



  @ApiParam({ name: 'payment_method_id', required: true })
  @ApiBody({ type: PaymentMethodUpdateDto })
  @UseGuards(AdminGuard)
  @Put(':payment_method_id')
  async update(
    @Param() params: PaymentMethodIdParamDto,
    @Body() request: PaymentMethodUpdateDto,
    @Res() response: any,
  ) {
    try {
      const data = await this.paymentMethodService.update(params, request);
      response.status(200).json(data);
    } catch (error) {
      console.log(error);
      response.status(error.status || 500).json(toJsonResponse(error.status || 500, error.message));
    }
  }

  @ApiParam({ name: 'payment_method_id', required: true })
  @UseGuards(AdminGuard)
  @Delete(':payment_method_id')
  async delete(@Param() params: PaymentMethodIdParamDto, @Res() response: any) {
    try {
      await this.paymentMethodService.delete(params);
      response.status(204).json();
    } catch (error) {
      console.log(error);
      response.status(error.status || 500).json(toJsonResponse(error.status || 500, error.message));
    }
  }

  @ApiBearerAuth('access-token')
  @ApiOperation({ summary: 'Get payment methods for influencer based on their country' })
  @UseGuards(CommonGuard)
  @Get('influencer')
  async getInfluencerPaymentMethods(@Query() queryParam: any, @Request() req: any, @Res() response: any) {
    try {
      const data = await this.paymentMethodService.getPaymentMethodsByInfluencerCountry(queryParam, req.user);
      response.status(200).json(data);
    } catch (error) {
      console.log(error);
      response.status(error.status || 500).json(toJsonResponse(error.status || 500, error.message));
    }
  }

  @ApiBearerAuth('access-token')
  @ApiBody({ type: InfluencerPaymentMethodCreateDto })
  @ApiOperation({ summary: 'Store payment method for influencer with JSON data' })
  @UseGuards(CommonGuard)
  @Post('influencer')
  async createInfluencerPaymentMethod(@Request() req: any, @Body() request: InfluencerPaymentMethodCreateDto, @Res() response: any) {
    try {
      const data = await this.paymentMethodService.createInfluencerPaymentMethod(req.user, request);
      response.status(201).json(data);
    } catch (error) {
      console.log(error);
      response.status(error.status || 500).json(toJsonResponse(error.status || 500, error.message));
    }
  }


  @Get('script')
  async script(@Res() response: any) {
    try {
      const data = await this.paymentMethodService.script();
      response.status(200).json(data);
    } catch (error) {
      console.log(error);
      response.status(error.status || 500).json(toJsonResponse(error.status || 500, error.message));
    }
  }

  @ApiParam({ name: 'payment_method_id', required: true })
  @UseGuards(CommonGuard)
  @Get(':payment_method_id')
  async getById(@Param() params: PaymentMethodIdParamDto, @Res() response: any) {
    try {
      const data = await this.paymentMethodService.getById(params);
      response.status(200).json(data);
    } catch (error) {
      console.log(error);
      response.status(error.status || 500).json(toJsonResponse(error.status || 500, error.message));
    }
  }


}
