/**
 * Confluence Cloud REST API v2 client — routes through AgilitonAPI gateway.
 * Falls back to direct Confluence access if AGILITON_API_KEY is not set.
 *
 * Gateway: AGILITON_API_KEY + AGILITON_API_URL
 * Direct:  CONFLUENCE_USER/JIRA_USER + CONFLUENCE_API_TOKEN/JIRA_API_TOKEN
 */

// Gateway config
const GATEWAY_URL = (process.env.AGILITON_API_URL || 'https://api.agiliton.cloud').replace(/\/$/, '');
const GATEWAY_KEY = process.env.AGILITON_API_KEY || '';

// Direct config (fallback)
const BASE_URL = process.env.CONFLUENCE_URL || 'https://agiliton.atlassian.net/wiki';
const API_V2 = `${BASE_URL}/api/v2`;
const API_V1 = `${BASE_URL}/rest/api`;

function useGateway(): boolean {
  return !!GATEWAY_KEY;
}

function getAuth(): string {
  const user = process.env.CONFLUENCE_USER || process.env.JIRA_USER;
  const token = process.env.CONFLUENCE_API_TOKEN || process.env.JIRA_API_TOKEN;
  if (!user || !token) {
    throw new Error('CONFLUENCE_USER and CONFLUENCE_API_TOKEN (or JIRA_USER/JIRA_API_TOKEN) must be set');
  }
  return Buffer.from(`${user}:${token}`).toString('base64');
}

async function request(url: string, options: RequestInit = {}): Promise<any> {
  let finalUrl = url;
  const headers: Record<string, string> = {
    'Accept': 'application/json',
    ...(options.headers as Record<string, string> || {}),
  };

  if (useGateway()) {
    // Route through gateway — translate Confluence URLs to gateway paths
    finalUrl = toGatewayUrl(url);
    headers['X-API-Key'] = GATEWAY_KEY;
  } else {
    headers['Authorization'] = `Basic ${getAuth()}`;
  }

  if (options.body && typeof options.body === 'string') {
    headers['Content-Type'] = 'application/json';
  }

  const response = await fetch(finalUrl, { ...options, headers });

  if (!response.ok) {
    const text = await response.text().catch(() => '');
    throw new Error(`Confluence API ${response.status}: ${text.slice(0, 500)}`);
  }

  if (response.status === 204) return null;
  return response.json();
}

/**
 * Translate a direct Confluence URL to a gateway URL.
 * /wiki/api/v2/spaces → /confluence/spaces
 * /wiki/rest/api/content/search → /confluence/search
 * /wiki/rest/api/space → /confluence/space
 */
function toGatewayUrl(url: string): string {
  // Extract path from full URL
  let path = url;
  if (path.startsWith('http')) {
    const u = new URL(path);
    path = u.pathname + u.search;
  }

  // v2 API: /wiki/api/v2/... → /confluence/...
  const v2Match = path.match(/\/api\/v2\/(.*)$/);
  if (v2Match) return `${GATEWAY_URL}/confluence/${v2Match[1]}`;

  // v1 API: /wiki/rest/api/content/search → /confluence/search
  const searchMatch = path.match(/\/rest\/api\/content\/search(.*)$/);
  if (searchMatch) return `${GATEWAY_URL}/confluence/search${searchMatch[1]}`;

  // v1 API: /wiki/rest/api/space → /confluence/space
  const spaceMatch = path.match(/\/rest\/api\/space(.*)$/);
  if (spaceMatch) return `${GATEWAY_URL}/confluence/space${spaceMatch[1]}`;

  // Fallback: strip /wiki prefix and use as-is
  const stripped = path.replace(/^\/wiki/, '');
  return `${GATEWAY_URL}/confluence${stripped}`;
}

// --- Types ---

export interface Space {
  id: string;
  key: string;
  name: string;
  type: string;
  status: string;
  description?: string;
}

export interface Page {
  id: string;
  status: string;
  title: string;
  spaceId: string;
  parentId?: string;
  authorId: string;
  createdAt: string;
  version: {
    number: number;
    message?: string;
    createdAt: string;
    authorId?: string;
  };
  body?: {
    storage?: { representation: string; value: string };
    atlas_doc_format?: { representation: string; value: string };
  };
  _links?: {
    webui?: string;
    editui?: string;
  };
}

