// SIM Management Controller Endpoints
// These endpoints should be added to your subscriptions controller
// Location: apps/bff/src/modules/subscriptions/subscriptions.controller.ts

import {
  Controller,
  Get,
  Post,
  Body,
  Param,
  Query,
  Request,
  ParseIntPipe,
  BadRequestException,
} from "@nestjs/common";
import { ApiTags, ApiOperation, ApiParam, ApiQuery, ApiBody, ApiResponse, ApiBearerAuth } from "@nestjs/swagger";
import { ZodValidationPipe } from "@bff/core/validation";
import type { RequestWithUser } from "@bff/modules/auth/auth.types";
import { SimManagementService } from "../sim-management.service";
import {
  simTopupRequestSchema,
  simChangePlanRequestSchema,
  simCancelRequestSchema,
  simFeaturesRequestSchema,
  type SimTopupRequest,
  type SimChangePlanRequest,
  type SimCancelRequest,
  type SimFeaturesRequest,
} from "../sim-management/types/sim-requests.types";

// ==================== SIM Management Endpoints ====================
// Add these methods to your SubscriptionsController class

@ApiTags("subscriptions")
@Controller("subscriptions")
@ApiBearerAuth()
export class SimEndpointsController {
  constructor(private readonly simManagementService: SimManagementService) {}

  @Get(":id/sim/debug")
  @ApiOperation({
    summary: "Debug SIM subscription data",
    description: "Retrieves subscription data to help debug SIM management issues",
  })
  @ApiParam({ name: "id", type: Number, description: "Subscription ID" })
  @ApiResponse({ status: 200, description: "Subscription debug data" })
  async debugSimSubscription(
    @Request() req: RequestWithUser,
    @Param("id", ParseIntPipe) subscriptionId: number
  ): Promise<Record<string, unknown>> {
    return this.simManagementService.debugSimSubscription(req.user.id, subscriptionId);
  }

  @Get(":id/sim")
  @ApiOperation({
    summary: "Get SIM details and usage",
    description: "Retrieves comprehensive SIM information including details and current usage",
  })
  @ApiParam({ name: "id", type: Number, description: "Subscription ID" })
  @ApiResponse({ status: 200, description: "SIM information" })
  @ApiResponse({ status: 400, description: "Not a SIM subscription" })
  @ApiResponse({ status: 404, description: "Subscription not found" })
  async getSimInfo(
    @Request() req: RequestWithUser,
    @Param("id", ParseIntPipe) subscriptionId: number
  ) {
    return this.simManagementService.getSimInfo(req.user.id, subscriptionId);
  }

  @Get(":id/sim/info")
  @ApiOperation({
    summary: "Get SIM information (alias for /sim)",
    description: "Retrieves comprehensive SIM information including details and current usage",
  })
  @ApiParam({ name: "id", type: Number, description: "Subscription ID" })
  @ApiResponse({ status: 200, description: "SIM information" })
  @ApiResponse({ status: 400, description: "Not a SIM subscription" })
  @ApiResponse({ status: 404, description: "Subscription not found" })
  async getSimInfoAlias(
    @Request() req: RequestWithUser,
    @Param("id", ParseIntPipe) subscriptionId: number
  ) {
    return this.simManagementService.getSimInfo(req.user.id, subscriptionId);
  }

  @Get(":id/sim/details")
  @ApiOperation({
    summary: "Get SIM details",
    description: "Retrieves detailed SIM information including ICCID, plan, status, etc.",
  })
  @ApiParam({ name: "id", type: Number, description: "Subscription ID" })
  @ApiResponse({ status: 200, description: "SIM details" })
  async getSimDetails(
    @Request() req: RequestWithUser,
    @Param("id", ParseIntPipe) subscriptionId: number
  ) {
    return this.simManagementService.getSimDetails(req.user.id, subscriptionId);
  }

  @Get(":id/sim/usage")
  @ApiOperation({
    summary: "Get SIM data usage",
    description: "Retrieves current data usage and recent usage history",
  })
  @ApiParam({ name: "id", type: Number, description: "Subscription ID" })
  @ApiResponse({ status: 200, description: "SIM usage data" })
  async getSimUsage(
    @Request() req: RequestWithUser,
    @Param("id", ParseIntPipe) subscriptionId: number
  ) {
    return this.simManagementService.getSimUsage(req.user.id, subscriptionId);
  }

  @Get(":id/sim/top-up-history")
  @ApiOperation({
    summary: "Get SIM top-up history",
    description: "Retrieves data top-up history for the specified date range",
  })
  @ApiParam({ name: "id", type: Number, description: "Subscription ID" })
  @ApiQuery({ name: "fromDate", description: "Start date (YYYYMMDD)", example: "20240101" })
  @ApiQuery({ name: "toDate", description: "End date (YYYYMMDD)", example: "20241231" })
  @ApiResponse({ status: 200, description: "Top-up history" })
  async getSimTopUpHistory(
    @Request() req: RequestWithUser,
    @Param("id", ParseIntPipe) subscriptionId: number,
    @Query("fromDate") fromDate: string,
    @Query("toDate") toDate: string
  ) {
    if (!fromDate || !toDate) {
      throw new BadRequestException("fromDate and toDate are required");
    }

    return this.simManagementService.getSimTopUpHistory(req.user.id, subscriptionId, {
      fromDate,
      toDate,
    });
  }

