import { type CssNode, walk } from 'css-tree';

/**
 * Intentionally only resolves `*` and `/` operations without dealing with parenthesis, because this is the only thing required to run Tailwind v4
 */
export function resolveCalcExpressions(node: CssNode) {
  walk(node, {
    visit: 'Function',
    enter(func, funcListItem) {
      if (func.name === 'calc') {
        /*
          [
            { type: 'Dimension', loc: null, value: '0.25', unit: 'rem' },
            { type: 'Operator', loc: null, value: '*' },
            { type: 'Number', loc: null, value: '2' }
            { type: 'Percentage', loc: null, value: '2' }
          ]
        */
        func.children.forEach((child, item) => {
          const left = item.prev;
          const right = item.next;
          if (
            left &&
            right &&
            child.type === 'Operator' &&
            (left.data.type === 'Dimension' ||
              left.data.type === 'Number' ||
              left.data.type === 'Percentage') &&
            (right.data.type === 'Dimension' ||
              right.data.type === 'Number' ||
              right.data.type === 'Percentage')
          ) {
            if (child.value === '*' || child.value === '/') {
              const value = (() => {
                if (child.value === '*') {
                  return String(
                    Number.parseFloat(left.data.value) *
                      Number.parseFloat(right.data.value),
                  );
                }
                if (right.data.value === '0') {
                  return '0';
                }
                return String(
                  Number.parseFloat(left.data.value) /
                    Number.parseFloat(right.data.value),
                );
              })();
              if (
                left.data.type === 'Dimension' &&
                right.data.type === 'Number'
              ) {
                item.data = {
                  type: 'Dimension',
                  unit: left.data.unit,
                  value,
                };
                func.children.remove(left);
                func.children.remove(right);
              } else if (
                left.data.type === 'Number' &&
                right.data.type === 'Dimension'
              ) {
                item.data = {
                  type: 'Dimension',
                  unit: right.data.unit,
                  value,
                };
                func.children.remove(left);
                func.children.remove(right);
              } else if (
                left.data.type === 'Number' &&
                right.data.type === 'Number'
              ) {
                item.data = {
                  type: 'Number',
                  value,
                };
                func.children.remove(left);
                func.children.remove(right);
              } else if (
                left.data.type === 'Dimension' &&
                right.data.type === 'Dimension' &&
                left.data.unit === right.data.unit
              ) {
                if (child.value === '/') {
                  item.data = {
                    type: 'Number',
                    value,
                  };
                } else {
                  item.data = {
                    type: 'Dimension',
                    unit: left.data.unit,
                    value,
                  };
                }
                func.children.remove(left);
                func.children.remove(right);
              } else if (
                left.data.type === 'Percentage' &&
                right.data.type === 'Number'
              ) {
                item.data = {
                  type: 'Percentage',
                  value,
                };
                func.children.remove(left);
                func.children.remove(right);
              } else if (
                left.data.type === 'Number' &&
                right.data.type === 'Percentage'
              ) {
                item.data = {
                  type: 'Percentage',
                  value,
                };
                func.children.remove(left);
                func.children.remove(right);
              } else if (
                left.data.type === 'Percentage' &&
                right.data.type === 'Percentage'
              ) {
                if (child.value === '/') {
                  item.data = {
                    type: 'Number',
                    value,
                  };
                } else {
                  item.data = {
                    type: 'Percentage',
                    value,
                  };
                }
                func.children.remove(left);
                func.children.remove(right);
              }
            }
          }
        });
        if (func.children.size === 1 && func.children.first) {
          funcListItem.data = func.children.first;
        }
      }
    },
  });
}
