import {
  Body,
  Controller,
  HttpStatus,
  Post,
  Get,
  Req,
  UseGuards,
} from '@nestjs/common';
import {
  ApiOperation,
  ApiResponse,
  ApiTags,
  ApiBearerAuth,
} from '@nestjs/swagger';
import { ErrorResponse } from '../../common/error/types/types';
import { Request } from 'express';
import { AccountsService } from './accounts.service';
import {
  CreateAccountRequest,
  CreateAccountResponse,
  GetLicenseSummaryRequest,
  GetLicenseSummaryResponse,
  GetMyAccountResponse,
  GetTypistGroupsResponse,
  GetTypistsResponse,
  CreatePartnerAccountRequest,
  CreatePartnerAccountResponse,
  GetPartnerLicensesRequest,
  GetPartnerLicensesResponse,
  GetOrderHistoriesRequest,
  GetOrderHistoriesResponce,
  LicenseOrder,
} from './types/types';
import { USER_ROLES, ADMIN_ROLES, TIERS } from '../../constants';
import { AuthGuard } from '../../common/guards/auth/authguards';
import { RoleGuard } from '../../common/guards/role/roleguards';
import { retrieveAuthorizationToken } from '../../common/http/helper';
import { AccessToken } from '../../common/token';
import jwt from 'jsonwebtoken';

@ApiTags('accounts')
@Controller('accounts')
export class AccountsController {
  constructor(
    private readonly accountService: AccountsService, //private readonly cryptoService: CryptoService,
  ) {}

  @Post()
  @ApiResponse({
    status: HttpStatus.OK,
    type: CreateAccountResponse,
    description: '成功時のレスポンス',
  })
  @ApiResponse({
    status: HttpStatus.BAD_REQUEST,
    description: '登録済みユーザーからの登録など',
    type: ErrorResponse,
  })
  @ApiResponse({
    status: HttpStatus.INTERNAL_SERVER_ERROR,
    description: '想定外のサーバーエラー',
    type: ErrorResponse,
  })
  @ApiOperation({ operationId: 'createAccount' })
  async createAccount(
    @Body() body: CreateAccountRequest,
  ): Promise<CreateAccountResponse> {
    const {
      companyName,
      country,
      dealerAccountId,
      adminMail,
      adminPassword,
      adminName,
      acceptedTermsVersion,
    } = body;
    const role = USER_ROLES.NONE;

    await this.accountService.createAccount(
      companyName,
      country,
      dealerAccountId,
      adminMail,
      adminPassword,
      adminName,
      role,
      acceptedTermsVersion,
    );

    return {};
  }

