/**
 * Figma API Client
 */

import type {
  FigmaFileResponse,
  FigmaNodeResponse,
  FigmaImageResponse,
  FigmaImageFillsResponse,
  ParsedFigmaUrl,
} from './types.ts';

const BASE_URL = 'https://api.figma.com/v1';

export class FigmaClient {
  private apiKey: string;

  constructor(apiKey: string) {
    this.apiKey = apiKey;
  }

  private async request<T>(endpoint: string): Promise<T> {
    const url = `${BASE_URL}${endpoint}`;
    const response = await fetch(url, {
      headers: {
        'X-Figma-Token': this.apiKey,
      },
    });

    if (!response.ok) {
      const text = await response.text().catch(() => 'Unknown error');
      throw new Error(`Figma API error (${response.status}): ${text}`);
    }

    return response.json() as Promise<T>;
  }

  async getFile(fileKey: string, depth: number | null = null): Promise<FigmaFileResponse> {
    const depthParam = depth ? `?depth=${depth}` : '';
    return this.request<FigmaFileResponse>(`/files/${fileKey}${depthParam}`);
  }

  async getNode(fileKey: string, nodeId: string, depth: number | null = null): Promise<FigmaNodeResponse> {
    const encodedNodeId = encodeURIComponent(nodeId);
    const depthParam = depth ? `&depth=${depth}` : '';
    return this.request<FigmaNodeResponse>(`/files/${fileKey}/nodes?ids=${encodedNodeId}${depthParam}`);
  }

  async getImageFills(fileKey: string): Promise<FigmaImageFillsResponse> {
    return this.request<FigmaImageFillsResponse>(`/files/${fileKey}/images`);
  }

  async getImages(
    fileKey: string,
    nodeIds: string[],
    format: 'png' | 'svg' = 'png',
    scale = 1
  ): Promise<Record<string, string | null>> {
    if (nodeIds.length === 0) return {};

    const ids = nodeIds.join(',');
    let endpoint: string;

    if (format === 'svg') {
      const params = `ids=${ids}&format=svg&svg_outline_text=true&svg_include_id=false&svg_simplify_stroke=true`;
      endpoint = `/images/${fileKey}?${params}`;
    } else {
      endpoint = `/images/${fileKey}?ids=${ids}&format=png&scale=${scale}`;
    }

    const response = await this.request<FigmaImageResponse>(endpoint);
    return response.images;
  }
}

export function parseFigmaUrl(url: string): ParsedFigmaUrl | null {
  const patterns = [
    /figma\.com\/(?:file|design)\/([a-zA-Z0-9]+)(?:\/[^?]+)?(?:\?.*node-id=([0-9-]+))?/,
    /figma\.com\/(?:file|design)\/([a-zA-Z0-9]+)/,
  ];

  for (const pattern of patterns) {
    const match = url.match(pattern);
    if (match) {
      return {
        fileKey: match[1],
        nodeId: match[2] ? match[2].replace('-', ':') : null,
      };
    }
  }

  return null;
}

export async function downloadImage(imageUrl: string, localPath: string, fileName: string): Promise<string> {
  const fs = await import('fs');
  const path = await import('path');

  if (!fs.existsSync(localPath)) {
    fs.mkdirSync(localPath, { recursive: true });
  }

  const fullPath = path.join(localPath, fileName);

  const response = await fetch(imageUrl, { method: 'GET' });
  if (!response.ok) {
    throw new Error(`Failed to download image: ${response.statusText}`);
  }

  const buffer = await response.arrayBuffer();
  fs.writeFileSync(fullPath, Buffer.from(buffer));

  return fullPath;
}
