import { Component, ViewChild, ElementRef, OnInit, OnDestroy, AfterViewInit, HostListener } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
import { SiteTreeservice } from '../SiteBuilderGrid/SiteTree.service';

interface Section {
  type: string;
  content: string;
}

interface Page {
  id: string; // Unique identifier for each page
  name: string;
  sections: Section[];
  children?: Page[];
  parent?: Page; // Reference to parent for easier navigation
}

@Component({
  selector: 'app-tree-node',
  templateUrl: './tree-node.component.html',
  styleUrls: ['./tree-node.component.css']
})
export class TreeNodeComponent implements OnInit, OnDestroy, AfterViewInit {
  // Canvas properties
  @ViewChild('canvasContainer') canvasContainer!: ElementRef;
  private destroy$ = new Subject<void>();
  
  // Grid movement properties
  private isDraggingCanvas = false;
  private startX = 0;
  private startY = 0;
  private panning = false;
  
  // Zoom properties
  currentScale = 1;
  private maxScale = 2;
  private minScale = 0.5;
  private scaleFactor = 0.1;
  
  // Grid position
  gridTranslateX = 0;
  gridTranslateY = 0;
  
  // Site structure data
  rootPage: Page | null = null;
  selectedPage: Page | null = null;
  selectedSection: Section | null = null;
  editMode: 'page' | 'section' | null = null;
  siteId: number = 0;
  loading = false;
  hasUnsavedChanges = false;
  
  // Section management
  availableSectionTypes: string[] = [];
  showOffcanvas = false;
  currentParentPage: Page | null = null;
  customSectionType = '';
  customSectionContent = '';
  
  // Adding child pages
  showAddChildModal = false;
  newPageName = '';
  currentParentForChild: Page | null = null;
  
  // For drag and drop
  draggedPage: Page | null = null;
  draggedSection: Section | null = null;
  dropTargetPage: Page | null = null;

  currentSectionIndex: number = -1;

  
  // Section templates with better descriptions
  sectionTemplates = [
    {
      type: 'Hero Header Section',
      description: 'Main banner with headline and CTA',
      content: 'Introduce the company and its mission, with a strong call-to-action to sign up or learn more.'
    },
    {
      type: 'Feature Section',
      description: 'Highlight product features with icons',
      content: 'Highlight the core features of the platform, such as project creation, technology selection, and wireframing.'
    },
    {
      type: 'Features List Section',
      description: 'Bulleted list of key features',
      content: 'Secure JWT-based login, Easy project management, and Technology choices for frontend and backend.'
    },
    {
      type: 'Benefits Section',
      description: 'Explain the benefits to users',
      content: 'Detail the benefits of using our platform including time savings, quality improvement, and better outcomes.'
    },
    {
      type: 'How It Works Section',
      description: 'Step-by-step process explanation',
      content: 'Explain the process of using our platform from signup to completion.'
    },
    {
      type: 'Testimonial Section',
      description: 'Customer quotes and reviews',
      content: 'Showcase customer testimonials to build trust and credibility.'
    },
    {
      type: 'CTA Section',
      description: 'Call-to-action buttons and form',
      content: 'Encourage visitors to sign up or contact for more information.'
    },
    {
      type: 'Gallery Section',
      description: 'Image gallery showcase',
      content: 'Display portfolio items, project screenshots, or other visual content.'
    },
    {
      type: 'Navbar',
      description: 'Top navigation bar',
      content: 'Site navigation with links to main sections.'
    },
    {
      type: 'Footer',
      description: 'Bottom site footer',
      content: 'Contact information, links, and copyright details.'
    }
  ];

  constructor(
    private siteTreeService: SiteTreeservice,
    private route: ActivatedRoute
  ) {}
  
  ngOnInit(): void {
    this.siteId = this.route.snapshot.params['id'];
    this.fetchSiteTree();
  }
  
