'use client';

import { useEffect, useRef } from 'react';
import * as d3 from 'd3';

interface Service {
  name: string;
  span_count: number;
  error_count: number;
}

interface Dependency {
  source: string;
  target: string;
  call_count: number;
  error_count: number;
}

interface ServiceMapGraphProps {
  services: Service[];
  dependencies: Dependency[];
}

export function ServiceMapGraph({ services, dependencies }: ServiceMapGraphProps) {
  const svgRef = useRef<SVGSVGElement>(null);

  useEffect(() => {
    if (!svgRef.current || services.length === 0) return;

    const svg = d3.select(svgRef.current);
    svg.selectAll('*').remove();

    const width = svgRef.current.clientWidth;
    const height = svgRef.current.clientHeight;

    // Create nodes
    const nodes = services.map((s) => ({
      id: s.name,
      ...s,
    }));

    // Create links
    const links = dependencies.map((d) => ({
      ...d,
    }));

    // Force simulation
    const simulation = d3
      .forceSimulation(nodes as any)
      .force(
        'link',
        d3
          .forceLink(links)
          .id((d: any) => d.id)
          .distance(150)
      )
      .force('charge', d3.forceManyBody().strength(-400))
      .force('center', d3.forceCenter(width / 2, height / 2))
      .force('collision', d3.forceCollide().radius(60));

    // Arrow markers
    svg
      .append('defs')
      .append('marker')
      .attr('id', 'arrowhead')
      .attr('viewBox', '-0 -5 10 10')
      .attr('refX', 25)
      .attr('refY', 0)
      .attr('orient', 'auto')
      .attr('markerWidth', 8)
      .attr('markerHeight', 8)
      .append('path')
      .attr('d', 'M 0,-5 L 10,0 L 0,5')
      .attr('fill', '#4b5563');

    // Links
    const link = svg
      .append('g')
      .selectAll('line')
      .data(links)
      .enter()
      .append('line')
      .attr('stroke', (d: any) => (d.error_count > 0 ? '#ef4444' : '#4b5563'))
      .attr('stroke-width', (d: any) => Math.min(Math.log(d.call_count + 1) + 1, 4))
      .attr('stroke-opacity', 0.6)
      .attr('marker-end', 'url(#arrowhead)');

    // Link labels
    const linkLabels = svg
      .append('g')
      .selectAll('text')
      .data(links)
      .enter()
      .append('text')
      .attr('font-size', '10px')
      .attr('fill', '#9ca3af')
      .text((d: any) => d.call_count.toLocaleString());

    // Nodes
    const node = svg
      .append('g')
      .selectAll('g')
      .data(nodes)
      .enter()
      .append('g')
      .call(
        d3.drag<SVGGElement, any>()
          .on('start', (event, d) => {
            if (!event.active) simulation.alphaTarget(0.3).restart();
            d.fx = d.x;
            d.fy = d.y;
          })
          .on('drag', (event, d) => {
            d.fx = event.x;
            d.fy = event.y;
          })
          .on('end', (event, d) => {
            if (!event.active) simulation.alphaTarget(0);
            d.fx = null;
            d.fy = null;
          })
      );

    // Node circles
    node
      .append('circle')
      .attr('r', (d: any) => Math.min(Math.log(d.span_count + 1) * 5 + 20, 40))
      .attr('fill', (d: any) =>
        d.error_count > 0 ? 'rgba(239, 68, 68, 0.2)' : 'rgba(99, 102, 241, 0.2)'
      )
      .attr('stroke', (d: any) =>
        d.error_count > 0 ? '#ef4444' : '#6366f1'
      )
      .attr('stroke-width', 2);

    // Node labels
    node
      .append('text')
      .attr('text-anchor', 'middle')
      .attr('dy', 4)
      .attr('font-size', '12px')
      .attr('font-weight', '500')
      .attr('fill', '#e5e7eb')
      .text((d: any) => d.id.length > 15 ? d.id.slice(0, 15) + '...' : d.id);

    // Span count labels
    node
      .append('text')
      .attr('text-anchor', 'middle')
      .attr('dy', 18)
      .attr('font-size', '10px')
      .attr('fill', '#9ca3af')
      .text((d: any) => `${d.span_count.toLocaleString()} spans`);

    simulation.on('tick', () => {
      link
        .attr('x1', (d: any) => d.source.x)
        .attr('y1', (d: any) => d.source.y)
        .attr('x2', (d: any) => d.target.x)
        .attr('y2', (d: any) => d.target.y);

      linkLabels
        .attr('x', (d: any) => (d.source.x + d.target.x) / 2)
        .attr('y', (d: any) => (d.source.y + d.target.y) / 2);

      node.attr('transform', (d: any) => `translate(${d.x},${d.y})`);
    });

    return () => {
      simulation.stop();
    };
  }, [services, dependencies]);

  return (
    <svg
      ref={svgRef}
      className="w-full h-full"
      style={{ minHeight: '400px' }}
    />
  );
}
