import i18n from 'i18next';
import Constants from 'expo-constants';
import * as Notifications from 'expo-notifications';
import { Platform } from 'react-native';

import { httpJson } from '../utils/http';
import { APP_ENV } from '../constants/env';
import { getDailyReminderSettings, getOrCreateClientUserId, getUserProfileScoring } from '../storage/appStorage';
import type { UserProfileScoring } from '../storage/appStorage';
import { toBackendLocaleFromLanguageTag } from '../i18n/locale';

export type PushEnv = 'dev' | 'prod';

export type PushPlatform = 'ios' | 'android';

export type PushDeviceMeta = {
  model?: string;
  os_version?: string;
  app_version?: string;
  locale?: string;
  timezone?: string;
};

export type PushRegisterRequest = {
  client_user_id: string;
  platform: PushPlatform;
  push_token: string;
  app_id: string;
  env: PushEnv;
  device_meta?: PushDeviceMeta;
};

export type PushPreferencesRequest = {
  client_user_id: string;
  enabled: boolean;
  times_per_day: number; // 0～5
  timezone?: string;
  locale?: string;
  // 可选：用户画像（用于后端 Push 场景推荐文案生成）
  user_profile?: UserProfileScoring;
};

export type PushPreferencesResponse = PushPreferencesRequest & {
  updated_at?: string;
};

export function buildAcceptLanguage(): 'en' | 'tc' {
  return toBackendLocaleFromLanguageTag(i18n.language);
}

function toPushEnv(appEnv: typeof APP_ENV): PushEnv {
  // 客户端 APP_ENV: local/dev/prod → 后端推送 env: dev/prod
  if (appEnv === 'prod') return 'prod';
  return 'dev';
}

function pickAppId(): string {
  // 优先按平台取 bundleId/package；拿不到则回退到 slug
  if (Platform.OS === 'ios') {
    return (
      Constants.expoConfig?.ios?.bundleIdentifier ||
      Constants.easConfig?.projectId ||
      Constants.expoConfig?.slug ||
      'unknown'
    );
  }
  if (Platform.OS === 'android') {
    return (
      Constants.expoConfig?.android?.package ||
      Constants.easConfig?.projectId ||
      Constants.expoConfig?.slug ||
      'unknown'
    );
  }
  return Constants.expoConfig?.slug || 'unknown';
}

function pickTimezone(): string | undefined {
  try {
    const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
    return tz && String(tz).trim() ? String(tz).trim() : undefined;
  } catch {
    return undefined;
  }
}

function pickLocale(): string | undefined {
  const lang = (i18n.language || '').trim();
  return lang ? lang : undefined;
}

function pickPlatform(): PushPlatform {
  return Platform.OS === 'ios' ? 'ios' : 'android';
}

function getExpoProjectId(): string | undefined {
  // Expo 官方推荐读取 projectId（EAS/Dev Client 下通常需要）
  return (
    Constants.easConfig?.projectId ||
    // 兼容 app.json / app.config.ts 的 extra.eas.projectId
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    (Constants.expoConfig as any)?.extra?.eas?.projectId ||
    // 兜底：某些运行时环境仍可直接读到 EXPO_PUBLIC_ 注入
    process.env.EXPO_PUBLIC_EAS_PROJECT_ID ||
    undefined
  );
}

export async function getExpoPushTokenOrThrow(): Promise<string> {
  const projectId = getExpoProjectId();
  try {
    const res = projectId
      ? await Notifications.getExpoPushTokenAsync({ projectId })
      : await Notifications.getExpoPushTokenAsync();
    return res.data;
  } catch (e) {
    const msg = e instanceof Error ? e.message : String(e);
    const hint = projectId
      ? ''
      : '（可能缺少 EAS projectId：请在 .env.local 配置 EXPO_PUBLIC_EAS_PROJECT_ID，或在 app.json/app.config.ts 的 extra.eas.projectId 写入后重试）';
    throw new Error(`获取 Expo Push Token 失败：${msg}${hint}`);
  }
}

export async function registerPushToken(args: { pushToken: string }): Promise<void> {
  const clientUserId = await getOrCreateClientUserId();
  const headers: Record<string, string> = {
    'Accept-Language': buildAcceptLanguage(),
  };

  const deviceMeta: PushDeviceMeta = {
    os_version: String(Platform.Version ?? ''),
    app_version: Constants.expoConfig?.version,
    locale: pickLocale(),
    timezone: pickTimezone(),
  };

  const body: PushRegisterRequest = {
    client_user_id: clientUserId,
    platform: pickPlatform(),
    push_token: args.pushToken,
    app_id: pickAppId(),
    env: toPushEnv(APP_ENV),
    device_meta: deviceMeta,
  };

  await httpJson<void>({
    path: '/v1/push/register',
    method: 'POST',
    headers,
    body,
    timeoutMs: 10_000,
    debugLabel: 'PushRegister',
  });
}

export async function setPushPreferences(args: { enabled: boolean; timesPerDay: number }): Promise<PushPreferencesResponse> {
  const clientUserId = await getOrCreateClientUserId();
  const tz = pickTimezone();
  const locale = pickLocale();
  const scoringProfile = await getUserProfileScoring().catch(() => null);
  const headers: Record<string, string> = {
    'Accept-Language': buildAcceptLanguage(),
  };

  const body: PushPreferencesRequest = {
    client_user_id: clientUserId,
    enabled: Boolean(args.enabled) && args.timesPerDay > 0,
    times_per_day: Math.min(5, Math.max(0, Math.round(args.timesPerDay))),
    timezone: tz,
    locale,
    user_profile: scoringProfile ?? undefined,
  };

  return await httpJson<PushPreferencesResponse>({
    path: '/v1/push/preferences',
    method: 'PUT',
    headers,
    body,
    timeoutMs: 10_000,
    debugLabel: 'PushPreferences',
  });
}

export async function getPushPreferences(): Promise<PushPreferencesResponse> {
  const clientUserId = await getOrCreateClientUserId();
  const headers: Record<string, string> = {
    'Accept-Language': buildAcceptLanguage(),
  };
  const qs = `client_user_id=${encodeURIComponent(clientUserId)}`;
  return await httpJson<PushPreferencesResponse>({
    path: `/v1/push/preferences?${qs}`,
    method: 'GET',
    headers,
    timeoutMs: 8_000,
    debugLabel: 'PushPreferencesGet',
  });
}

// 预留：未来推送文案个性化需要上报用户画像时使用（本期先不强制依赖）
export async function setPushProfileHint(_profile: UserProfileScoring | null): Promise<void> {
  // 本期不实现：后端通过现有推荐模块自行拉取/计算 push 文案
}

export async function syncPushPreferencesFromLocal(): Promise<void> {
  const s = await getDailyReminderSettings();
  await setPushPreferences({ enabled: s.pushEnabled, timesPerDay: s.timesPerDay });
}

