// iOS SwiftUI emitter — consumes a DTCG token object and produces a single
// Swift file exposing semantic Colors, primitive spacing/radius as CGFloat, and
// primitive palette colors.

import { resolveRef } from './_token-ref.js';

const HEADER_VERSION = '7.0.0';

// Convert a dotted DTCG path to camelCase identifier.
// e.g. "semantic.color.action.primary" → "actionPrimary"
//      "primitive.color.brand.primary" → "brandPrimary"
//      "primitive.spacing.s0" → "spacingS0"
//      "primitive.radius.r0" → "radiusR0"
function camelFromPath(path) {
  const parts = path.split('.');
  // Drop leading "primitive"/"semantic" and the type bucket.
  // We keep meaningful parts.
  const trimmed = parts.slice(1); // drop primitive/semantic
  // Drop the type segment for semantic colors ("color.action.primary" → "action.primary")
  // For primitive colors ("color.brand.primary" → keep "brand.primary")
  // For primitive spacing ("spacing.s0") we want "spacingS0" — keep all.
  let segments;
  if (trimmed[0] === 'color' && trimmed.length >= 3) {
    segments = trimmed.slice(1);
  } else {
    segments = trimmed;
  }
  return segments
    .map((s, i) => (i === 0 ? s : s.charAt(0).toUpperCase() + s.slice(1)))
    .join('')
    .replace(/[^a-zA-Z0-9]/g, '');
}

// Convert "#rrggbb" or "#rgb" to "0xRRGGBB" for SwiftUI Color(hex:).
function hexToSwiftHex(hex) {
  if (typeof hex !== 'string') return null;
  let h = hex.trim().replace(/^#/, '');
  if (h.length === 3) {
    h = h.split('').map((c) => c + c).join('');
  }
  if (h.length === 6 && /^[0-9a-fA-F]{6}$/.test(h)) {
    return `0x${h.toUpperCase()}`;
  }
  if (h.length === 8 && /^[0-9a-fA-F]{8}$/.test(h)) {
    // drop alpha
    return `0x${h.slice(2).toUpperCase()}`;
  }
  return null;
}

function dimensionToNumber(value) {
  if (typeof value === 'number') return value;
  if (typeof value !== 'string') return null;
  const m = value.match(/^(-?\d+(?:\.\d+)?)(px|pt|rem|em)?$/);
  if (!m) return null;
  const n = parseFloat(m[1]);
  const unit = m[2];
  if (unit === 'rem' || unit === 'em') return n * 16;
  return n;
}

// Walk leaves of a subtree producing { path, token } pairs.
function* walkLeaves(node, prefix) {
  if (node == null || typeof node !== 'object') return;
  if ('$value' in node && '$type' in node) {
    yield { path: prefix, token: node };
    return;
  }
  for (const key of Object.keys(node)) {
    yield* walkLeaves(node[key], prefix ? `${prefix}.${key}` : key);
  }
}

export function formatIosSwiftUI(tokens) {
  const lines = [];
  const source = tokens?.$metadata?.source || '';
  lines.push(`// Generated by designlang v${HEADER_VERSION} — https://github.com/Manavarya09/design-extract`);
  if (source) lines.push(`// Source: ${source}`);
  lines.push('import SwiftUI');
  lines.push('');
  lines.push('extension Color {');
  lines.push('  init(hex: UInt32) {');
  lines.push('    let r = Double((hex >> 16) & 0xFF) / 255');
  lines.push('    let g = Double((hex >> 8) & 0xFF) / 255');
  lines.push('    let b = Double(hex & 0xFF) / 255');
  lines.push('    self.init(red: r, green: g, blue: b)');
  lines.push('  }');
  lines.push('');
  lines.push('  // MARK: Semantic');

  // Semantic colors
  const semanticColor = tokens?.semantic?.color;
  if (semanticColor) {
    for (const leaf of walkLeaves(semanticColor, 'semantic.color')) {
      if (leaf.token.$type !== 'color') continue;
      const resolved = resolveRef(tokens, leaf.path);
      const swiftHex = hexToSwiftHex(resolved);
      if (!swiftHex) continue;
      lines.push(`  static let ${camelFromPath(leaf.path)} = Color(hex: ${swiftHex})`);
    }
  }
  lines.push('}');
  lines.push('');

  // CGFloat spacing + radius
  lines.push('extension CGFloat {');
  lines.push('  // MARK: Primitive spacing');
  const spacing = tokens?.primitive?.spacing || {};
  for (const key of Object.keys(spacing)) {
    const tok = spacing[key];
    if (!tok || tok.$type !== 'dimension') continue;
    const n = dimensionToNumber(resolveRef(tokens, `primitive.spacing.${key}`));
    if (n == null) continue;
    const name = camelFromPath(`primitive.spacing.${key}`);
    lines.push(`  static let ${name}: CGFloat = ${n}`);
  }
  lines.push('');
  lines.push('  // MARK: Primitive radius');
  const radius = tokens?.primitive?.radius || {};
  for (const key of Object.keys(radius)) {
    const tok = radius[key];
    if (!tok || tok.$type !== 'dimension') continue;
    const n = dimensionToNumber(resolveRef(tokens, `primitive.radius.${key}`));
    if (n == null) continue;
    const name = camelFromPath(`primitive.radius.${key}`);
    lines.push(`  static let ${name}: CGFloat = ${n}`);
  }
  lines.push('}');
  lines.push('');

  // Primitive palette colors for direct use
  lines.push('// MARK: Primitive palette (for direct use)');
  lines.push('extension Color {');
  const primColor = tokens?.primitive?.color;
  if (primColor) {
    for (const leaf of walkLeaves(primColor, 'primitive.color')) {
      if (leaf.token.$type !== 'color') continue;
      const resolved = resolveRef(tokens, leaf.path);
      const swiftHex = hexToSwiftHex(resolved);
      if (!swiftHex) continue;
      lines.push(`  static let ${camelFromPath(leaf.path)} = Color(hex: ${swiftHex})`);
    }
  }
  lines.push('}');
  lines.push('');

  // Typography hint comments (composite typography tokens)
  const typography = tokens?.semantic?.typography;
  if (typography) {
    for (const key of Object.keys(typography)) {
      const tok = typography[key];
      if (!tok || tok.$type !== 'typography') continue;
      const v = tok.$value || {};
      lines.push(
        `// typography.${key}: family=${v.fontFamily ?? ''} size=${v.fontSize ?? ''} weight=${v.fontWeight ?? ''} lineHeight=${v.lineHeight ?? ''}`,
      );
    }
  }

  return lines.join('\n') + '\n';
}