  ngAfterViewInit(): void {
    this.initCanvasControls();
    
    // Set up touch events for mobile
    const canvas = this.canvasContainer.nativeElement;
    canvas.addEventListener('touchstart', this.handleTouchStart.bind(this));
    canvas.addEventListener('touchmove', this.handleTouchMove.bind(this));
    canvas.addEventListener('touchend', this.handleTouchEnd.bind(this));
    
    // Center grid after initial load
    setTimeout(() => {
      this.centerGrid();
    }, 500);
  }
  
  ngOnDestroy(): void {
    // Auto-save changes before component destruction
    if (this.hasUnsavedChanges) {
      this.saveTreeData(true);
    }
    
    this.destroy$.next();
    this.destroy$.complete();
  }
  
  // GRID MOVEMENT METHODS
  
  initCanvasControls(): void {
    const canvas = this.canvasContainer.nativeElement;
    
    // Mouse down event for dragging
    canvas.addEventListener('mousedown', (e: MouseEvent) => {
      // Only initiate drag if not clicking on interactive elements
      if ((e.target as HTMLElement).closest('.node-card, .node-header, button, input, select, textarea, .modal, .editor-form, .section-card, .add-button')) {
        return;
      }
      
      this.panning = true;
      this.startX = e.clientX - this.gridTranslateX;
      this.startY = e.clientY - this.gridTranslateY;
      canvas.style.cursor = 'grabbing';
      e.preventDefault();
    });
    
    // Mouse move for dragging the grid
    document.addEventListener('mousemove', (e: MouseEvent) => {
      if (!this.panning) return;
      
      // Calculate new position
      const newX = e.clientX - this.startX;
      const newY = e.clientY - this.startY;
      
      // Update position
      this.gridTranslateX = newX;
      this.gridTranslateY = newY;
      this.applyGridTransform();
    });
    
    // Mouse up to end dragging
    document.addEventListener('mouseup', () => {
      this.panning = false;
      canvas.style.cursor = 'grab';
    });
    
    // Mouse wheel for zooming
    canvas.addEventListener('wheel', (e: WheelEvent) => {
      e.preventDefault();
      
      // Calculate zoom based on wheel direction
      const delta = e.deltaY < 0 ? this.scaleFactor : -this.scaleFactor;
      const newScale = Math.min(this.maxScale, Math.max(this.minScale, this.currentScale + delta));
      
      // Get mouse position relative to canvas
      const rect = canvas.getBoundingClientRect();
      const mouseX = e.clientX - rect.left;
      const mouseY = e.clientY - rect.top;
      
      // Calculate zoom around mouse position
      this.zoomAtPoint(newScale, mouseX, mouseY);
    }, { passive: false });
  }
  
  // Touch event handlers for mobile devices
  handleTouchStart(e: TouchEvent): void {
    if (e.touches.length !== 1) return;
    
    const touch = e.touches[0];
    this.panning = true;
    this.startX = touch.clientX - this.gridTranslateX;
    this.startY = touch.clientY - this.gridTranslateY;
    e.preventDefault();
  }
  
  handleTouchMove(e: TouchEvent): void {
    if (!this.panning || e.touches.length !== 1) return;
    
    const touch = e.touches[0];
    this.gridTranslateX = touch.clientX - this.startX;
    this.gridTranslateY = touch.clientY - this.startY;
    this.applyGridTransform();
    e.preventDefault();
  }
  
  handleTouchEnd(): void {
    this.panning = false;
  }
  
  // Apply transform to the grid
  applyGridTransform(): void {
    const grid = document.querySelector('.sitemap-grid') as HTMLElement;
    if (!grid) return;
    
    grid.style.transform = `translate(${this.gridTranslateX}px, ${this.gridTranslateY}px) scale(${this.currentScale})`;
  }
  
  // Public method to get total transform for template binding
  getTotalTransform(): string {
    return `translate(${this.gridTranslateX}px, ${this.gridTranslateY}px) scale(${this.currentScale})`;
  }
  
