import { ComponentType } from '@/src/components/builder/config/componentRegistry';
import { BuilderService } from '@/src/services/BuilderService';
import { usePortfolioProjects } from '@/src/services/PortfolioProjectService';
import { usePortfolio } from '@/src/services/PortfolioService';
import { PortfolioElement } from '@/src/types/portfolio';
import { PortfolioProjectStatus } from '@prisma/client';
import { useParams } from 'next/navigation';
import { useState } from 'react';
import { BuilderSkeleton } from '../skeletons/BuilderSkeleton';
import { BuilderProvider } from './context/BuilderContext';
import { usePortfolioConfig } from './context/PortfolioConfigContext';
import { EditPanel } from './EditPanel';
import { PortfolioCanvas } from './PortfolioCanvas';
import { TopPanel } from './TopPanel';

export function Builder() {
  const { id } = useParams();
  const { isLoading: portfolioLoading, error: portfolioError, portfolio } = usePortfolio(id as string);
  const { updateConfig, config } = usePortfolioConfig();
  const [selectedElement, setSelectedElement] = useState<PortfolioElement | null>(null);
  const [isEditPanelOpen, setIsEditPanelOpen] = useState(false);
  const { projects, isLoading: portfolioProjectsLoading } = usePortfolioProjects(id as string);
  const isLoading = portfolioLoading || !config || portfolioProjectsLoading;

  const handleAddComponent = (
    index: number,
    componentType: ComponentType,
    initialProps?: Partial<PortfolioElement['props']>
  ) => {
    if (!config) return;
    const updatedProps = componentType.startsWith('project_') ? { projects: projects } : initialProps;
    const newConfig = BuilderService.addComponent(index, componentType, config, updatedProps);
    updateConfig(newConfig);
  };

  const handleAddToSection = (
    parentId: string,
    position: string,
    componentType: ComponentType,
    initialProps?: Partial<PortfolioElement['props']>,
    top?: boolean
  ) => {
    if (!config) return;
    const updatedProps = componentType.startsWith('project_') ? { projects: projects } : initialProps;
    const newConfig = BuilderService.addToSection(config, parentId, position, componentType, updatedProps, top);
    updateConfig(newConfig);
  };

  const handleElementUpdate = (id: string, newProps: Record<string, unknown>) => {
    if (!config) return;
    const newConfig = BuilderService.updateElementProps(config, id, newProps);
    updateConfig(newConfig);

    if (selectedElement && selectedElement.id === id) {
      setSelectedElement({
        ...selectedElement,
        props: newProps,
      });
    }
  };

  const handleElementRemove = (id: string) => {
    if (!config) return;
    const newConfig = BuilderService.removeElement(config, id);
    updateConfig(newConfig);
  };

  const handleElementMove = (id: string, direction: 'up' | 'down') => {
    if (!config) return;
    const newConfig = BuilderService.moveElement(config, id, direction);
    updateConfig(newConfig);
  };

  const handleElementSelect = (element: PortfolioElement) => {
    setSelectedElement(element);
    setTimeout(() => {
      setIsEditPanelOpen(true);
    }, 0);
  };

  const handleElementDeselect = () => {
    setSelectedElement(null);
  };

  const handleEditPanelToggle = () => {
    setIsEditPanelOpen(!isEditPanelOpen);
  };

  return (
    <>
      {isLoading && <BuilderSkeleton />}
      {portfolioError && <p>Error: {portfolioError?.message}</p>}
      {!isLoading && !portfolioError && portfolio && (
        <div className='flex flex-col min-h-screen bg-neutral-50 max-w-screen'>
          <TopPanel name={portfolio.title} portfolioId={id as string} />

          <div className='flex'>
            <div className='w-full builder'>
              <BuilderProvider
                value={{
                  onElementSelect: handleElementSelect,
                  onElementRemove: handleElementRemove,
                  onElementMove: handleElementMove,
                  onElementUpdate: handleElementUpdate,
                  onAddComponent: handleAddComponent,
                  onAddToSection: handleAddToSection,
                  selectedElementId: selectedElement?.id,
                  portfolioProjects: projects.filter((project) => project.status !== PortfolioProjectStatus.REJECTED),
                }}
              >
                <PortfolioCanvas elements={config?.elements ?? []} isPreview={false} />

                {selectedElement && (
                  <EditPanel
                    selectedElement={selectedElement}
                    onClose={handleElementDeselect}
                    isOpen={isEditPanelOpen}
                    onToggleOpen={handleEditPanelToggle}
                  />
                )}
              </BuilderProvider>
            </div>
          </div>
        </div>
      )}
    </>
  );
}