export interface Comment {
  id: string;
  status: string;
  title: string;
  body?: {
    storage?: { representation: string; value: string };
  };
  version: { number: number; createdAt: string };
}

// --- Spaces ---

export async function listSpaces(limit = 25): Promise<Space[]> {
  const data = await request(`${API_V2}/spaces?limit=${limit}&sort=name`);
  return data.results;
}

export async function getSpace(spaceIdOrKey: string): Promise<Space> {
  return request(`${API_V2}/spaces/${spaceIdOrKey}`);
}

export async function createSpace(key: string, name: string, description?: string): Promise<Space> {
  // v2 doesn't have space creation — use v1
  const body: any = {
    key,
    name,
    type: 'global',
  };
  if (description) {
    body.description = {
      plain: { value: description, representation: 'plain' },
    };
  }
  return request(`${API_V1}/space`, {
    method: 'POST',
    body: JSON.stringify(body),
  });
}

// --- Pages ---

export async function searchPages(query: string, spaceId?: string, limit = 10): Promise<Page[]> {
  let cql = `type=page AND text ~ "${query.replace(/"/g, '\\"')}"`;
  if (spaceId) cql += ` AND space.id=${spaceId}`;
  cql += ' ORDER BY lastmodified DESC';

  const params = new URLSearchParams({
    cql,
    limit: String(limit),
  });
  // CQL search is v1 only
  const data = await request(`${API_V1}/content/search?${params}`);
  return data.results.map((r: any) => ({
    id: r.id,
    status: r.status,
    title: r.title,
    spaceId: r.space?.id || '',
    authorId: r.history?.createdBy?.accountId || '',
    createdAt: r.history?.createdDate || '',
    version: {
      number: r.version?.number || 1,
      createdAt: r.version?.when || '',
    },
    _links: {
      webui: r._links?.webui ? `${BASE_URL}${r._links.webui}` : undefined,
    },
  }));
}

export async function getPage(pageId: string, includeBody = true): Promise<Page> {
  const params = includeBody ? '?body-format=storage' : '';
  return request(`${API_V2}/pages/${pageId}${params}`);
}

export async function getPageByTitle(spaceId: string, title: string): Promise<Page | null> {
  const params = new URLSearchParams({
    title,
    'space-id': spaceId,
    'body-format': 'storage',
    limit: '1',
  });
  const data = await request(`${API_V2}/pages?${params}`);
  return data.results?.[0] || null;
}

export async function createPage(
  spaceId: string,
  title: string,
  body: string,
  parentId?: string,
): Promise<Page> {
  const payload: any = {
    spaceId,
    status: 'current',
    title,
    body: {
      representation: 'storage',
      value: body,
    },
  };
  if (parentId) payload.parentId = parentId;

  return request(`${API_V2}/pages`, {
    method: 'POST',
    body: JSON.stringify(payload),
  });
}

export async function updatePage(
  pageId: string,
  title: string,
  body: string,
  versionNumber: number,
  versionMessage?: string,
): Promise<Page> {
  const payload: any = {
    id: pageId,
    status: 'current',
    title,
    body: {
      representation: 'storage',
      value: body,
    },
    version: {
      number: versionNumber,
      message: versionMessage || 'Updated via Claude',
    },
  };

  return request(`${API_V2}/pages/${pageId}`, {
    method: 'PUT',
    body: JSON.stringify(payload),
  });
}

// --- Comments ---

export async function getPageComments(pageId: string, limit = 25): Promise<Comment[]> {
  const data = await request(`${API_V2}/pages/${pageId}/footer-comments?body-format=storage&limit=${limit}`);
  return data.results;
}

export async function addPageComment(pageId: string, body: string): Promise<Comment> {
  return request(`${API_V2}/footer-comments`, {
    method: 'POST',
    body: JSON.stringify({
      pageId,
      body: {
        representation: 'storage',
        value: body,
      },
    }),
  });
}

// --- Utility ---

export function getWebUrl(page: Page): string {
  if (page._links?.webui) {
    return page._links.webui.startsWith('http')
      ? page._links.webui
      : `${BASE_URL}${page._links.webui}`;
  }
  return `${BASE_URL}/pages/${page.id}`;
}