  // Zoom at a specific point
  zoomAtPoint(newScale: number, x: number, y: number): void {
    if (newScale === this.currentScale) return;
    
    // Calculate offset change to zoom at mouse position
    const scaleFactor = newScale / this.currentScale;
    const dx = x - x * scaleFactor;
    const dy = y - y * scaleFactor;
    
    // Apply new position and scale
    this.gridTranslateX = this.gridTranslateX * scaleFactor + dx;
    this.gridTranslateY = this.gridTranslateY * scaleFactor + dy;
    this.currentScale = newScale;
    
    this.applyGridTransform();
  }
  
  // Center the grid in the viewport
  centerGrid(): void {
    const canvas = this.canvasContainer.nativeElement;
    const grid = document.querySelector('.tree-grid') as HTMLElement;
    const rootNode = document.querySelector('.home-node') as HTMLElement;
    
    if (!canvas || !grid) {
      setTimeout(() => this.centerGrid(), 100);
      return;
    }
    
    const canvasRect = canvas.getBoundingClientRect();
    const gridRect = grid.getBoundingClientRect();
    
    // Calculate scale to fit content within the fixed box
    const scaleX = canvasRect.width / gridRect.width * 0.2;
    const scaleY = canvasRect.height / gridRect.height * 0.2;
    const scale = Math.min(Math.max(this.minScale, Math.min(scaleX, scaleY)), 1);
    
    // Position the grid - centered horizontally, but align top of tree with top of viewport
    this.currentScale = scale;
    this.gridTranslateX = -700; // Set left position to -900px
    
    // Position vertically to place root node near top with some padding
    const topPadding = 50; // Pixels from top of viewport
    if (rootNode) {
      const rootRect = rootNode.getBoundingClientRect();
      const rootOffsetY = (rootRect.top - gridRect.top) * 0.9;
      this.gridTranslateY = topPadding - rootOffsetY;
    } else {
      // Fallback if root node not found
      this.gridTranslateY = topPadding;
    }
    
    this.applyGridTransform();
  }
  
  // ZOOM CONTROL METHODS
  
  zoomIn(): void {
    const canvas = this.canvasContainer.nativeElement;
    const rect = canvas.getBoundingClientRect();
    const centerX = rect.width / 2;
    const centerY = rect.height / 2;
    
    const newScale = Math.min(this.maxScale, this.currentScale + this.scaleFactor);
    this.zoomAtPoint(newScale, centerX, centerY);
  }
  
  zoomOut(): void {
    const canvas = this.canvasContainer.nativeElement;
    const rect = canvas.getBoundingClientRect();
    const centerX = rect.width / 2;
    const centerY = rect.height / 2;
    
    const newScale = Math.max(this.minScale, this.currentScale - this.scaleFactor);
    this.zoomAtPoint(newScale, centerX, centerY);
  }
  
  resetZoom(): void {
    this.centerGrid();
  }
  
  // TREE DATA METHODS
  
  fetchSiteTree(): void {
    this.loading = true;
    this.siteTreeService.getById(this.siteId).subscribe({
      next: (res) => {
        this.loading = false;
        // Parse and unwrap
        const raw = typeof res.model === 'string' ? JSON.parse(res.model) : res.model;
        const rootTitle = raw.title || 'Site Structure';
        const pagesObj = raw.data?.Children || raw.Children || raw.data || raw;
        this.processSiteData( pagesObj,rootTitle);
      },
      error: () => {
        this.loading = false;
        this.createDefaultStructure();
      }
    });
  }
  
  // Create a default structure
  createDefaultStructure(): void {
    const defaultData = {
      "Home": {
        "Navbar": {},
        "Hero Header Section": "Introduce the company and its mission, with a strong call-to-action to sign up or learn more.",
        "Feature Section": "Highlight the core features of the platform.",
        "CTA Section": "Encourage visitors to sign up or contact for more information.",
        "Footer": {}
      }
    };
    this.processSiteData(defaultData);
  }
  