  @Post(":id/sim/top-up")
  @ApiOperation({
    summary: "Top up SIM data quota",
    description: "Add data quota to the SIM service",
  })
  @ApiParam({ name: "id", type: Number, description: "Subscription ID" })
  @ApiBody({
    description: "Top-up request",
    schema: {
      type: "object",
      properties: {
        quotaMb: { type: "number", description: "Quota in MB", example: 1000 },
        amount: {
          type: "number",
          description: "Amount to charge in JPY (optional, defaults to calculated amount)",
          example: 500,
        },
        currency: {
          type: "string",
          description: "ISO currency code (optional, defaults to JPY)",
          example: "JPY",
        },
      },
      required: ["quotaMb"],
    },
  })
  @ApiResponse({ status: 200, description: "Top-up successful" })
  async topUpSim(
    @Request() req: RequestWithUser,
    @Param("id", ParseIntPipe) subscriptionId: number,
    @Body(new ZodValidationPipe(simTopupRequestSchema)) body: SimTopupRequest
  ) {
    await this.simManagementService.topUpSim(req.user.id, subscriptionId, body);
    return { success: true, message: "SIM top-up completed successfully" };
  }

  @Post(":id/sim/change-plan")
  @ApiOperation({
    summary: "Change SIM plan",
    description:
      "Change the SIM service plan. The change will be automatically scheduled for the 1st of the next month. Available plans: 5GB, 10GB, 25GB, 50GB.",
  })
  @ApiParam({ name: "id", type: Number, description: "Subscription ID" })
  @ApiBody({
    description: "Plan change request",
    schema: {
      type: "object",
      properties: {
        newPlanCode: { 
          type: "string", 
          description: "New plan code", 
          enum: ["5GB", "10GB", "25GB", "50GB"],
          example: "25GB" 
        },
      },
      required: ["newPlanCode"],
    },
  })
  @ApiResponse({ status: 200, description: "Plan change successful" })
  async changeSimPlan(
    @Request() req: RequestWithUser,
    @Param("id", ParseIntPipe) subscriptionId: number,
    @Body(new ZodValidationPipe(simChangePlanRequestSchema)) body: SimChangePlanRequest
  ) {
    const result = await this.simManagementService.changeSimPlan(req.user.id, subscriptionId, body);
    return {
      success: true,
      message: "SIM plan change completed successfully",
      ...result,
    };
  }

  @Post(":id/sim/cancel")
  @ApiOperation({
    summary: "Cancel SIM service",
    description: "Cancel the SIM service (immediate or scheduled)",
  })
  @ApiParam({ name: "id", type: Number, description: "Subscription ID" })
  @ApiBody({
    description: "Cancellation request",
    schema: {
      type: "object",
      properties: {
        scheduledAt: {
          type: "string",
          description: "Schedule cancellation (YYYYMMDD)",
          example: "20241231",
        },
      },
    },
    required: false,
  })
  @ApiResponse({ status: 200, description: "Cancellation successful" })
  async cancelSim(
    @Request() req: RequestWithUser,
    @Param("id", ParseIntPipe) subscriptionId: number,
    @Body(new ZodValidationPipe(simCancelRequestSchema)) body: SimCancelRequest
  ) {
    await this.simManagementService.cancelSim(req.user.id, subscriptionId, body);
    return { success: true, message: "SIM cancellation completed successfully" };
  }

  @Post(":id/sim/reissue-esim")
  @ApiOperation({
    summary: "Reissue eSIM profile",
    description:
      "Reissue a downloadable eSIM profile (eSIM only). Optionally provide a new EID to transfer to.",
  })
  @ApiParam({ name: "id", type: Number, description: "Subscription ID" })
  @ApiBody({
    description: "Optional new EID to transfer the eSIM to",
    schema: {
      type: "object",
      properties: {
        newEid: {
          type: "string",
          description: "32-digit EID",
          example: "89049032000001000000043598005455",
        },
      },
      required: [],
    },
  })
  @ApiResponse({ status: 200, description: "eSIM reissue successful" })
  @ApiResponse({ status: 400, description: "Not an eSIM subscription" })
  async reissueEsimProfile(
    @Request() req: RequestWithUser,
    @Param("id", ParseIntPipe) subscriptionId: number,
    @Body() body: { newEid?: string } = {}
  ) {
    await this.simManagementService.reissueEsimProfile(req.user.id, subscriptionId, body.newEid);
    return { success: true, message: "eSIM profile reissue completed successfully" };
  }

  @Post(":id/sim/features")
  @ApiOperation({
    summary: "Update SIM features",
    description:
      "Enable/disable voicemail, call waiting, international roaming, and switch network type (4G/5G)",
  })
  @ApiParam({ name: "id", type: Number, description: "Subscription ID" })
  @ApiBody({
    description: "Features update request",
    schema: {
      type: "object",
      properties: {
        voiceMailEnabled: { type: "boolean" },
        callWaitingEnabled: { type: "boolean" },
        internationalRoamingEnabled: { type: "boolean" },
        networkType: { type: "string", enum: ["4G", "5G"] },
      },
    },
  })
  @ApiResponse({ status: 200, description: "Features update successful" })
  async updateSimFeatures(
    @Request() req: RequestWithUser,
    @Param("id", ParseIntPipe) subscriptionId: number,
    @Body(new ZodValidationPipe(simFeaturesRequestSchema)) body: SimFeaturesRequest
  ) {
    await this.simManagementService.updateSimFeatures(req.user.id, subscriptionId, body);
    return { success: true, message: "SIM features updated successfully" };
  }

  @Get("debug/sim-details/:account")
  // @Public() // Uncomment if you have a Public decorator for debug endpoints
  @ApiOperation({
    summary: "[DEBUG] Get SIM details from Freebit",
    description: "Query Freebit API directly to see plan code and details for any account",
  })
  @ApiParam({ name: "account", description: "SIM account number (e.g., 02000215161147)" })
  async debugSimDetails(@Param("account") account: string) {
    return await this.simManagementService.getSimDetailsDebug(account);
  }
}

