import {AfterViewInit, Component, ElementRef, HostListener, inject, NgZone, OnDestroy, ViewChild} from '@angular/core';

@Component({
  selector: 'app-particles-background',
  imports: [],
  templateUrl: './particles-background.component.html',
  styleUrl: './particles-background.component.scss',
})
export class ParticleBackgroundComponent implements AfterViewInit, OnDestroy {
  @ViewChild('canvas', { static: true }) canvasRef!: ElementRef<HTMLCanvasElement>;

  private readonly ngZone = inject(NgZone);

  private ctx!: CanvasRenderingContext2D;
  private particles: any[] = [];
  private animationFrameId: number = 0;

  // --- Configuration ---
  private readonly numParticles = 80;
  private readonly maxDistance = 150;
  private readonly particleSpeed = 0.8;

  ngAfterViewInit(): void {
    const canvas = this.canvasRef.nativeElement;
    this.ctx = canvas.getContext('2d')!;

    this.resizeCanvas();
    this.initParticles();

    this.ngZone.runOutsideAngular(() => {
      this.animate();
    });
  }

  ngOnDestroy(): void {
    cancelAnimationFrame(this.animationFrameId);
  }

  @HostListener('window:resize')
  resizeCanvas(): void {
    const canvas = this.canvasRef.nativeElement;
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
  }

  private initParticles(): void {
    this.particles = [];
    const canvas = this.canvasRef.nativeElement;

    for (let i = 0; i < this.numParticles; i++) {
      this.particles.push({
        x: Math.random() * canvas.width,
        y: Math.random() * canvas.height,
        vx: (Math.random() - 0.5) * this.particleSpeed,
        vy: (Math.random() - 0.5) * this.particleSpeed,
        radius: Math.random() * 1.5 + 0.5
      });
    }
  }

  private readonly animate = (): void => {
    const canvas = this.canvasRef.nativeElement;

    this.ctx.clearRect(0, 0, canvas.width, canvas.height);

    for (let i = 0; i < this.numParticles; i++) {
      const p = this.particles[i];

      p.x += p.vx;
      p.y += p.vy;

      if (p.x < 0 || p.x > canvas.width) p.vx *= -1;
      if (p.y < 0 || p.y > canvas.height) p.vy *= -1;

      this.ctx.beginPath();
      this.ctx.arc(p.x, p.y, p.radius, 0, Math.PI * 2);
      this.ctx.fillStyle = 'rgba(120, 150, 170, 0.4)';
      this.ctx.fill();

      for (let j = i + 1; j < this.numParticles; j++) {
        const p2 = this.particles[j];

        const dx = p.x - p2.x;
        const dy = p.y - p2.y;
        const distance = Math.hypot(dx, dy);

        if (distance < this.maxDistance) {
          this.ctx.beginPath();
          this.ctx.moveTo(p.x, p.y);
          this.ctx.lineTo(p2.x, p2.y);

          const opacity = (1 - (distance / this.maxDistance)) * 0.5;
          this.ctx.strokeStyle = `rgba(120, 150, 170, ${opacity})`;
          this.ctx.lineWidth = 1;
          this.ctx.stroke();
        }
      }
    }

    this.animationFrameId = requestAnimationFrame(this.animate);
  };
}