  processSiteData(pagesObj: any, rootTitle?: string): void {
    // Initialize root with dynamic title
    this.rootPage = { id: 'root', name: rootTitle, sections: [], children: [] };
    this.availableSectionTypes = [];
    this.hasUnsavedChanges = false;
    let idCounter = 0;

    // Recursive builder
    const buildPages = (obj: any, parent?: Page): Page[] => {
      return Object.keys(obj || {}).map(key => {
        const pageData = obj[key] || {};
        const page: Page = {
          id: `page-${++idCounter}`,
          name: key,
          sections: [],
          children: [],
          parent
        };
        // Sections: all props except Children
        Object.keys(pageData).forEach(prop => {
          if (prop !== 'Children') {
            const val = pageData[prop];
            page.sections.push({
              type: prop,
              content: Array.isArray(val)
                ? val.join('\n')
                : typeof val === 'object'
                ? JSON.stringify(val, null, 2)
                : String(val)
            });
            if (!this.availableSectionTypes.includes(prop)) {
              this.availableSectionTypes.push(prop);
            }
          }
        });
        // Recurse into Children
        if (pageData.Children) {
          page.children = buildPages(pageData.Children, page);
        }
        return page;
      });
    };

    this.rootPage.children = buildPages(pagesObj, this.rootPage);
    setTimeout(() => this.centerGrid(), 100);
  }
  
  createPageFromData(pageName: string, pageData: any, idPrefix: string): Page {
    const page: Page = {
      id: idPrefix,
      name: pageName,
      sections: [],
      children: []
    };
    
    // Extract sections
    if (pageData) {
      // Process properties as sections
      Object.keys(pageData).forEach(key => {
        if (key !== 'Children') {
          const value = pageData[key];
          
          // Add to available section types if not already included
          if (!this.availableSectionTypes.includes(key)) {
            this.availableSectionTypes.push(key);
          }
          
          // Handle different value types
          if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
            // Object value
            page.sections.push({
              type: key,
              content: Object.keys(value).length > 0 ? JSON.stringify(value, null, 2) : ''
            });
          } else if (Array.isArray(value)) {
            // Array value
            page.sections.push({
              type: key,
              content: value.join('\n')
            });
          } else {
            // String or primitive value
            page.sections.push({
              type: key,
              content: String(value)
            });
          }
        }
      });
      
      // Process children recursively if the Children key exists
      if (pageData.Children) {
        let childId = 0;
        Object.keys(pageData.Children).forEach(childName => {
          const childData = pageData.Children[childName];
          const childPage = this.createPageFromData(childName, childData, `${idPrefix}-child-${++childId}`);
          childPage.parent = page;
          page.children?.push(childPage);
        });
      }
    }
    
