/**
 * Address Controller
 *
 * HTTP endpoints for address lookup and management.
 */

import {
  Controller,
  Get,
  Param,
  Req,
  UseGuards,
  UseInterceptors,
  ClassSerializerInterceptor,
} from "@nestjs/common";
import type { Request } from "express";
import { createZodDto } from "nestjs-zod";
import { Public } from "@bff/modules/auth/decorators/public.decorator.js";
import { RateLimitGuard, RateLimit } from "@bff/core/rate-limiting/index.js";
import { extractClientIp } from "@bff/core/http/request-context.util.js";
import { JapanPostFacade } from "@bff/integrations/japanpost/index.js";
import {
  addressLookupResultSchema,
  zipCodeLookupRequestSchema,
} from "@customer-portal/domain/address";

// ============================================================================
// DTOs
// ============================================================================

/**
 * ZIP code parameter DTO
 * Validates ZIP code format (with or without hyphen)
 */
class ZipCodeParamDto extends createZodDto(zipCodeLookupRequestSchema) {}

/**
 * Address lookup result DTO
 */
class AddressLookupResultDto extends createZodDto(addressLookupResultSchema) {}

// ============================================================================
// Controller
// ============================================================================

@Controller("address")
@UseInterceptors(ClassSerializerInterceptor)
export class AddressController {
  constructor(private readonly japanPost: JapanPostFacade) {}

  /**
   * Lookup address by ZIP code
   *
   * @route GET /api/address/lookup/zip/:zipCode
   * @param zipCode - Japanese ZIP code (e.g., "100-0001" or "1000001")
   * @returns Address lookup result with Japanese and romanized address data
   *
   * @example
   * GET /api/address/lookup/zip/100-0001
   * Response:
   * {
   *   "zipCode": "1000001",
   *   "addresses": [
   *     {
   *       "zipCode": "1000001",
   *       "prefecture": "東京都",
   *       "city": "千代田区",
   *       "town": "千代田",
   *       "prefectureRoma": "Tokyo",
   *       "cityRoma": "Chiyoda-ku",
   *       "townRoma": "Chiyoda"
   *     }
   *   ],
   *   "count": 1
   * }
   */
  @Public()
  @Get("lookup/zip/:zipCode")
  @UseGuards(RateLimitGuard)
  @RateLimit({ limit: 30, ttl: 60 }) // 30 requests per minute
  async lookupByZipCode(
    @Param() params: ZipCodeParamDto,
    @Req() req: Request
  ): Promise<AddressLookupResultDto> {
    const clientIp = extractClientIp(req);
    return this.japanPost.lookupByZipCode(params.zipCode, clientIp);
  }

  /**
   * Check if address lookup service is available
   *
   * @route GET /api/address/status
   * @returns Service availability status
   */
  @Public()
  @Get("status")
  getStatus(): { available: boolean } {
    return { available: this.japanPost.isAvailable() };
  }
}
