import { Logger } from "~/utils/logger.js";
import {GradientConverter} from "~/utils/gradient.js"

export { FigmaToDSLConverter, convertFigmaToDSL, parseFigmaJSON };
export type { FigmaNode, DSLNode, GlobalStyles };

interface FigmaNode {
  id: string;
  name: string;
  type: string;
  layout?: string;
  fills?: string ;
  effects?: string;
  borderRadius?: string;
  text?: string;
  textStyle?: string;
  children?: FigmaNode[];
  opacity?:number
  componentId?: string; 
  strokes?: string | any;
}

interface GlobalStyles {
  [key: string]: any;
}

interface DSLNode {
  type: string;
  attrs: Record<string, any>;
  children?: DSLNode[];
}

class FigmaToDSLConverter {
  private counter: number = 0;
  private globalStyles: GlobalStyles;
  private currentTimestamp: string;
  private nodeCache: Map<string, DSLNode> = new Map();

  constructor(globalStyles: GlobalStyles) {
    this.globalStyles = globalStyles;
    this.currentTimestamp = Date.now().toString().slice(-6);
  }

  public convertRoot(nodes: FigmaNode[]): DSLNode {
    if (!nodes || nodes.length === 0) {
      throw new Error('No nodes provided');
    }

    // 假设第一个节点是根节点
    const rootNode = nodes[0];
    return this.convertNode(null,rootNode);
  }

  private convertNode(parentNode:DSLNode | any,node: FigmaNode): DSLNode {
    // 检查缓存
    const cacheKey = this.generateCacheKey(node);
    if (this.nodeCache.has(cacheKey)) {
      return this.nodeCache.get(cacheKey)!;
    }

    const dslNode: DSLNode = {
      type: this.mapNodeType(node.type),
      attrs: this.extractAttributes(parentNode,node),
    };
    if(dslNode.type && dslNode.attrs.flexDirection){
        const type = dslNode.type;
        const flexDirection = dslNode.attrs.flexDirection;
        if(type!=flexDirection){
            dslNode.type = flexDirection;
        }
    }
    delete dslNode.attrs.flexDirection;
    if (node.children && node.children.length > 0) {
      const children = this.convertChildren(dslNode,node.children);
      // 如果有 gap 信息，应用到子节点
      if (dslNode.attrs.gap && dslNode.type) { 
        dslNode.children = this.applyGapToChildren(
          children, 
          dslNode.attrs.gap, 
          dslNode.type
        );
        // 移除临时的 gap 属性
        delete dslNode.attrs.gap;
      } else {
        dslNode.children = children;
      }
      //处理圆角
      // this.handleBorderRadius(parentNode,dslNode);
    }


    // 缓存结果
    this.nodeCache.set(cacheKey, dslNode);
    return dslNode;
  }


private handleBorderRadius(parentNode:DSLNode,node:DSLNode){
    const { attrs: pAttrs } = parentNode || {};
    const { attrs: dAttrs } = node;
    const hasNoBorderRadius = !dAttrs.borderRadius && 
        !dAttrs.borderLeftTopRadius && 
        !dAttrs.borderRightTopRadius && 
        !dAttrs.borderLeftBottomRadius && 
        !dAttrs.borderRightBottomRadius;
    const hasBackground = dAttrs.background || dAttrs.backgroundColor;
    const sameSize = dAttrs.width === pAttrs?.width && dAttrs.height === pAttrs?.height;
    if (pAttrs && hasNoBorderRadius && hasBackground && sameSize) {
        // 复制所有圆角属性
        const radiusProps = ['borderRadius', 'borderLeftTopRadius', 'borderRightTopRadius', 
                            'borderLeftBottomRadius', 'borderRightBottomRadius'];
        
        radiusProps.forEach(prop => {
            if (pAttrs[prop]) {
                dAttrs[prop] = pAttrs[prop];
            }
        });
    }

}
  // 新增方法：处理子节点的 gap
private applyGapToChildren(children: DSLNode[], gap: number, layoutMode: string): DSLNode[] {
  if (!children || children.length === 0 || gap <= 0) {
    return children;
  }

  return children.map((child, index) => {
    // 如果是最后一个子元素，不设置间距
    if (index === 0) {
      return child;
    }
    
    if (layoutMode === 'row') {
      // 行布局：设置右边距
      child.attrs.marginLeft = gap;
    } else if (layoutMode === 'column') {
      // 列布局：设置下边距
      child.attrs.marginTop = gap;
    }
    // Logger.error("layoutMode: "+layoutMode+" , gap："+gap+" , child: "+child);
    return child;
  });
}