  @ApiResponse({
    status: HttpStatus.OK,
    type: GetLicenseSummaryResponse,
    description: '成功時のレスポンス',
  })
  @ApiResponse({
    status: HttpStatus.UNAUTHORIZED,
    description: '認証エラー',
    type: ErrorResponse,
  })
  @ApiResponse({
    status: HttpStatus.INTERNAL_SERVER_ERROR,
    description: '想定外のサーバーエラー',
    type: ErrorResponse,
  })
  @ApiOperation({
    operationId: 'getLicenseSummary',
    description: '指定したアカウントのライセンス集計情報を取得します',
  })
  @ApiBearerAuth()
  @UseGuards(AuthGuard)
  @UseGuards(
    RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN], tiers: [TIERS.TIER5] }),
  )
  @Post('licenses/summary')
  async getLicenseSummary(
    @Req() req: Request,
    @Body() body: GetLicenseSummaryRequest,
  ): Promise<GetLicenseSummaryResponse> {
    console.log(req.header('Authorization'));
    console.log(body);

    const response = await this.accountService.getLicenseSummary(
      body.accountId,
    );
    return response;
  }

  @ApiResponse({
    status: HttpStatus.OK,
    type: GetMyAccountResponse,
    description: '成功時のレスポンス',
  })
  @ApiResponse({
    status: HttpStatus.BAD_REQUEST,
    description: '該当アカウントがDBに存在しない場合',
    type: ErrorResponse,
  })
  @ApiResponse({
    status: HttpStatus.UNAUTHORIZED,
    description: '認証エラー',
    type: ErrorResponse,
  })
  @ApiResponse({
    status: HttpStatus.INTERNAL_SERVER_ERROR,
    description: '想定外のサーバーエラー',
    type: ErrorResponse,
  })
  @ApiOperation({
    operationId: 'getMyAccount',
    description: 'ログインしているユーザーのアカウント情報を取得します',
  })
  @ApiBearerAuth()
  @UseGuards(AuthGuard)
  @UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
  @Get('me')
  async getMyAccount(@Req() req: Request): Promise<GetMyAccountResponse> {
    console.log(req.header('Authorization'));

    // アクセストークン取得
    const accessToken = retrieveAuthorizationToken(req);
    const payload = jwt.decode(accessToken, { json: true }) as AccessToken;
    //アカウントID取得処理
    const accountId = await this.accountService.getMyAccountInfo(payload);
    return {
      account: {
        accountId: accountId,
      },
    };
  }

  @ApiResponse({
    status: HttpStatus.OK,
    type: GetTypistsResponse,
    description: '成功時のレスポンス',
  })
  @ApiResponse({
    status: HttpStatus.UNAUTHORIZED,
    description: '認証エラー',
    type: ErrorResponse,
  })
  @ApiResponse({
    status: HttpStatus.INTERNAL_SERVER_ERROR,
    description: '想定外のサーバーエラー',
    type: ErrorResponse,
  })
  @ApiOperation({
    operationId: 'getTypists',
    description:
      'ログインしているユーザーのアカウント配下のタイピスト一覧を取得します',
  })
  @ApiBearerAuth()
  @UseGuards(AuthGuard)
  @Get('typists')
  async getTypists(@Req() req: Request): Promise<GetTypistsResponse> {
    console.log(req.header('Authorization'));
    // アクセストークン取得
    const accessToken = retrieveAuthorizationToken(req);
    const payload = jwt.decode(accessToken, { json: true }) as AccessToken;

    const typists = await this.accountService.getTypists(payload.userId);

    return { typists };
  }

  @ApiResponse({
    status: HttpStatus.OK,
    type: GetTypistGroupsResponse,
    description: '成功時のレスポンス',
  })
  @ApiResponse({
    status: HttpStatus.UNAUTHORIZED,
    description: '認証エラー',
    type: ErrorResponse,
  })
  @ApiResponse({
    status: HttpStatus.INTERNAL_SERVER_ERROR,
    description: '想定外のサーバーエラー',
    type: ErrorResponse,
  })
  @ApiOperation({
    operationId: 'getTypistGroups',
    description:
      'ログインしているユーザーのアカウント配下のタイピストグループ一覧を取得します',
  })
  @ApiBearerAuth()
  @UseGuards(AuthGuard)
  @Get('typist-groups')
  async getTypistGroups(@Req() req: Request): Promise<GetTypistGroupsResponse> {
    console.log(req.header('Authorization'));
    // アクセストークン取得
    const accessToken = retrieveAuthorizationToken(req);
    const payload = jwt.decode(accessToken, { json: true }) as AccessToken;

    const typistGroups = await this.accountService.getTypistGroups(
      payload.userId,
    );

    return { typistGroups };
  }

  @Post('partner')
  @ApiResponse({
    status: HttpStatus.OK,
    type: CreatePartnerAccountResponse,
    description: '成功時のレスポンス',
  })
  @ApiResponse({
    status: HttpStatus.UNAUTHORIZED,
    description: '認証エラー',
    type: ErrorResponse,
  })
  @ApiResponse({
    status: HttpStatus.BAD_REQUEST,
    description: '登録済みユーザーからの登録など',
    type: ErrorResponse,
  })
  @ApiResponse({
    status: HttpStatus.INTERNAL_SERVER_ERROR,
    description: '想定外のサーバーエラー',
    type: ErrorResponse,
  })
  @ApiOperation({ operationId: 'createPartnerAccount' })
  @ApiBearerAuth()
  @UseGuards(AuthGuard)
  @UseGuards(
    RoleGuard.requireds({
      roles: [ADMIN_ROLES.ADMIN],
      tiers: [TIERS.TIER1, TIERS.TIER2, TIERS.TIER3],
    }),
  )
  async createPartnerAccount(
    @Req() req: Request,
    @Body() body: CreatePartnerAccountRequest,
  ): Promise<CreatePartnerAccountResponse> {
    const { companyName, country, email, adminName } = body;
    const accessToken = retrieveAuthorizationToken(req);
    const payload = jwt.decode(accessToken, { json: true }) as AccessToken;

    await this.accountService.createPartnerAccount(
      companyName,
      country,
      email,
      adminName,
      payload.userId,
      payload.tier,
    );

    return {};
  }

  @Post('partner-licenses')
  @ApiResponse({
    status: HttpStatus.OK,
    type: GetPartnerLicensesResponse,
    description: '成功時のレスポンス',
  })
  @ApiResponse({
    status: HttpStatus.UNAUTHORIZED,
    description: '認証エラー',
    type: ErrorResponse,
  })
  @ApiResponse({
    status: HttpStatus.INTERNAL_SERVER_ERROR,
    description: '想定外のサーバーエラー',
    type: ErrorResponse,
  })
  @ApiOperation({ operationId: 'getPartnerLicenses' })
  @ApiBearerAuth()
  @UseGuards(AuthGuard)
  @UseGuards(
    RoleGuard.requireds({
      roles: [ADMIN_ROLES.ADMIN],
      tiers: [TIERS.TIER1, TIERS.TIER2, TIERS.TIER3, TIERS.TIER4],
    }),
  )
  async getPartnerLicenses(
    @Req() req: Request,
    @Body() body: GetPartnerLicensesRequest,
  ): Promise<GetPartnerLicensesResponse> {
    const { limit, offset, accountId } = body;

    const getPartnerLicensesResponse =
      await this.accountService.getPartnerLicenses(limit, offset, accountId);

    return getPartnerLicensesResponse;
  }

  @Post('order-histories')
  @ApiResponse({
    status: HttpStatus.OK,
    type: GetOrderHistoriesResponce,
    description: '成功時のレスポンス',
  })
  @ApiResponse({
    status: HttpStatus.UNAUTHORIZED,
    description: '認証エラー',
    type: ErrorResponse,
  })
  @ApiResponse({
    status: HttpStatus.INTERNAL_SERVER_ERROR,
    description: '想定外のサーバーエラー',
    type: ErrorResponse,
  })
  @ApiOperation({ operationId: 'getOrderHistories' })
  @ApiBearerAuth()
  @UseGuards(AuthGuard)
  @UseGuards(
    RoleGuard.requireds({
      roles: [ADMIN_ROLES.ADMIN],
    }),
  )
  async getOrderHistories(
    @Req() req: Request,
    @Body() body: GetOrderHistoriesRequest,
  ): Promise<GetOrderHistoriesResponce> {
    const { limit, offset, accountId } = body;

    const getOrderHistoriesResponce =
      await this.accountService.getOrderHistories(limit, offset, accountId);

    return getOrderHistoriesResponce;
  }
}
