export const APP_LOCALE_COOKIE = 'beaver_locale';
export const APP_LOCALE_STORAGE_KEY = 'beaver_locale';

export const APP_LOCALES = ['zh-CN', 'en-US', 'zh-Hant'] as const;

export type AppLocale = (typeof APP_LOCALES)[number];

export function isAppLocale(value: string | null | undefined): value is AppLocale {
  return value === 'zh-CN' || value === 'en-US' || value === 'zh-Hant';
}

export function normalizeAppLocale(value?: string | null): AppLocale {
  const probe = value?.trim().toLowerCase() || '';
  if (probe.startsWith('en')) {
    return 'en-US';
  }
  if (
    probe === 'zh-hant' ||
    probe.startsWith('zh-tw') ||
    probe.startsWith('zh-hk') ||
    probe.startsWith('zh-mo')
  ) {
    return 'zh-Hant';
  }
  return 'zh-CN';
}

function readCookieLocale(): string | null {
  if (typeof document === 'undefined') {
    return null;
  }

  const match = document.cookie
    .split('; ')
    .find((item) => item.startsWith(`${APP_LOCALE_COOKIE}=`));
  if (!match) {
    return null;
  }
  return decodeURIComponent(match.slice(APP_LOCALE_COOKIE.length + 1));
}

export function readBrowserAppLocale(): AppLocale {
  if (typeof window === 'undefined') {
    return 'zh-CN';
  }

  const fromDocument = document.documentElement.lang;
  if (fromDocument) {
    return normalizeAppLocale(fromDocument);
  }

  const fromStorage = window.localStorage.getItem(APP_LOCALE_STORAGE_KEY);
  if (fromStorage) {
    return normalizeAppLocale(fromStorage);
  }

  const fromCookie = readCookieLocale();
  if (fromCookie) {
    return normalizeAppLocale(fromCookie);
  }

  return normalizeAppLocale(window.navigator.language);
}

export function persistAppLocale(locale: AppLocale): void {
  if (typeof window === 'undefined') {
    return;
  }

  document.documentElement.lang = locale;
  window.localStorage.setItem(APP_LOCALE_STORAGE_KEY, locale);
  document.cookie = `${APP_LOCALE_COOKIE}=${encodeURIComponent(locale)}; path=/; max-age=31536000; samesite=lax`;
}

export function getCurrentAppLocale(): AppLocale {
  if (typeof window === 'undefined') {
    return 'zh-CN';
  }
  return readBrowserAppLocale();
}

export function pickAppText<T>(locale: string | null | undefined, zhValue: T, enValue: T): T {
  const appLocale = normalizeAppLocale(locale);
  if (appLocale === 'en-US') {
    return enValue;
  }
  if (appLocale === 'zh-Hant') {
    return toTraditionalValue(zhValue);
  }
  return zhValue;
}

function toTraditionalValue<T>(value: T): T {
  return typeof value === 'string' ? (toTraditionalChinese(value) as T) : value;
}

const SIMPLIFIED_TO_TRADITIONAL_PHRASES: Array<[string, string]> = [
  ['智能体', '智慧體'],
  ['Agent Team', 'Agent Team'],
];

