import { PortfolioElement } from '@/src/types/portfolio';
import { ComponentType } from '@/src/components/builder/config/componentRegistry';
import { defaultProps } from '@/src/components/builder/config/defaultProps';

export class ElementService {
  static createElement(
    componentType: ComponentType,
    id?: string,
    position?: string,
    initialProps?: Partial<PortfolioElement['props']>
  ): PortfolioElement {
    const elementId = id ?? `${componentType}-${Date.now()}`;

    const newElement: PortfolioElement = {
      id: elementId,
      layout: componentType,
      props: { ...defaultProps[componentType], ...(initialProps || {}) },
    };

    if (position) {
      newElement.props = { ...newElement.props, position };
    }

    return newElement;
  }

  static updateProps(
    elements: PortfolioElement[],
    elementId: string,
    newProps: PortfolioElement['props']
  ): PortfolioElement[] {
    return elements.map((element) => {
      if (element.id === elementId) {
        return { ...element, props: { ...element.props, ...newProps } };
      }

      if (element.props?.children) {
        return {
          ...element,
          props: {
            ...element.props,
            children: this.updateProps(element.props.children as PortfolioElement[], elementId, newProps),
          },
        };
      }

      return element;
    });
  }

  static removeElement(elements: PortfolioElement[], elementId: string): PortfolioElement[] {
    const filteredElements = elements.filter((element) => element.id !== elementId);

    return filteredElements.map((element) => {
      if (element.props?.children) {
        return {
          ...element,
          props: {
            ...element.props,
            children: this.removeElement(element.props.children as PortfolioElement[], elementId),
          },
        };
      }
      return element;
    });
  }

  static moveElement(elements: PortfolioElement[], elementId: string, direction: 'up' | 'down'): PortfolioElement[] {
    const index = elements.findIndex((element) => element.id === elementId);
    if (index === -1) {
      return elements.map((element) => {
        if (element.props?.children) {
          return {
            ...element,
            props: {
              ...element.props,
              children: this.moveElement(element.props.children as PortfolioElement[], elementId, direction),
            },
          };
        }
        return element;
      });
    }

    if (direction === 'up' && index === 1 && elements[0]?.layout.startsWith('header_')) {
      return elements;
    }

    if (direction === 'up' && index === 0) return elements;
    if (direction === 'down' && index === elements.length - 1) return elements;

    const newElements = [...elements];
    const targetIndex = direction === 'up' ? index - 1 : index + 1;

    [newElements[index], newElements[targetIndex]] = [newElements[targetIndex], newElements[index]];

    return newElements;
  }

  static addToSection(
    elements: PortfolioElement[],
    sectionId: string,
    newElement: PortfolioElement,
    top?: boolean
  ): PortfolioElement[] {
    return elements.map((element) => {
      if (element.id === sectionId) {
        const children = Array.isArray(element.props.children) ? [...element.props.children] : [];
        const index = top ? 0 : children.length;
        children.splice(index, 0, newElement);
        return { ...element, props: { ...element.props, children } };
      }
      return element;
    });
  }

  static addElementAtIndex(
    index: number,
    componentType: ComponentType,
    elements?: PortfolioElement[],
    initialProps?: Partial<PortfolioElement['props']>
  ): PortfolioElement[] {
    const elems = elements || [];
    const newElement = this.createElement(componentType, undefined, undefined, initialProps);
    return [...elems.slice(0, index), newElement, ...elems.slice(index)];
  }
}
