/**
 * DSS Extract Command
 *
 * Extract tokens or components from Figma.
 */

import chalk from 'chalk';
import ora from 'ora';
import { writeFileSync, existsSync, mkdirSync } from 'fs';
import { join } from 'path';
import { getConfig, getProjectRoot } from '../lib/config.js';
import { getApiClient } from '../lib/api.js';
import { isServerRunning } from '../lib/server.js';

interface ExtractOptions {
  format: string;
  output?: string;
  fileKey?: string;
}

export async function extractCommand(
  type: string,
  options: ExtractOptions
): Promise<void> {
  const validTypes = ['tokens', 'components', 'styles', 'all'];
  if (!validTypes.includes(type)) {
    console.log(chalk.red(`  Invalid type: ${type}`));
    console.log(chalk.dim(`  Valid types: ${validTypes.join(', ')}`));
    process.exit(1);
  }

  const config = getConfig();
  const cwd = getProjectRoot();

  // Check if server is running
  if (!isServerRunning(cwd)) {
    console.log(chalk.yellow('  DSS server is not running'));
    console.log(chalk.dim('  Start it with: dss start'));
    process.exit(1);
  }

  const fileKey = options.fileKey || config.figmaFileKey;
  if (!fileKey) {
    console.log(chalk.red('  No Figma file key configured'));
    console.log(chalk.dim('  Set it with: dss config --set figmaFileKey=YOUR_KEY'));
    process.exit(1);
  }

  const outputDir = options.output || join(cwd, '.dss', 'output');
  if (!existsSync(outputDir)) {
    mkdirSync(outputDir, { recursive: true });
  }

  const api = getApiClient({ port: config.port });

  if (type === 'tokens' || type === 'all') {
    await extractTokens(api, fileKey, options.format, outputDir);
  }

  if (type === 'components' || type === 'all') {
    await extractComponents(api, fileKey, outputDir);
  }

  if (type === 'styles' || type === 'all') {
    await extractStyles(api, fileKey, outputDir);
  }
}

async function extractTokens(
  api: ReturnType<typeof getApiClient>,
  fileKey: string,
  format: string,
  outputDir: string
): Promise<void> {
  const spinner = ora('Extracting tokens...').start();

  try {
    const result = await api.extractTokens(fileKey, format || 'json');

    const filename = format === 'css' ? 'tokens.css' :
                     format === 'scss' ? '_tokens.scss' :
                     format === 'ts' ? 'tokens.ts' : 'tokens.json';

    const outputPath = join(outputDir, filename);
    writeFileSync(outputPath, result.formatted_output);

    spinner.succeed(`Extracted ${result.tokens_count} tokens`);
    console.log(chalk.dim(`  Output: ${outputPath}`));
  } catch (error) {
    spinner.fail('Failed to extract tokens');
    console.error(chalk.red(`  ${(error as Error).message}`));
  }
}

async function extractComponents(
  api: ReturnType<typeof getApiClient>,
  fileKey: string,
  outputDir: string
): Promise<void> {
  const spinner = ora('Extracting components...').start();

  try {
    const result = await api.extractComponents(fileKey);

    const outputPath = join(outputDir, 'components.json');
    writeFileSync(outputPath, JSON.stringify(result.components, null, 2));

    spinner.succeed(`Extracted ${result.components_count} components`);
    console.log(chalk.dim(`  Output: ${outputPath}`));

    // Show component summary
    console.log('');
    result.components.forEach(comp => {
      console.log(chalk.dim(`    - ${comp.name}`));
      if (comp.variants?.length) {
        console.log(chalk.dim(`      Variants: ${comp.variants.join(', ')}`));
      }
    });
  } catch (error) {
    spinner.fail('Failed to extract components');
    console.error(chalk.red(`  ${(error as Error).message}`));
  }
}

async function extractStyles(
  api: ReturnType<typeof getApiClient>,
  fileKey: string,
  outputDir: string
): Promise<void> {
  const spinner = ora('Extracting styles...').start();

  try {
    // Note: This would need a corresponding API endpoint
    // For now, we'll extract tokens which include style information
    const result = await api.extractTokens(fileKey, 'json');

    const outputPath = join(outputDir, 'styles.json');
    writeFileSync(outputPath, JSON.stringify(result.tokens, null, 2));

    spinner.succeed(`Extracted styles`);
    console.log(chalk.dim(`  Output: ${outputPath}`));
  } catch (error) {
    spinner.fail('Failed to extract styles');
    console.error(chalk.red(`  ${(error as Error).message}`));
  }
}