    return page;
  }
  
  // Generate output JSON from tree structure
  generateOutputJson(): any {
    const output: any = {};
    
    if (this.rootPage?.children) {
      this.rootPage.children.forEach(page => {
        output[page.name] = this.convertPageToJsonObject(page);
      });
    }
    
    return output;
  }
  
  convertPageToJsonObject(page: Page): any {
    const pageObj: any = {};
    
    // Add sections
    page.sections.forEach(section => {
      try {
        // Check if content is an array (line breaks)
        if (section.content.includes('\n')) {
          pageObj[section.type] = section.content.split('\n');
        } else {
          // Try to parse JSON content for objects
          const parsedContent = JSON.parse(section.content);
          pageObj[section.type] = parsedContent;
        }
      } catch (e) {
        // If parsing fails, use the raw content
        pageObj[section.type] = section.content;
      }
    });
    
    // Add children
    if (page.children && page.children.length > 0) {
      pageObj.Children = {};
      
      page.children.forEach(childPage => {
        pageObj.Children[childPage.name] = this.convertPageToJsonObject(childPage);
      });
    }
    
    return pageObj;
  }
  
  // PAGE AND SECTION MANAGEMENT
  
  selectPage(page: Page): void {
    this.selectedPage = page;
    this.selectedSection = null;
  }
  
  selectSection(section: Section): void {
    this.selectedSection = section;
    this.editMode = 'section';
  }
  
  // Show modal to add a child page
  showAddChildPageModal(parent: Page): void {
    this.currentParentForChild = parent;
    this.newPageName = '';
    this.showAddChildModal = true;
  }
  
  // Add a child page
  addChildPage(): void {
    if (this.currentParentForChild && this.newPageName) {
      if (!this.currentParentForChild.children) {
        this.currentParentForChild.children = [];
      }
      
      const newPage: Page = {
        id: `page-${Date.now()}`,
        name: this.newPageName,
        sections: [],
        children: [],
        parent: this.currentParentForChild
      };
      
      this.currentParentForChild.children.push(newPage);
      this.hasUnsavedChanges = true;
      this.closeAddChildModal();
      
      // Auto-select the new page
      this.selectPage(newPage);
    }
  }
  
  closeAddChildModal(): void {
    this.showAddChildModal = false;
    this.currentParentForChild = null;
    this.newPageName = '';
  }
  
  // Delete a page
  deletePage(page: Page, event: Event): void {
    event.stopPropagation();
    
    if (!page.parent || !page.parent.children) return;
    
    if (confirm(`Are you sure you want to delete "${page.name}" and all its children?`)) {
      const index = page.parent.children.indexOf(page);
      if (index !== -1) {
        page.parent.children.splice(index, 1);
        
        if (this.selectedPage === page) {
          this.selectedPage = null;
          this.editMode = null;
        }
        
        this.hasUnsavedChanges = true;
      }
    }
  }
  
  // Format section content as HTML with colored text
  getSectionContentHtml(content: string): string {
    if (!content) return '';
    
    // Replace line breaks with <br> for proper display
    return content.replace(/\n/g, '<br>');
  }
  
  // Show add section offcanvas
  openSectionOffcanvas(page: Page, sectionIndex: number = -1, event?: Event): void {
    if (event) {
      event.stopPropagation();
    }
    this.currentParentPage = page;
    this.currentSectionIndex = sectionIndex;
    this.customSectionType = '';
    this.customSectionContent = '';
    this.showOffcanvas = true;
  }
  
  // Close the offcanvas
  closeOffcanvas(): void {
    this.showOffcanvas = false;
    this.currentParentPage = null;
    this.currentSectionIndex = -1;
  }
  
  // Add section from a template
  addSectionFromTemplate(template: any): void {
    if (this.currentParentPage) {
      const newSection: Section = {
        type: template.type,
        content: template.content
      };
      
      // Insert at specific position if provided, otherwise add to end
      if (this.currentSectionIndex >= 0) {
        this.currentParentPage.sections.splice(this.currentSectionIndex + 1, 0, newSection);
      } else {
        this.currentParentPage.sections.push(newSection);
      }
      
      if (!this.availableSectionTypes.includes(template.type)) {
        this.availableSectionTypes.push(template.type);
      }
      
      this.hasUnsavedChanges = true;
      this.closeOffcanvas();
    }
  }
  
  // Add custom section
 
