import { getGoogleAccessToken, googleFetch } from './google-auth.js';

function headerMap(message) {
  return Object.fromEntries((message.payload?.headers || []).map(h => [String(h.name).toLowerCase(), h.value]));
}

function decodeBase64Url(data = '') {
  if (!data) return '';
  try { return Buffer.from(String(data), 'base64url').toString('utf8'); } catch { return ''; }
}

function bodyTextFromPayload(payload = {}) {
  if (payload.body?.data) return decodeBase64Url(payload.body.data);
  const parts = Array.isArray(payload.parts) ? payload.parts : [];
  const preferred = parts.find(part => part.mimeType === 'text/plain' && part.body?.data)
    || parts.find(part => part.body?.data);
  return preferred ? bodyTextFromPayload(preferred) : '';
}

function shapeMessage(message, { includeBody = false } = {}) {
  const headers = headerMap(message);
  const shaped = {
    id: message.id,
    thread_id: message.threadId,
    from: headers.from || null,
    subject: headers.subject || null,
    date: headers.date || null,
    snippet: message.snippet || '',
  };
  if (includeBody) {
    shaped.to = headers.to || null;
    shaped.body_text = bodyTextFromPayload(message.payload || {});
  }
  return shaped;
}

async function fetchGoogleJson(url, token, opts, toolName) {
  const loggedFetch = googleFetch(toolName, opts);
  const res = await loggedFetch(url, { headers: { Authorization: `Bearer ${token}` } });
  if (!res.ok) throw new Error(`google api failed: ${res.status}`);
  return res.json();
}

export async function gmail_messages_list(args = {}, opts = {}) {
  const toolName = 'gmail_messages_list';
  const token = await getGoogleAccessToken(opts, toolName);
  const url = new URL('https://gmail.googleapis.com/gmail/v1/users/me/messages');
  if (args.max_results) url.searchParams.set('maxResults', String(args.max_results));
  if (args.q) url.searchParams.set('q', args.q);
  for (const label of args.label_ids || args.labelIds || []) url.searchParams.append('labelIds', String(label));
  const data = await fetchGoogleJson(url, token, opts, toolName);
  const messages = data.messages || [];
  return Promise.all(messages.map(async message => {
    const detail = await fetchGoogleJson(`https://gmail.googleapis.com/gmail/v1/users/me/messages/${encodeURIComponent(message.id)}?format=metadata`, token, opts, toolName);
    return shapeMessage(detail);
  }));
}

export async function gmail_message_read(args = {}, opts = {}) {
  if (!args.message_id) throw new Error('message_id is required');
  const toolName = 'gmail_message_read';
  const token = await getGoogleAccessToken(opts, toolName);
  const data = await fetchGoogleJson(`https://gmail.googleapis.com/gmail/v1/users/me/messages/${encodeURIComponent(args.message_id)}?format=full`, token, opts, toolName);
  return shapeMessage(data, { includeBody: true });
}

export async function gmail_thread_read(args = {}, opts = {}) {
  if (!args.thread_id) throw new Error('thread_id is required');
  const toolName = 'gmail_thread_read';
  const token = await getGoogleAccessToken(opts, toolName);
  const data = await fetchGoogleJson(`https://gmail.googleapis.com/gmail/v1/users/me/threads/${encodeURIComponent(args.thread_id)}?format=full`, token, opts, toolName);
  return { id: data.id, messages: (data.messages || []).map(message => shapeMessage(message, { includeBody: true })) };
}
