/**
 * Japan Post Facade
 *
 * Public API for Japan Post integration.
 * Controllers should use this facade instead of internal services directly.
 *
 * Adds Redis-backed caching for postal code lookups — address data is
 * stable and rarely changes, so a 24-hour TTL avoids redundant API calls.
 */

import { Inject, Injectable } from "@nestjs/common";
import { Logger } from "nestjs-pino";
import { JapanPostAddressService } from "../services/japanpost-address.service.js";
import { CacheService } from "@bff/infra/cache/cache.service.js";
import type { AddressLookupResult } from "@customer-portal/domain/address";

const CACHE_PREFIX = "japanpost:zip:";
const CACHE_TTL_SECONDS = 86_400; // 24 hours

@Injectable()
export class JapanPostFacade {
  constructor(
    private readonly addressService: JapanPostAddressService,
    private readonly cache: CacheService,
    @Inject(Logger) private readonly logger: Logger
  ) {}

  /**
   * Lookup address by ZIP code
   *
   * @param zipCode - ZIP code (with or without hyphen, e.g., "100-0001" or "1000001")
   * @param clientIp - Client IP address for API request (defaults to 127.0.0.1)
   * @returns Domain AddressLookupResult with Japanese and romanized address data
   */
  async lookupByZipCode(
    zipCode: string,
    clientIp: string = "127.0.0.1"
  ): Promise<AddressLookupResult> {
    const normalizedZip = zipCode.replace(/-/g, "");
    const cacheKey = `${CACHE_PREFIX}${normalizedZip}`;

    try {
      const cached = await this.cache.get<AddressLookupResult>(cacheKey);
      if (cached) {
        return cached;
      }
    } catch {
      // Redis unavailable — proceed without cache
    }

    const result = await this.addressService.lookupByZipCode(zipCode, clientIp);

    // Cache successful lookups with results
    if (result.count > 0) {
      try {
        await this.cache.set(cacheKey, result, CACHE_TTL_SECONDS);
      } catch {
        this.logger.debug({ zipCode: normalizedZip }, "Failed to cache Japan Post lookup result");
      }
    }

    return result;
  }

  /**
   * Check if the Japan Post service is available
   */
  isAvailable(): boolean {
    return this.addressService.isAvailable();
  }
}
