import { Controller } from "@nestjs/common";
import { GrpcMethod } from "@nestjs/microservices";
import { PreferencesService } from "../preferences/preferences.service.js";
import { updatePreferencesSchema } from "../preferences/preferences.dto.js";
import type { NotificationPreference } from "../notifications/notifications.schema.js";

/**
 * PreferencesGrpcController —— gRPC 入口（NotificationPreferenceService 2 RPC）。
 *
 * 仲裁依据：
 * - msg.proto §NotificationPreferenceService（GetPreferences / UpdatePreferences）
 * - proto-loader 默认 keepCase=false，字段名 camelCase
 */

interface GrpcPreference {
  id: string;
  userId: string;
  type: string;
  channels: string[];
  frequencyLimit: number;
  quietHoursStart: string;
  quietHoursEnd: string;
  quietHoursTimezone: string;
  enabled: boolean;
  createdAt: number;
  updatedAt: number;
}

function opt(val: unknown): string | undefined {
  if (typeof val === "string" && val.length > 0) return val;
  return undefined;
}

function toGrpcPreference(p: NotificationPreference): GrpcPreference {
  return {
    id: p.id,
    userId: p.userId,
    type: p.type,
    channels: p.channels,
    frequencyLimit: p.frequencyLimit ?? 0,
    quietHoursStart: p.quietHoursStart ?? "",
    quietHoursEnd: p.quietHoursEnd ?? "",
    quietHoursTimezone: p.quietHoursTimezone ?? "",
    enabled: p.enabled,
    createdAt: p.createdAt instanceof Date ? p.createdAt.getTime() : 0,
    updatedAt: p.updatedAt instanceof Date ? p.updatedAt.getTime() : 0,
  };
}

@Controller()
export class PreferencesGrpcController {
  constructor(private readonly service: PreferencesService) {}

  @GrpcMethod("NotificationPreferenceService", "GetPreferences")
  async getPreferences(
    data: Record<string, unknown>,
  ): Promise<{ preferences: GrpcPreference[] }> {
    const prefs = await this.service.getByUserId(String(data.userId ?? ""));
    return { preferences: prefs.map(toGrpcPreference) };
  }

  @GrpcMethod("NotificationPreferenceService", "UpdatePreferences")
  async updatePreferences(
    data: Record<string, unknown>,
  ): Promise<Record<string, never>> {
    const rawPrefs = Array.isArray(data.preferences) ? data.preferences : [];

    const dto = updatePreferencesSchema.parse({
      userId: data.userId,
      preferences: rawPrefs.map((p: Record<string, unknown>) => ({
        type: p.type,
        channels: Array.isArray(p.channels) ? p.channels : [],
        frequencyLimit: p.frequencyLimit ? Number(p.frequencyLimit) : undefined,
        quietHoursStart: opt(p.quietHoursStart),
        quietHoursEnd: opt(p.quietHoursEnd),
        quietHoursTimezone: opt(p.quietHoursTimezone),
        enabled: p.enabled ?? true,
      })),
    });

    await this.service.update(dto);
    return {};
  }
}