  private convertChildren(parentNode:DSLNode,children: FigmaNode[]): DSLNode[] {
    const filterNodes = children.filter(child => child.type !== "GROUP");
    return filterNodes.map(child => this.convertNode(parentNode,child));
  }

  private generateCacheKey(node: FigmaNode): string {
    return `${node.id}_${node.type}_${node.layout || ''}_${node.textStyle || ''}`;
  }

  private mapNodeType(originalType: string): string {
    const typeMap: Record<string, string> = {
      'FRAME': 'column',
      'RECTANGLE': 'Image',
      'TEXT': 'Text',
      'INSTANCE': 'Image',
      'GROUP': 'GROUP',
      'BOOLEAN_OPERATION': 'column',
      'ELLIPSE': 'column',
      'IMAGE-SVG': 'column'
    };

    return typeMap[originalType] || 'div';
  }

  private extractAttributes(parentNode:DSLNode | any,node: FigmaNode): Record<string, any> {
    const attrs: Record<string, any> = {
      name: this.generateName(node)
    };

    // 按优先级顺序提取属性
    try{
      this.extractLayoutAttributes(parentNode,node, attrs);
    }catch (error) {
      Logger.error(error);
      throw new Error('extractLayoutAttributes: ');
    }
     try{
      this.extractTextAttributes(node, attrs);
    }catch (error) {
      Logger.error(error);
      throw new Error('extractTextAttributes: ');
    }
    
    try{
      this.extractFillAttributes(node, attrs);
    } catch (error) {
      Logger.error(error);
      throw new Error('extractFillAttributes: ');
    }
    try{
      this.extractBorderAttributes(node, attrs);
    } catch (error) {
      Logger.error(error);
      throw new Error('extractBorderAttributes: ');
    }
     try{
      this.extractEffectAttributes(node, attrs);
    } catch (error) {
      Logger.error(error);
      throw new Error('extractEffectAttributes: ');
    }
    try{
      this.extractSpecialAttributes(parentNode,node, attrs);
    } catch (error) {
      Logger.error(error);
      throw new Error('extractSpecialAttributes: ');
    }

    return this.normalizeAttributes(attrs);
  }

  private extractLayoutAttributes(parentNode:DSLNode | any,node: FigmaNode, attrs: Record<string, any>): void {
    if (!node.layout || !this.globalStyles[node.layout]) return;

    const layoutStyle = this.globalStyles[node.layout];
    
    // 尺寸处理
    if (layoutStyle.dimensions) {
        if(layoutStyle.dimensions.width){
            attrs.width = Math.round(layoutStyle.dimensions.width);
        }
        if(layoutStyle.dimensions.height){
            attrs.height = Math.round(layoutStyle.dimensions.height);
        }
    }
    // attrs.mode_ = layoutStyle.mode
    // 位置处理
    if (layoutStyle.locationRelativeToParent) {
      attrs.position = 'absolute';
      attrs.left = Math.round(layoutStyle.locationRelativeToParent.x);
      attrs.top = Math.round(layoutStyle.locationRelativeToParent.y);
      // const isshowPosition = this.shouldUseAbsolutePosition(parentNode,node,layoutStyle);
      // if(!isshowPosition){
      //   delete attrs.position;
      //   delete attrs.left;
      //   delete attrs.top;
      // }
    } else if (layoutStyle.position) {
      attrs.position = layoutStyle.position;
    }

    // 布局方向和对齐
    if (layoutStyle.mode) {
      this.handleLayoutMode(layoutStyle, attrs);
    }

    // 内边距处理
    if (layoutStyle.padding) {
      this.handlePadding(layoutStyle.padding, attrs);
    }

    // 间距处理
    if (layoutStyle.gap) {
      this.handleGap(node,layoutStyle, attrs);
    }
  }

