import {
  Body,
  Controller,
  HttpStatus,
  Post,
  Req,
  UseGuards,
} from '@nestjs/common';
import {
  ApiResponse,
  ApiTags,
  ApiOperation,
  ApiBearerAuth,
} from '@nestjs/swagger';
import { ErrorResponse } from '../../common/error/types/types';
import { LicensesService } from './licenses.service';
import {
  CreateOrdersResponse,
  CreateOrdersRequest,
  IssueCardLicensesResponse,
  IssueCardLicensesRequest,
  ActivateCardLicensesResponse,
  ActivateCardLicensesRequest,
} from './types/types';
import { Request } from 'express';
import { retrieveAuthorizationToken } from '../../common/http/helper';
import { AccessToken } from '../../common/token';
import { AuthGuard } from '../../common/guards/auth/authguards';
import { RoleGuard } from '../../common/guards/role/roleguards';
import { ADMIN_ROLES, TIERS } from '../../constants';
import jwt from 'jsonwebtoken';

@ApiTags('licenses')
@Controller('licenses')
export class LicensesController {
  constructor(private readonly licensesService: LicensesService) {}
  @ApiResponse({
    status: HttpStatus.OK,
    type: CreateOrdersResponse,
    description: '成功時のレスポンス',
  })
  @ApiResponse({
    status: HttpStatus.BAD_REQUEST,
    description: '同一PONumberの注文がすでに存在する場合など',
    type: ErrorResponse,
  })
  @ApiResponse({
    status: HttpStatus.UNAUTHORIZED,
    description: '認証エラー',
    type: ErrorResponse,
  })
  @ApiResponse({
    status: HttpStatus.INTERNAL_SERVER_ERROR,
    description: '想定外のサーバーエラー',
    type: ErrorResponse,
  })
  @ApiOperation({ operationId: 'createOrders' })
  @ApiBearerAuth()
  @UseGuards(AuthGuard)
  @UseGuards(
    RoleGuard.requireds({
      roles: [ADMIN_ROLES.ADMIN],
      tiers: [TIERS.TIER2, TIERS.TIER3, TIERS.TIER4, TIERS.TIER5],
    }),
  )
  @Post('/orders')
  async createOrders(
    @Req() req: Request,
    @Body() body: CreateOrdersRequest,
  ): Promise<CreateOrdersResponse> {
    console.log(req.header('Authorization'));
    console.log(body);

    // AuthGuardでチェック済みなのでここでのアクセストークンチェックはしない
    const accessToken = retrieveAuthorizationToken(req);
    const payload = jwt.decode(accessToken, { json: true }) as AccessToken;

    // ライセンス注文処理
    await this.licensesService.licenseOrders(
      payload,
      body.poNumber,
      body.orderCount,
    );
    return {};
  }

  @ApiResponse({
    status: HttpStatus.OK,
    type: IssueCardLicensesResponse,
    description: '成功時のレスポンス',
  })
  @ApiResponse({
    status: HttpStatus.UNAUTHORIZED,
    description: '認証エラー',
    type: ErrorResponse,
  })
  @ApiResponse({
    status: HttpStatus.INTERNAL_SERVER_ERROR,
    description: '想定外のサーバーエラー',
    type: ErrorResponse,
  })
  @ApiOperation({ operationId: 'issueCardLicenses' })
  @ApiBearerAuth()
  @UseGuards(AuthGuard)
  @UseGuards(
    RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN], tiers: [TIERS.TIER1] }),
  )
  @Post('/cards')
  async issueCardLicenses(
    @Req() req: Request,
    @Body() body: IssueCardLicensesRequest,
  ): Promise<IssueCardLicensesResponse> {
    console.log(req.header('Authorization'));
    console.log(body);

    const accessToken = retrieveAuthorizationToken(req);
    const payload = jwt.decode(accessToken, { json: true }) as AccessToken;

    const cardLicenseKeys = await this.licensesService.issueCardLicenseKeys(
      payload.userId,
      body.createCount,
    );

    return cardLicenseKeys;
  }

  @ApiResponse({
    status: HttpStatus.OK,
    type: ActivateCardLicensesResponse,
    description: '成功時のレスポンス',
  })
  @ApiResponse({
    status: HttpStatus.BAD_REQUEST,
    description:
      'パラメータのライセンスキーが不正な内容の場合/存在しない場合/登録済みの場合',
    type: ErrorResponse,
  })
  @ApiResponse({
    status: HttpStatus.UNAUTHORIZED,
    description: '認証エラー',
    type: ErrorResponse,
  })
  @ApiResponse({
    status: HttpStatus.INTERNAL_SERVER_ERROR,
    description: '想定外のサーバーエラー',
    type: ErrorResponse,
  })
  @ApiOperation({ operationId: 'activateCardLicenses' })
  @ApiBearerAuth()
  @UseGuards(AuthGuard)
  @UseGuards(
    RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN], tiers: [TIERS.TIER5] }),
  )
  @Post('/cards/activate')
  async activateCardLicenses(
    @Req() req: Request,
    @Body() body: ActivateCardLicensesRequest,
  ): Promise<ActivateCardLicensesResponse> {
    console.log(req.header('Authorization'));
    console.log(body);

    const accessToken = retrieveAuthorizationToken(req);
    const payload = jwt.decode(accessToken, { json: true }) as AccessToken;

    await this.licensesService.activateCardLicenseKey(
      payload.userId,
      body.cardLicenseKey,
    );

    return {};
  }
}
