import { Controller, Get, Request, UseGuards, Header } from "@nestjs/common";
import { RateLimitGuard, RateLimit } from "@bff/core/rate-limiting/index.js";
import type { RequestWithUser } from "@bff/modules/auth/auth.types.js";
import { Public } from "@bff/modules/auth/decorators/public.decorator.js";
import {
  parseInternetCatalog,
  parseSimCatalog,
  parseVpnCatalog,
  type InternetAddonCatalogItem,
  type InternetInstallationCatalogItem,
  type InternetPlanCatalogItem,
  type SimActivationFeeCatalogItem,
  type SimCatalogCollection,
  type SimCatalogProduct,
  type VpnCatalogProduct,
  type VpnCatalogCollection,
} from "@customer-portal/domain/services";
import { InternetServicesService } from "./application/internet-services.service.js";
import { SimServicesService } from "./application/sim-services.service.js";
import { VpnServicesService } from "./application/vpn-services.service.js";
import { SalesforceReadThrottleGuard } from "@bff/integrations/salesforce/guards/salesforce-read-throttle.guard.js";

@Controller("services")
@Public() // Allow public access - services can be browsed without authentication
@UseGuards(SalesforceReadThrottleGuard, RateLimitGuard)
export class ServicesController {
  constructor(
    private internetCatalog: InternetServicesService,
    private simCatalog: SimServicesService,
    private vpnCatalog: VpnServicesService
  ) {}

  @Get("internet/plans")
  @RateLimit({ limit: 20, ttl: 60 }) // 20 requests per minute
  @Header("Cache-Control", "private, no-store") // Personalised responses: avoid browser caching (realtime invalidation relies on refetch)
  async getInternetPlans(@Request() req: RequestWithUser): Promise<{
    plans: InternetPlanCatalogItem[];
    installations: InternetInstallationCatalogItem[];
    addons: InternetAddonCatalogItem[];
  }> {
    const userId = req.user?.id;
    if (!userId) {
      const catalog = await this.internetCatalog.getCatalogData();
      return parseInternetCatalog(catalog);
    }

    const [plans, installations, addons] = await Promise.all([
      this.internetCatalog.getPlansForUser(userId),
      this.internetCatalog.getInstallations(),
      this.internetCatalog.getAddons(),
    ]);

    return parseInternetCatalog({ plans, installations, addons });
  }

  @Get("internet/addons")
  @Header("Cache-Control", "public, max-age=300, s-maxage=300") // 5 minutes
  async getInternetAddons(): Promise<InternetAddonCatalogItem[]> {
    return this.internetCatalog.getAddons();
  }

  @Get("internet/installations")
  @Header("Cache-Control", "public, max-age=300, s-maxage=300") // 5 minutes
  async getInternetInstallations(): Promise<InternetInstallationCatalogItem[]> {
    return this.internetCatalog.getInstallations();
  }

  @Get("sim/plans")
  @RateLimit({ limit: 20, ttl: 60 }) // 20 requests per minute
  @Header("Cache-Control", "private, no-store") // Personalised responses: avoid browser caching (realtime invalidation relies on refetch)
  async getSimCatalogData(@Request() req: RequestWithUser): Promise<SimCatalogCollection> {
    const userId = req.user?.id;
    if (!userId) {
      const catalog = await this.simCatalog.getCatalogData();
      return parseSimCatalog({
        ...catalog,
        plans: catalog.plans.filter(plan => !plan.simHasFamilyDiscount),
      });
    }

    const [plans, activationFees, addons] = await Promise.all([
      this.simCatalog.getPlansForUser(userId),
      this.simCatalog.getActivationFees(),
      this.simCatalog.getAddons(),
    ]);

    return parseSimCatalog({ plans, activationFees, addons });
  }

  @Get("sim/activation-fees")
  @Header("Cache-Control", "public, max-age=300, s-maxage=300") // 5 minutes
  async getSimActivationFees(): Promise<SimActivationFeeCatalogItem[]> {
    return this.simCatalog.getActivationFees();
  }

  @Get("sim/addons")
  @Header("Cache-Control", "public, max-age=300, s-maxage=300") // 5 minutes
  async getSimAddons(): Promise<SimCatalogProduct[]> {
    return this.simCatalog.getAddons();
  }

  @Get("vpn/plans")
  @RateLimit({ limit: 20, ttl: 60 }) // 20 requests per minute
  @Header("Cache-Control", "public, max-age=300, s-maxage=300") // 5 minutes
  async getVpnPlans(): Promise<VpnCatalogCollection> {
    // Backwards-compatible: return the full VPN catalog (plans + activation fees)
    const catalog = await this.vpnCatalog.getCatalogData();
    return parseVpnCatalog(catalog);
  }

  @Get("vpn/activation-fees")
  @Header("Cache-Control", "public, max-age=300, s-maxage=300") // 5 minutes
  async getVpnActivationFees(): Promise<VpnCatalogProduct[]> {
    return this.vpnCatalog.getActivationFees();
  }
}