    /**
   * 判断元素是否需要绝对定位
   */
  private shouldUseAbsolutePosition(parentNode:DSLNode | any,node: FigmaNode, globalStyles: GlobalStyles): boolean {
    if (!parentNode) return true;
    if(node.type=="TEXT"){
      Logger.error("shouldUseAbsolutePosition: "+parentNode.type+" , "+node.text+" , "+globalStyles.locationRelativeToParent);
      // 规则1: 检查父容器是否为 Flexbox 布局
      if(parentNode.type=="row" || parentNode.type=="column"){
        return false;
      }
      
      // 规则3: 检查是否有明确的相对定位需求
      const needsExplicitPositioning = this.needsExplicitPositioning(globalStyles);
      return needsExplicitPositioning;
    }else{
      return true;
    }
    
  }

 /**
   * 判断是否需要显式定位
   */
  private needsExplicitPositioning(globalStyles: GlobalStyles): boolean {
    // 有明确的相对父级位置信息，且不是 Flexbox 子元素
    if (globalStyles.locationRelativeToParent && 
        globalStyles.locationRelativeToParent.x !== 0 && 
        globalStyles.locationRelativeToParent.y !== 0) {
      return true;
    }
    // 装饰性元素或需要重叠的元素
    if (globalStyles.mode === 'none' && 
        globalStyles.sizing?.horizontal === 'fixed' && 
        globalStyles.sizing?.vertical === 'fixed') {
      return true;
    }
    return false;
  }

  private handleLayoutMode(layoutStyle: any, attrs: Record<string, any>): void {
    const mode = layoutStyle.mode;
    if (mode === 'row' || mode === 'column') {
      attrs.flexDirection = mode === 'row' ? 'row' : 'column';
    }

    if (layoutStyle.alignItems) {
      attrs.alignItems = this.mapAlignItems(layoutStyle.alignItems);
    }

    if (layoutStyle.justifyContent) {
      attrs.justifyContent = this.mapJustifyContent(layoutStyle.justifyContent);
    }
    if (layoutStyle.marginLeft !== undefined && layoutStyle.marginLeft !== null) {
      attrs.marginLeft = layoutStyle.marginLeft;
    }
    if (layoutStyle.marginTop !== undefined && layoutStyle.marginTop !== null) {
      attrs.marginTop = layoutStyle.marginTop;
    }
  }

  private handlePadding(padding: string, attrs: Record<string, any>): void {
    const paddingValues = padding.split(' ').map(val => parseInt(val));
    
    if (paddingValues.length === 1) {
      attrs.padding = paddingValues[0];
    } else if (paddingValues.length === 2) {
      attrs.paddingTop = paddingValues[0];
      attrs.paddingBottom = paddingValues[0];
      attrs.paddingRight = paddingValues[1];
      attrs.paddingLeft = paddingValues[1];
    } else if (paddingValues.length === 4) {
      attrs.paddingTop = paddingValues[0];
      attrs.paddingRight = paddingValues[1];
      attrs.paddingBottom = paddingValues[2];
      attrs.paddingLeft = paddingValues[3];
    }
  }

  private handleGap(node: FigmaNode,layoutStyle: any, attrs: Record<string, any>): void {
    const gapValue = parseInt(layoutStyle.gap);
    if (!isNaN(gapValue)) {
    //   if (layoutStyle.mode === 'row') {
    //     attrs.marginRight = gapValue;
    //   } else if (layoutStyle.mode === 'column') {
    //     attrs.marginBottom = gapValue;
    //   }
        attrs.gap = gapValue;
    }
  }