// Similar update for addCustomSection
addCustomSection(): void {
  if (this.currentParentPage && this.customSectionType) {
    const newSection: Section = {
      type: this.customSectionType,
      content: this.customSectionContent || ''
    };
    
    // Insert at specific position if provided, otherwise add to end
    if (this.currentSectionIndex >= 0) {
      this.currentParentPage.sections.splice(this.currentSectionIndex + 1, 0, newSection);
    } else {
      this.currentParentPage.sections.push(newSection);
    }
    
    if (!this.availableSectionTypes.includes(this.customSectionType)) {
      this.availableSectionTypes.push(this.customSectionType);
    }
    
    this.hasUnsavedChanges = true;
    this.closeOffcanvas();
  }
}
  
  // Edit section
  editSection(section: Section, event: Event): void {
    event.stopPropagation();
    this.selectedSection = section;
    this.editMode = 'section';
  }
  
  // Cancel edit
  cancelEdit(): void {
    this.editMode = null;
    this.selectedSection = null;
  }
  
  // Save edit
  saveEdit(): void {
    this.editMode = null;
    this.hasUnsavedChanges = true;
  }
  
  // Delete section
  deleteSection(section: Section, page: Page, event: Event): void {
    event.stopPropagation();
    
    if (confirm(`Are you sure you want to delete this "${section.type}" section?`)) {
      const index = page.sections.indexOf(section);
      if (index !== -1) {
        page.sections.splice(index, 1);
        
        if (this.selectedSection === section) {
          this.selectedSection = null;
          this.editMode = null;
        }
        
        this.hasUnsavedChanges = true;
      }
    }
  }
  
  // DRAG AND DROP METHODS
  
  // Handle page drag start
  onPageDragStart(page: Page): void {
    this.draggedPage = page;
  }
  
  // Handle page drag end
  onPageDragEnd(): void {
    this.draggedPage = null;
    this.dropTargetPage = null;
  }
  
  // Handle page drop
  onPageDrop(targetPage: Page): void {
    if (!this.draggedPage || this.draggedPage === targetPage) return;
    
    // Remove from current parent
    if (this.draggedPage.parent && this.draggedPage.parent.children) {
      const sourceIndex = this.draggedPage.parent.children.indexOf(this.draggedPage);
      if (sourceIndex > -1) {
        this.draggedPage.parent.children.splice(sourceIndex, 1);
      }
    }
    
    // Add to new parent
    if (!targetPage.children) {
      targetPage.children = [];
    }
    
    // Update parent reference
    this.draggedPage.parent = targetPage;
    targetPage.children.push(this.draggedPage);
    
    this.hasUnsavedChanges = true;
  }
  
  // Handle section drag drop
  onSectionDrop(event: CdkDragDrop<Section[]>): void {
    if (event.previousContainer === event.container) {
      // Reordering within the same page
      moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
    } else {
      // Moving to a different page
      transferArrayItem(
        event.previousContainer.data,
        event.container.data,
        event.previousIndex,
        event.currentIndex
      );
    }
    
    this.hasUnsavedChanges = true;
  }
  
  // UI HELPER METHODS
  
  getNodeIcon(page: Page): string {
    if (page.name.toLowerCase() === 'home') {
      return 'fas fa-home';
    } else if (page.children && page.children.length > 0) {
      return 'fas fa-folder-open';
    } else {
      return 'fas fa-file';
    }
  }
  
  // Save tree data
  saveTreeData(silent: boolean = false): void {
    const outputData = this.generateOutputJson();
    const jsonData = JSON.stringify(outputData, null, 2);
    
    if (this.siteId) {
      this.loading = true;
      
      this.siteTreeService.update(this.siteId, { 
        id: this.siteId, 
        model: jsonData 
      }).subscribe({
        next: () => {
          this.loading = false;
          this.hasUnsavedChanges = false;
          
          if (!silent) {
            alert('Site structure saved successfully');
          }
        },
        error: (err) => {
          this.loading = false;
          console.error('Error saving data:', err);
          
          if (!silent) {
            alert('Failed to save site structure');
          }
        }
      });
    }
  }
  
  @HostListener('window:beforeunload', ['$event'])
  beforeUnloadHandler(event: BeforeUnloadEvent): void {
    if (this.hasUnsavedChanges) {
      event.preventDefault();
      event.returnValue = 'You have unsaved changes. Are you sure you want to leave?';
    }
  }
  
  @HostListener('window:resize')
  onWindowResize(): void {
    this.centerGrid();
  }
}