const SIMPLIFIED_TO_TRADITIONAL_CHARS: Record<string, string> = {
  个: '個',
  为: '為',
  么: '麼',
  义: '義',
  习: '習',
  书: '書',
  了: '了',
  于: '於',
  云: '雲',
  产: '產',
  仅: '僅',
  从: '從',
  仓: '倉',
  仪: '儀',
  们: '們',
  优: '優',
  会: '會',
  传: '傳',
  体: '體',
  余: '餘',
  侧: '側',
  侦: '偵',
  促: '促',
  俩: '倆',
  值: '值',
  假: '假',
  做: '做',
  停: '停',
  储: '儲',
  像: '像',
  儿: '兒',
  先: '先',
  光: '光',
  关: '關',
  兴: '興',
  具: '具',
  内: '內',
  册: '冊',
  写: '寫',
  军: '軍',
  农: '農',
  况: '況',
  冻: '凍',
  净: '淨',
  准: '準',
  几: '幾',
  击: '擊',
  划: '劃',
  则: '則',
  创: '創',
  初: '初',
  删: '刪',
  别: '別',
  到: '到',
  制: '製',
  剂: '劑',
  剩: '剩',
  办: '辦',
  功: '功',
  加: '加',
  务: '務',
  动: '動',
  助: '助',
  势: '勢',
  包: '包',
  区: '區',
  协: '協',
  单: '單',
  卖: '賣',
  占: '佔',
  卡: '卡',
  历: '歷',
  压: '壓',
  厕: '廁',
  厢: '廂',
  县: '縣',
  参: '參',
  双: '雙',
  发: '發',
  变: '變',
  叠: '疊',
  号: '號',
  后: '後',
  向: '向',
  吗: '嗎',
  启: '啟',
  员: '員',
  命: '命',
  咨: '諮',
  哑: '啞',
  响: '響',
  唤: '喚',
  问: '問',
  單: '單',
  喂: '餵',
  器: '器',
  团: '團',
  园: '園',
  困: '困',
  图: '圖',
  场: '場',
  块: '塊',
  坏: '壞',
  址: '址',
  坚: '堅',
  坛: '壇',
  型: '型',
  垃: '垃',
  域: '域',
  堆: '堆',
  填: '填',
  增: '增',
  墙: '牆',
  声: '聲',
  处: '處',
  备: '備',
  复: '復',
  够: '夠',
  头: '頭',
  奖: '獎',
  好: '好',
  如: '如',
  始: '始',
  委: '委',
  存: '存',
  学: '學',
  宁: '寧',
  它: '它',
  安: '安',
  完: '完',
  实: '實',
  审: '審',
  客: '客',
  宪: '憲',
  宽: '寬',
  对: '對',
  导: '導',
  将: '將',
  尔: '爾',
  尝: '嘗',
  层: '層',
  属: '屬',
  岁: '歲',
  岛: '島',
  州: '州',
  工: '工',
  币: '幣',
  师: '師',
  帐: '帳',
  带: '帶',
  帮: '幫',
  干: '乾',
  并: '並',
  广: '廣',
  庆: '慶',
  库: '庫',
  应: '應',
  废: '廢',
  开: '開',
  异: '異',
  弃: '棄',
  张: '張',
  强: '強',
  归: '歸',
  当: '當',
  录: '錄',
  彻: '徹',
  径: '徑',
  待: '待',
  循: '循',
  忆: '憶',
  志: '誌',
  忧: '憂',
  念: '念',
  态: '態',
  总: '總',
  恢: '恢',
  息: '息',
  您: '您',
  情: '情',
  想: '想',
  意: '意',
  愿: '願',
  戏: '戲',
  战: '戰',
  户: '戶',
  执: '執',
  扩: '擴',
  扫: '掃',
  扬: '揚',
  批: '批',
  找: '找',
  技: '技',
  报: '報',
  护: '護',
  抽: '抽',
  担: '擔',
  拥: '擁',
  择: '擇',
  按: '按',
  挥: '揮',
  换: '換',
  损: '損',
  据: '據',
  授: '授',
  掉: '掉',
  接: '接',
  控: '控',
  推: '推',
  提: '提',
  插: '插',
  揭: '揭',
  搜: '搜',
  携: '攜',
  摄: '攝',
  摘: '摘',
  播: '播',
  操: '操',
  支: '支',
  收: '收',
  改: '改',
  放: '放',
  效: '效',
  数: '數',
  文: '文',
  断: '斷',
  新: '新',
  无: '無',
  时: '時',
  明: '明',
  显: '顯',
  智: '智',
  暂: '暫',
  更: '更',
  替: '替',
  术: '術',
  机: '機',
  权: '權',
  条: '條',
  来: '來',
  极: '極',
  构: '構',
  标: '標',
  栏: '欄',
  树: '樹',
  样: '樣',
  核: '核',
  案: '案',
  档: '檔',
  检: '檢',
  楼: '樓',
  次: '次',
  款: '款',
  步: '步',
  残: '殘',
  段: '段',
  毕: '畢',
  气: '氣',
  汇: '匯',
  汉: '漢',
  没: '沒',
  法: '法',
  注: '註',
  泄: '洩',
  测: '測',
  浏: '瀏',
  消: '消',
  涉: '涉',
  涨: '漲',
  润: '潤',
  添: '添',
  清: '清',
  渠: '渠',
  渲: '渲',
  温: '溫',
  滚: '滾',
  满: '滿',
  漏: '漏',
  演: '演',
  点: '點',
  烦: '煩',
  热: '熱',
  然: '然',
  照: '照',
  爱: '愛',
  父: '父',
  片: '片',
  版: '版',
  状: '狀',
  独: '獨',
  环: '環',
  现: '現',
  理: '理',
  画: '畫',
  畅: '暢',
  疗: '療',
  登: '登',
  监: '監',
  盘: '盤',
  码: '碼',
  础: '礎',
  确: '確',
  碍: '礙',
  礼: '禮',
  离: '離',
  种: '種',
  称: '稱',
  稳: '穩',
  窗: '窗',
  笔: '筆',
  签: '簽',
  简: '簡',
  算: '算',
  管: '管',
  类: '類',
  粘: '黏',
  精: '精',
  系: '系',
  级: '級',
  线: '線',
  组: '組',
  细: '細',
  终: '終',
  经: '經',
  结: '結',
  绝: '絕',
  统: '統',
  维: '維',
  缓: '緩',
  编: '編',
  缩: '縮',
  缺: '缺',
  网: '網',
  置: '置',
  联: '聯',
  聊: '聊',
  肃: '肅',
  背: '背',
  能: '能',
  脚: '腳',
  脱: '脫',
  脑: '腦',
  自动: '自動',
  舰: '艦',
  艺: '藝',
  节: '節',
  范: '範',
  荐: '薦',
  获: '獲',
  营: '營',
  落: '落',
  著: '著',
  藏: '藏',
  虑: '慮',
  虚: '虛',
  虽: '雖',
  行: '行',
  补: '補',
  表: '表',
  装: '裝',
  规: '規',
  视: '視',
  觉: '覺',
  览: '覽',
  计: '計',
  订: '訂',
  认: '認',
  议: '議',
  讯: '訊',
  记: '記',
  讲: '講',
  许: '許',
  论: '論',
  设: '設',
  访: '訪',
  证: '證',
  评: '評',
  识: '識',
  诉: '訴',
  试: '試',
  话: '話',
  详: '詳',
  语: '語',
  误: '誤',
  请: '請',
  读: '讀',
  调: '調',
  谈: '談',
  谢: '謝',
  谷: '谷',
  账: '帳',
  负: '負',
  责: '責',
  败: '敗',
  货: '貨',
  质: '質',
  资: '資',
  赃: '贓',
  起: '起',
  超: '超',
  跃: '躍',
  路: '路',
  踪: '蹤',
  车: '車',
  轮: '輪',
  软: '軟',
  载: '載',
  辑: '輯',
  输: '輸',
  边: '邊',
  达: '達',
  过: '過',
  还: '還',
  这: '這',
  进: '進',
  远: '遠',
  连: '連',
  迟: '遲',
  适: '適',
  选: '選',
  递: '遞',
  通: '通',
  逻: '邏',
  遗: '遺',
  遥: '遙',
  邀: '邀',
  邮: '郵',
  部: '部',
  配: '配',
  释: '釋',
  重: '重',
  针: '針',
  钥: '鑰',
  钟: '鐘',
  钮: '鈕',
  钱: '錢',
  链: '鏈',
  错: '錯',
  键: '鍵',
  镜: '鏡',
  长: '長',
  门: '門',
  闭: '閉',
  间: '間',
  队: '隊',
  阶: '階',
  阳: '陽',
  阴: '陰',
  陈: '陳',
  际: '際',
  隐: '隱',
  难: '難',
  雏: '雛',
  需: '需',
  面: '面',
  页: '頁',
  项: '項',
  顺: '順',
  须: '須',
  预: '預',
  题: '題',
  颜: '顏',
  风: '風',
  飞: '飛',
  馆: '館',
  验: '驗',
  高: '高',
  鱼: '魚',
  鲜: '鮮',
  鸟: '鳥',
  麦: '麥',
  黄: '黃',
};

export function toTraditionalChinese(value: string): string {
  let converted = value;
  for (const [source, target] of SIMPLIFIED_TO_TRADITIONAL_PHRASES) {
    converted = converted.split(source).join(target);
  }
  return Array.from(converted)
    .map((char) => SIMPLIFIED_TO_TRADITIONAL_CHARS[char] ?? char)
    .join('');
}
