#!/usr/bin/env node
/**
 * Point Memind LLM + local goosed (127.0.0.1:18006) at a working relay profile.
 *
 * Prefers ~/.config/goose/custom_providers/andu_deepseek.json (same as Goose Desktop),
 * then H5_LOCAL_RELAY_* env overrides.
 *
 * Usage:
 *   node scripts/fix-local-goose-relay.mjs
 */
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { createDbPool } from '../db.mjs';
import {
  createLlmProviderService,
  resolveChatCompletionsUrl,
  testRelayConnection,
} from '../llm-providers.mjs';

const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');

function loadEnvFile(filePath) {
  if (!fs.existsSync(filePath)) return;
  for (const line of fs.readFileSync(filePath, 'utf8').split('\n')) {
    const trimmed = line.trim();
    if (!trimmed || trimmed.startsWith('#')) continue;
    const eq = trimmed.indexOf('=');
    if (eq < 0) continue;
    const key = trimmed.slice(0, eq).trim();
    const value = trimmed.slice(eq + 1).trim();
    if (!process.env[key]) process.env[key] = value;
  }
}

function loadGooseAnduDeepseekProfile() {
  const profilePath = path.join(
    os.homedir(),
    '.config/goose/custom_providers/andu_deepseek.json',
  );
  if (!fs.existsSync(profilePath)) return null;
  const raw = JSON.parse(fs.readFileSync(profilePath, 'utf8'));
  const authHeader = raw?.headers?.Authorization ?? '';
  const token = authHeader.replace(/^Bearer\s+/i, '').trim();
  const baseUrl = String(raw?.base_url ?? '').trim();
  if (!token || !baseUrl) return null;
  const models = (raw?.models ?? []).map((item) => item.name).filter(Boolean);
  return {
    name: raw.display_name ?? 'Local Goose DeepSeek',
    apiUrl: resolveChatCompletionsUrl(baseUrl),
    apiKey: token,
    models: models.length ? models : ['deepseek-chat'],
    defaultModel: raw?.models?.[0]?.name ?? 'deepseek-chat',
    relayProvider: 'deepseek',
  };
}

loadEnvFile(path.join(root, '.env'));

const gooseProfile = loadGooseAnduDeepseekProfile();
const relayUrl =
  process.env.H5_LOCAL_RELAY_URL ??
  gooseProfile?.apiUrl ??
  'http://127.0.0.1:18300/relay/buyer/v1/chat/completions';
const relayToken =
  process.env.H5_LOCAL_RELAY_TOKEN ?? gooseProfile?.apiKey ?? '';
const relayModel = process.env.H5_LOCAL_RELAY_MODEL ?? gooseProfile?.defaultModel ?? 'deepseek-chat';
const relayModels = process.env.H5_LOCAL_RELAY_MODELS
  ? process.env.H5_LOCAL_RELAY_MODELS.split(',')
      .map((item) => item.trim())
      .filter(Boolean)
  : (gooseProfile?.models ?? ['deepseek-chat', 'deepseek-reasoner']);
const configName =
  process.env.H5_LOCAL_RELAY_NAME ?? gooseProfile?.name ?? 'Local Goose DeepSeek';

if (!relayToken) {
  console.error('缺少 relay token：设置 H5_LOCAL_RELAY_TOKEN 或配置 ~/.config/goose/custom_providers/andu_deepseek.json');
  process.exit(1);
}

const pool = createDbPool();
const svc = createLlmProviderService(pool, {
  apiTarget: process.env.TKMIND_API_TARGET ?? 'https://127.0.0.1:18006',
  apiSecret: process.env.TKMIND_SERVER__SECRET_KEY ?? 'local-dev-secret',
});

const [rows] = await pool.query(
  'SELECT id FROM h5_llm_provider_keys WHERE is_selected = 1 LIMIT 1',
);
const id = rows[0]?.id;
if (!id) {
  console.error('未找到已启用的 LLM 配置');
  process.exit(1);
}

const updated = await svc.updateKey(id, {
  name: configName,
  apiUrl: relayUrl,
  apiKey: relayToken,
  models: relayModels,
  defaultModel: relayModel,
  relayProvider: 'deepseek',
});

if (!updated.ok) {
  console.error('更新失败:', updated.message);
  process.exit(1);
}

const synced = await svc.syncSelectedToGoosed();
if (!synced.ok) {
  console.error('同步 goosed 失败:', synced.message);
  process.exit(1);
}

const test = await testRelayConnection({
  apiUrl: relayUrl,
  apiKey: relayToken,
  model: relayModel,
  relayProvider: 'deepseek',
});

console.log('LLM 已对接本地 goosed:', process.env.TKMIND_API_TARGET ?? 'https://127.0.0.1:18006');
console.log('Relay:', relayUrl);
console.log('goosed provider:', synced.providerId, 'model:', synced.model);
console.log('连通测试:', test.ok ? `OK (${test.latencyMs}ms)` : test.message);

await pool.end();
process.exit(test.ok ? 0 : 1);
