import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  ManyToOne,
  OneToMany,
  JoinColumn,
  CreateDateColumn,
  UpdateDateColumn,
  BeforeInsert,
  BeforeUpdate,
  AfterLoad
} from 'typeorm';

/**
 * Project Entity with Hierarchical Tree Structure
 * Uses Materialized Path pattern for efficient tree traversal
 */
@Entity('projects')
export class ProjectEntity {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({ type: 'varchar', length: 255 })
  name: string;

  @Column({ type: 'text', nullable: true })
  description: string;

  @Column({
    type: 'varchar',
    length: 20,
    default: 'active'
  })
  status: 'active' | 'on_hold' | 'completed' | 'archived';

  @Column({
    type: 'varchar',
    length: 1000,
    comment: 'Materialized path for tree structure (e.g., "0001.0002.0003")'
  })
  path: string;

  @Column({
    type: 'int',
    default: 0,
    comment: 'Depth level in the tree hierarchy'
  })
  level: number;

  @Column({ 
    type: 'uuid',
    nullable: true,
    name: 'parent_project'
  })
  parentId: string | null;

  @ManyToOne(() => ProjectEntity, project => project.children, {
    nullable: true,
    onDelete: 'CASCADE'
  })
  @JoinColumn({ name: 'parent_project' })
  parent: ProjectEntity | null;

  @OneToMany(() => ProjectEntity, project => project.parent)
  children: ProjectEntity[];

  @Column({ 
    type: 'varchar',
    length: 255,
    nullable: true,
    name: 'repository_url'
  })
  repositoryUrl: string | null;

  @Column({
    type: 'varchar',
    length: 50,
    nullable: true,
    name: 'bmad_workflow_type'
  })
  bmadWorkflowType: 'greenfield' | 'brownfield' | 'maintenance' | null;

  @Column({
    type: 'varchar',
    length: 255,
    nullable: true,
    name: 'task_master_project_id'
  })
  taskMasterProjectId: string | null;

  @Column({
    type: 'varchar',
    length: 20,
    default: 'medium'
  })
  priority: 'low' | 'medium' | 'high' | 'critical';

  @Column({ 
    type: 'date',
    nullable: true,
    name: 'start_date'
  })
  startDate: Date | null;

  @Column({ 
    type: 'date',
    nullable: true,
    name: 'due_date'
  })
  dueDate: Date | null;

  @Column({
    type: 'int',
    default: 0,
    name: 'completion_percentage'
  })
  completionPercentage: number;

  @Column({ 
    type: 'uuid',
    nullable: true,
    name: 'created_by'
  })
  createdBy: string | null;

  @Column({ 
    type: 'uuid',
    nullable: true,
    name: 'assigned_to'
  })
  assignedTo: string | null;

  @Column({
    type: 'simple-json',
    nullable: true
  })
  metadata: Record<string, any> | null;

  @Column({
    type: 'int',
    default: 0
  })
  sort: number;

  @CreateDateColumn({ name: 'date_created' })
  dateCreated: Date;

  @UpdateDateColumn({ name: 'date_updated' })
  dateUpdated: Date;

  // Computed properties
  private _ancestors: string[] = [];
  private _depth: number = 0;

  /**
   * Calculate ancestors from materialized path
   */
  @AfterLoad()
  calculateAncestors() {
    if (this.path) {
      const parts = this.path.split('.');
      this._ancestors = parts.slice(0, -1);
      this._depth = parts.length - 1;
    }
  }

  /**
   * Generate path for new nodes
   */
  @BeforeInsert()
  async generatePath() {
    if (!this.path && this.parentId) {
      // Path will be set by the service based on parent's path
      // This is a placeholder for the entity lifecycle
    }
  }

  /**
   * Update level based on path
   */
  @BeforeInsert()
  @BeforeUpdate()
  updateLevel() {
    if (this.path) {
      this.level = this.path.split('.').length - 1;
    }
  }

  /**
   * Get all ancestor IDs from the materialized path
   */
  getAncestorIds(): string[] {
    if (!this.path) return [];
    
    const parts = this.path.split('.');
    // Remove the last part (current node)
    return parts.slice(0, -1);
  }

  /**
   * Check if this project is an ancestor of another
   */
  isAncestorOf(other: ProjectEntity): boolean {
    if (!other.path || !this.path) return false;
    return other.path.startsWith(this.path + '.');
  }

  /**
   * Check if this project is a descendant of another
   */
  isDescendantOf(other: ProjectEntity): boolean {
    if (!this.path || !other.path) return false;
    return this.path.startsWith(other.path + '.');
  }

  /**
   * Get the next sibling path
   */
  getNextSiblingPath(): string {
    if (!this.path) return '0001';
    
    const parts = this.path.split('.');
    const lastPart = parts[parts.length - 1];
    const nextNumber = (parseInt(lastPart, 10) + 1).toString().padStart(4, '0');
    
    if (parts.length === 1) {
      return nextNumber;
    }
    
    return [...parts.slice(0, -1), nextNumber].join('.');
  }

  /**
   * Check if project is a root node
   */
  isRoot(): boolean {
    return !this.parentId && this.level === 0;
  }

  /**
   * Check if project is a leaf node (has no children)
   */
  isLeaf(): boolean {
    return !this.children || this.children.length === 0;
  }
}