  private extractTextAttributes(node: FigmaNode, attrs: Record<string, any>): void {
    if (node.text) {
      attrs.text = node.text;
    }

    if (!node.textStyle || !this.globalStyles[node.textStyle]) return;

    const textStyle = this.globalStyles[node.textStyle];
    
    if (textStyle.fontSize) {
      attrs.fontSize = Math.round(textStyle.fontSize);
    }

    if (textStyle.fontWeight) {
    
      if(textStyle.fontWeight > 400){
        attrs.textStyle = "bold";
      }
      delete attrs.fontWeight
    }

    if (textStyle.fontFamily) {
      attrs.typeface = textStyle.fontFamily;
    }

    if (textStyle.textLineHeight) {
      attrs.lineHeight = this.parseLineHeight(textStyle.textLineHeight);
    }

    if (textStyle.textAlignHorizontal) {
      attrs.textAlign = this.mapTextAlign(textStyle.textAlignHorizontal);
    }

    if (textStyle.letterSpacing) {
      attrs.letterSpacing = this.parseLetterSpacing(textStyle.letterSpacing);
    }
  }

  private extractFillAttributes(node: FigmaNode, attrs: Record<string, any>): void {
    if (!node.fills) return;
     if (!node.fills || !this.globalStyles[node.fills]) return;
    const layoutFills = this.globalStyles[node.fills];
    if(this.mapNodeType(node.type)=="Text"){
        if (Array.isArray(layoutFills)) {
            const firstFill = layoutFills[0];
            if (typeof firstFill === 'string') {
                attrs.textColor = this.normalizeColor(firstFill);
            } else if (firstFill && typeof firstFill === 'object') {
                if (firstFill.colors && Array.isArray(firstFill.colors)) {
                    attrs.textColor = this.normalizeColor(firstFill.colors[0]);
                }else if(firstFill.type == "GRADIENT_LINEAR" && firstFill.gradient){
                    attrs.textColor = GradientConverter.convertToCustomFormat(firstFill.gradient)
                }

            }
        } else if (typeof layoutFills === 'string') {
            attrs.textColor = this.normalizeColor(node.fills);
        }
    }else{
        if (Array.isArray(layoutFills)) {
            const firstFill = layoutFills[0];
            if (typeof firstFill === 'string') {
                attrs.backgroundColor = this.normalizeColor(firstFill);
            } else if (firstFill && typeof firstFill === 'object') {
                this.handleComplexFill(firstFill, attrs);
            }
        } else if (typeof layoutFills === 'string') {
            attrs.backgroundColor = this.normalizeColor(node.fills);
        }

    }
    
  }

  private handleComplexFill(fill: any, attrs: Record<string, any>): void {
    if (fill.type === 'GRADIENT_LINEAR' && fill.gradient) {
      attrs.background = GradientConverter.convertToCustomFormat(fill.gradient);
    }
    if (fill.type == "IMAGE" && fill.src) {
      attrs.src = fill.src;
    } 
    if (fill.colors && Array.isArray(fill.colors)) {
      attrs.backgroundColor = this.normalizeColor(fill.colors[0]);
    }
  }

  private extractBorderAttributes(node: FigmaNode, attrs: Record<string, any>): void {
    if (node.borderRadius) {
      const radius = parseInt(node.borderRadius);
      if (!isNaN(radius)) {
        attrs.borderRadius = Math.round(radius);
      }
    }

    if (node.strokes) {
      this.handleStrokes(node, attrs);
    }
  }
  
