type OdooCfg = {
  url: string;
  database: string;
  username: string;
  apiKeyOrPassword: string;
  model: string;
};

async function jsonRpc(url: string, service: string, method: string, args: unknown[]): Promise<unknown> {
  const base = url.replace(/\/$/, '');
  const res = await fetch(`${base}/jsonrpc`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      jsonrpc: '2.0',
      method: 'call',
      params: { service, method, args },
      id: Date.now(),
    }),
  });
  if (!res.ok) throw new Error(`Odoo HTTP ${res.status}`);
  const body = await res.json() as { result?: unknown; error?: { data?: { message?: string }; message?: string } };
  if (body.error) {
    throw new Error(body.error.data?.message || body.error.message || 'Odoo RPC error');
  }
  return body.result;
}

export async function syncToOdoo(
  cfg: OdooCfg,
  fields: { title: string; description: string; priority?: string },
): Promise<{ external_id: string; external_url: string | null }> {
  const uid = await jsonRpc(cfg.url, 'common', 'authenticate', [
    cfg.database, cfg.username, cfg.apiKeyOrPassword, {},
  ]);
  if (typeof uid !== 'number' || uid <= 0) {
    throw new Error('Odoo authentication failed — check URL, database, user and API key');
  }

  const priorityMap: Record<string, string> = { high: '1', medium: '2', low: '3' };
  const vals: Record<string, unknown> = {
    name: fields.title.slice(0, 200),
    description: fields.description,
  };
  if (fields.priority && cfg.model.includes('helpdesk')) {
    vals.priority = priorityMap[fields.priority] ?? '2';
  }

  const id = await jsonRpc(cfg.url, 'object', 'execute_kw', [
    cfg.database, uid, cfg.apiKeyOrPassword,
    cfg.model, 'create', [vals],
  ]);
  if (typeof id !== 'number') throw new Error('Odoo create returned no id');

  const base = cfg.url.replace(/\/$/, '');
  return {
    external_id: String(id),
    external_url: `${base}/web#id=${id}&model=${encodeURIComponent(cfg.model)}&view_type=form`,
  };
}