  /**
   * 获取figma strokes属性
   * @param node 
   * @param attrs 
   * @returns 
   */
  private handleStrokes(node: any, attrs: Record<string, any>): void {
    if (!node.strokes) return;
     if (!node.strokes || !this.globalStyles[node.strokes]) return;
    const strokes = this.globalStyles[node.strokes];
    if (typeof strokes === 'object' && strokes.colors) {
      attrs.borderColor = this.normalizeColor(strokes.colors[0]);
      if (strokes.strokeWeight) {
        const weight = parseFloat(strokes.strokeWeight);
        if (!isNaN(weight)) {
          attrs.borderWidth = weight;
        }

      }
    }
  }

  private extractEffectAttributes(node: FigmaNode, attrs: Record<string, any>): void {
    if (!node.effects || !this.globalStyles[node.effects]) return;

    const effectStyle = this.globalStyles[node.effects];
    
    // if (effectStyle.boxShadow) {
    //   attrs.boxShadow = effectStyle.boxShadow;
    // }

    // if (effectStyle.backdropFilter) {
    //   attrs.backdropFilter = effectStyle.backdropFilter;
    // }
  }

  private extractSpecialAttributes(parentNode:DSLNode | any,node: FigmaNode, attrs: Record<string, any>): void {
    // Logger.error("opacity:"+node.opacity);
    if (node.opacity !== undefined) {
      //去掉opacity 属性
      // attrs.opacity = Math.round(attrs.opacity * 100) / 100;
      if(attrs.backgroundColor){
          attrs.backgroundColor =  this.colorWithOpacitySimple(attrs.backgroundColor,node.opacity);
      }
       if(attrs.textColor){
          attrs.textColor =  this.colorWithOpacitySimple(attrs.textColor,node.opacity);
      }
    }
    //文字居中问题：
    if(node.type == "TEXT"){
      // Logger.error("nodeType: "+attrs.text+" , "+attrs.height)
      if((parentNode && parentNode.attrs && parentNode.attrs.height) && attrs.height){
          if(attrs.height >= parentNode.attrs.height){ 
             delete attrs.height
            //  parentNode.attrs.alignItems = "center";
            // // 缓存结果
            // const key = this.generateCacheKey(parentNode);
            // this.nodeCache.set(key, parentNode);
          }
          // 子元素宽高大于容器宽高时，则去掉子容器的宽高属性 
        if(parentNode && parentNode.attrs && parentNode.attrs.width && attrs.width){
          if(attrs.width >= parentNode.attrs.width){
                delete attrs.width
          }
        }
      }
    }
    

    // if(attrs.position && parentNode && parentNode.attrs && parentNode.attrs.mode_ == "none"){
    //     delete attrs.position
    //     delete attrs.left;
    //     delete attrs.top
    // }
  }


  private colorWithOpacitySimple(color: string, opacity: number): string {
  if (opacity < 0 || opacity > 1) {
    throw new Error('Opacity must be between 0 and 1');
  }
  
  const alpha = Math.round(opacity * 255);
  const alphaHex = alpha.toString(16).padStart(2, '0').toUpperCase();
  
  if (color.startsWith('#')) {
    const hex = color.replace('#', '');
    const fullHex = hex.length === 3 ? 
      hex.split('').map(c => c + c).join('') : hex;
    
    if (fullHex.length === 6) {
      return `#${fullHex}${alphaHex}`;
    }
  }
  
  if (color.startsWith('rgb')) {
    const match = color.match(/(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/);
    if (match) {
      const [_, r, g, b] = match;
      const rHex = parseInt(r).toString(16).padStart(2, '0');
      const gHex = parseInt(g).toString(16).padStart(2, '0');
      const bHex = parseInt(b).toString(16).padStart(2, '0');
      return `#${rHex}${gHex}${bHex}${alphaHex}`.toUpperCase();
    }
  }
  
  throw new Error('Unsupported color format');
}

  private generateName(node: FigmaNode): string {
    this.counter++;
    return `${this.currentTimestamp}_${this.mapNodeType(node.type)}_${this.counter}`;
  }

  private normalizeColor(color: any): string {
    if(typeof color === 'object' && color){
      if(color.type == "GRADIENT_LINEAR"){
        return GradientConverter.convertToCustomFormat(color.gradient)
      }
    }else {
       if (color.startsWith('rgba')) {
      const rgbaRegex = /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*([\d.]+)\s*)?\)/i;
      const match = color.match(rgbaRegex);
      // Logger.logA("normalizeColor: "+color+" , match："+match);
      if (match) {
        // const r = parseInt(match[1],10);
        // const g = parseInt(match[2],10);
        // const b = parseInt(match[3],10);
        // const a = Math.round(parseFloat(match[4]) * 255);
        return color;//`#${this.toHex(r)}${this.toHex(g)}${this.toHex(b)}${this.toHex(a)}`;
      }
      } else if (color.startsWith('rgb')) {
          return color;
      //   const match = color.match(/rgb$$(\d+),\s*(\d+),\s*(\d+)$$/);
      //   if (match) {
      //     const r = parseInt(match[1]);
      //     const g = parseInt(match[2]);
      //     const b = parseInt(match[3]);
      //     return `#${this.toHex(r)}${this.toHex(g)}${this.toHex(b)}`;
      //   }
      }
      
    }
    return color.startsWith('#') ? color : '#000000';
  }

  private toHex(value: number): string {
    return value.toString(16).padStart(2, '0').toUpperCase();
  }
  
  private parseLineHeight(lineHeight: string): number {
    // if ( lineHeight.includes('em')) {
    //   const emValue = parseFloat(lineHeight.replace("em","")) * 16
    //   return !isNaN(emValue) ? Math.round(emValue * 100) : 100;
    // }
    return parseInt(lineHeight);
  }
 


  private parseLetterSpacing(letterSpacing: string): number {
    if (letterSpacing.includes('%')) {
      const percentValue = parseFloat(letterSpacing) / 100;
      return parseFloat(percentValue.toFixed(2));
    }
    return parseFloat(letterSpacing) || 0;
  }

  private mapAlignItems(alignment: string): string {
    const alignmentMap: Record<string, string> = {
      'center': 'center',
      'flex-start': 'flex-start',
      'flex-end': 'flex-end',
      'stretch': 'stretch'
    };
    return alignmentMap[alignment] || 'flex-start';
  }

  private mapJustifyContent(justify: string): string {
    const justifyMap: Record<string, string> = {
      'center': 'center',
      'flex-start': 'flex-start',
      'flex-end': 'flex-end',
      'space-between': 'space-between',
      'space-around': 'space-around'
    };
    return justifyMap[justify] || 'flex-start';
  }

  private mapTextAlign(alignment: string): string {
    const alignmentMap: Record<string, string> = {
      'LEFT': 'left',
      'CENTER': 'center',
      'RIGHT': 'right',
      'JUSTIFY': 'justify'
    };
    return alignmentMap[alignment] || 'left';
  }

  private normalizeAttributes(attrs: Record<string, any>): Record<string, any> {
    const normalized: Record<string, any> = {};
    
    for (const [key, value] of Object.entries(attrs)) {
      if (typeof value === 'number') {
        normalized[key] = Math.round(value);
      } else if (key === 'letterSpacing' && typeof value === 'string' && value.includes('%')) {
        normalized[key] = this.parseLetterSpacing(value);
      } else {
        normalized[key] = value;
      }
    }

    return normalized;
  }
}

// 高性能转换函数
function convertFigmaToDSL(nodes: FigmaNode[], globalStyles: GlobalStyles): DSLNode {
  const converter = new FigmaToDSLConverter(globalStyles);
  return converter.convertRoot(nodes);
}

// 工具函数：解析Figma JSON
function parseFigmaJSON(jsonString: string): { nodes: FigmaNode[], globalStyles: GlobalStyles } {
  try {
    const data = JSON.parse(jsonString);
    return {
      nodes: data.nodes || [],
      globalStyles: data.globalVars?.styles || {}
    };
  } catch (error) {
    throw new Error('Invalid JSON format');
  }
}
