import React, { useEffect, useRef, useState, useCallback } from "react";
import * as d3 from "d3";
import apiService from "../../lib/api";
import { useAuth } from "../../contexts/auth-context";

const API_BASE_URL =
  import.meta.env.VITE_API_URL || "https://inogen-back.pelekan.org/api";

export interface Node {
  id: string;
  label: string;
  category: string;
  stageid: number;
  imageUrl?: string;
  x?: number;
  y?: number;
  fx?: number | null;
  fy?: number | null;
  isCenter?: boolean;
  rawData?: any;
}

export interface Link {
  source: string;
  target: string;
}

export interface CompanyDetails {
  id: string;
  label: string;
  category: string;
  stageid: number;
  fields: {
    F: string;
    N: string;
    V: string;
    T: number;
    U: string;
    S: boolean;
  }[];
  description?: string;
}

export interface NetworkGraphProps {
  onNodeClick?: (node: CompanyDetails) => void;
  onLoadingChange?: (loading: boolean) => void;
}

function parseApiResponse(raw: any): any[] {
  let data = raw;
  try {
    if (typeof data === "string") data = JSON.parse(data);
    if (typeof data === "string") data = JSON.parse(data);
  } catch {}
  return Array.isArray(data) ? data : [];
}

function isBrowser(): boolean {
  return typeof window !== "undefined";
}

export function NetworkGraph({ onNodeClick, onLoadingChange }: NetworkGraphProps) {
  const svgRef = useRef<SVGSVGElement | null>(null);
  const [nodes, setNodes] = useState<Node[]>([]);
  const [links, setLinks] = useState<Link[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [isMounted, setIsMounted] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const { token } = useAuth();

  useEffect(() => {
    if (isBrowser()) {
      const timer = setTimeout(() => setIsMounted(true), 100);
      return () => clearTimeout(timer);
    }
  }, []);

  const getImageUrl = useCallback(
    (stageid: number) => {
      if (!token?.accessToken) return null;
      return `${API_BASE_URL}/getimage?stageID=${stageid}&nameOrID=image&token=${token.accessToken}`;
    },
    [token?.accessToken],
  );

  const callAPI = useCallback(async (stage_id: number) => {
    return await apiService.call<any>({
      get_values_workflow_function: {
        stage_id: stage_id,
      },
    });
  }, []);

  useEffect(() => {
    if (!isMounted) return;

    let aborted = false;
    const controller = new AbortController();

    (async () => {
      setIsLoading(true);
      try {
        const res = await apiService.call<any[]>({
          graph_production_function: {},
        });
        if (aborted) return;

        const data = parseApiResponse(JSON.parse(res.data)?.graph_production);
        console.log(
          "All available fields in first item:",
          Object.keys(data[0] || {}),
        );

        // نود مرکزی
        const centerNode: Node = {
          id: "center",
          label: "پتروشیمی بندر امام",
          category: "center",
          stageid: 0,
          isCenter: true,
        };

        // دسته‌بندی‌ها
        const categories = Array.from(new Set(data.map((item: any) => item.category)));

        const categoryNodes: Node[] = categories.map((cat, index) => ({
          id: `cat-${index}`,
          label: cat,
          category: cat,
          stageid: -1,
        }));

        // نودهای نهایی
        const finalNodes: Node[] = data.map((item: any) => ({
          id: `node-${item.stageid}`,
          label: item.title,
          category: item.category,
          stageid: item.stageid,
          imageUrl: getImageUrl(item.stageid),
          rawData: item,
        }));

        // لینک‌ها: مرکز → دسته‌بندی‌ها → نودهای نهایی
        const graphLinks: Link[] = [
          ...categoryNodes.map((cat) => ({ source: "center", target: cat.id })),
          ...finalNodes.map((node) => {
            const catIndex = categories.indexOf(node.category);
            return { source: `cat-${catIndex}`, target: node.id };
          }),
        ];

        setNodes([centerNode, ...categoryNodes, ...finalNodes]);
        setLinks(graphLinks);
      } catch (err: any) {
        if (err.name !== "AbortError") {
          console.error("Failed to fetch graph data:", err);
          setError("Failed to load graph data");
          setNodes([]);
          setLinks([]);
        }
      } finally {
        if (!aborted) setIsLoading(false);
      }
    })();

    return () => {
      aborted = true;
      controller.abort();
    };
  }, [isMounted, token, getImageUrl]);

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

    const svg = d3.select(svgRef.current);
    const width = svgRef.current.clientWidth;
    const height = svgRef.current.clientHeight;
    svg.selectAll("*").remove();

    const defs = svg.append("defs");

    const filter = defs
      .append("filter")
      .attr("id", "glow")
      .attr("x", "-50%")
      .attr("y", "-50%")
      .attr("width", "200%")
      .attr("height", "200%");

    filter
      .append("feGaussianBlur")
      .attr("stdDeviation", "3")
      .attr("result", "coloredBlur");

    const feMerge = filter.append("feMerge");
    feMerge.append("feMergeNode").attr("in", "coloredBlur");
    feMerge.append("feMergeNode").attr("in", "SourceGraphic");

    const container = svg.append("g");

    const zoom = d3
      .zoom<SVGSVGElement, unknown>()
      .scaleExtent([0.3, 2.5])
      .on("zoom", (event) => container.attr("transform", event.transform));

    svg.call(zoom);

    const categoryToColor: Record<string, string> = {
      دانشگاه: "#3B82F6",
      مشاور: "#10B981",
      "دانش بنیان": "#F59E0B",
      استارتاپ: "#EF4444",
      شرکت: "#8B5CF6",
      صندوق: "#06B6D4",
      شتابدهنده: "#9333EA",
      "مرکز نوآوری": "#F472B6",
      center: "#34D399",
    };

    const simulation = d3
      .forceSimulation<Node>(nodes)
      .force(
        "link",
        d3
          .forceLink<Node, Link>(links)
          .id((d) => d.id)
          .distance(150)
          .strength(0.2),
      )
      .force("charge", d3.forceManyBody().strength(-300))
      .force("center", d3.forceCenter(width / 2, height / 2))
      .force("radial", d3.forceRadial(d => d.isCenter ? 0 : 300, width/2, height/2))
      .force("collision", d3.forceCollide().radius((d) => (d.isCenter ? 50 : 35)));

    // Initial zoom to show entire graph
    const initialScale = 0.6;
    const initialTranslate = [
      width / 2 - (width / 2) * initialScale,
      height / 2 - (height / 2) * initialScale,
    ];
    svg.call(
      zoom.transform,
      d3.zoomIdentity
        .translate(initialTranslate[0], initialTranslate[1])
        .scale(initialScale),
    );

    // Fix center node
    const centerNode = nodes.find(n => n.isCenter);
    const categoryNodes = nodes.filter(n => !n.isCenter && n.stageid === -1);
    
    if (centerNode) {
      const centerX = width / 2;
      const centerY = height / 2;
      centerNode.fx = centerX;
      centerNode.fy = centerY;
    
      const baseRadius = 450; // شعاع پایه
      const variation = 100; // تغییر طول یکی در میان
      const angleStep = (2 * Math.PI) / categoryNodes.length;
    
      categoryNodes.forEach((catNode, i) => {
        const angle = i * angleStep;
        const radius = baseRadius + (i % 2 === 0 ? -variation : variation);
        catNode.fx = centerX + radius * Math.cos(angle);
        catNode.fy = centerY + radius * Math.sin(angle);
      });
    }
    
    // نودهای نهایی **هیچ fx/fy نداشته باشند**
    // فقط forceLink آن‌ها را به دسته‌ها متصل نگه می‌دارد
    
    
// const finalNodes = nodes.filter(n => !n.isCenter && n.stageid !== -1);

// categoryNodes.forEach((catNode) => {
//   const childNodes = finalNodes.filter(n => n.category === catNode.category);
//   const childCount = childNodes.length;
//   const radius = 100; // فاصله از دسته
//   const angleStep = (2 * Math.PI) / childCount;

//   childNodes.forEach((node, i) => {
//     const angle = i * angleStep;
//     node.fx = catNode.fx! + radius * Math.cos(angle);
//     node.fy = catNode.fy! + radius * Math.sin(angle);
//   });
// });


    // Curved links
    const link = container
      .selectAll(".link")
      .data(links)
      .enter()
      .append("path")
      .attr("class", "link")
      .attr("stroke", "#E2E8F0")
      .attr("stroke-width", 2)
      .attr("stroke-opacity", 0.6)
      .attr("fill", "none");

    const nodeGroup = container
      .selectAll(".node")
      .data(nodes)
      .enter()
      .append("g")
      .attr("class", "node")
      .style("cursor", "pointer");

    const drag = d3
      .drag<SVGGElement, Node>()
      .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);
        if (!d.isCenter) {
          d.fx = null;
          d.fy = null;
        }
      });

    nodeGroup.call(drag);

    nodeGroup.each(function (d) {
      const group = d3.select(this);

      if (d.isCenter) {
        const rect = group
          .append("rect")
          .attr("width", 200)
          .attr("height", 80)
          .attr("x", -100) // نصف عرض جدید منفی
          .attr("y", -40)  // نصف ارتفاع جدید منفی
          .attr("rx", 8)
          .attr("ry", 8)
          .attr("fill", categoryToColor[d.category] || "#94A3B8")
          .attr("stroke", "#FFFFFF")
          .attr("stroke-width", 3)
          .style("pointer-events", "none");

        if (d.imageUrl || d.isCenter) {
          const pattern = defs
            .append("pattern")
            .attr("id", `image-${d.id}`)
            .attr("x", 0)
            .attr("y", 0)
            .attr("width", 1)
            .attr("height", 1);

          pattern
            .append("image")
            .attr("x", 0)
            .attr("y", 0)
            .attr("width", 200)  // ← هم‌اندازه با مستطیل
            .attr("height", 80)
            .attr("href", d.isCenter ? "/main-circle.png" : d.imageUrl)
            .attr("preserveAspectRatio", "xMidYMid slice");

          rect.attr("fill", `url(#image-${d.id})`);
        }
      } else {
        const circle = group
          .append("circle")
          .attr("r", 25)
          .attr("fill", categoryToColor[d.category] || "#fff")
          .attr("stroke", "#FFFFFF")
          .attr("stroke-width", 3);

        if (d.imageUrl) {
          const pattern = defs
            .append("pattern")
            .attr("id", `image-${d.id}`)
            .attr("x", 0)
            .attr("y", 0)
            .attr("width", 1)
            .attr("height", 1);

          pattern
            .append("image")
            .attr("x", 0)
            .attr("y", 0)
            .attr("width", 50)
            .attr("height", 50)
            .attr("href", d.imageUrl)
            .attr("preserveAspectRatio", "xMidYMid slice");

          defs
            .append("clipPath")
            .attr("id", `clip-${d.id}`)
            .append("circle")
            .attr("r", 25);

          circle
            .attr("fill", `url(#image-${d.id})`)
            .attr("clip-path", `url(#clip-${d.id})`);
        }
      }
    });

    const labels = nodeGroup
      .append("text")
      .text((d) => d.label)
      .attr("text-anchor", "middle")
      .attr("dy", (d) => (d.isCenter ? 50 : 45))
      .attr("font-size", (d) => (d.isCenter ? "14px" : "12px"))
      .attr("font-weight", "bold")
      .attr("fill", "#F9FAFB")
      .attr("stroke", "rgba(17, 24, 39, 0.95)")
      .attr("stroke-width", 4)
      .attr("paint-order", "stroke");

    nodeGroup
      .on("mouseenter", function (event, d) {
        if (d.isCenter) return;
        d3.select(this)
          .select(d.isCenter ? "rect" : "circle")
          .attr("filter", "url(#glow)")
          .transition()
          .duration(200)
          .attr("stroke", "#3B82F6")
          .attr("stroke-width", 4);
      })
      .on("mouseleave", function (event, d) {
        d3.select(this)
          .select(d.isCenter ? "rect" : "circle")
          .attr("filter", null)
          .transition()
          .duration(200)
          .attr("stroke", "#FFFFFF")
          .attr("stroke-width", 3);
      });

    nodeGroup.on("click", async function (event, d) {
      event.stopPropagation();
      if (d.isCenter) return;

      if (onNodeClick && d.stageid) {
        // Open dialog immediately with basic info
        const basicDetails: CompanyDetails = {
          id: d.id,
          label: d.label,
          category: d.category,
          stageid: d.stageid,
          fields: [],
        };
        onNodeClick(basicDetails);
        
        // Start loading
        onLoadingChange?.(true);
        
        try {
          const res = await callAPI(d.stageid);
          const responseData = JSON.parse(res.data);
          const fieldValues =
            JSON.parse(responseData?.getvalue)?.[0]?.FieldValues || [];

          const filteredFields = fieldValues.filter(
            (field: any) =>
              !["image", "img", "full_name", "about_collaboration"].includes(
                field.F.toLowerCase(),
              ),
          );

          const descriptionField = fieldValues.find(
            (field: any) =>
              field.F.toLowerCase().includes("description") ||
              field.F.toLowerCase().includes("about_collaboration") ||
              field.F.toLowerCase().includes("about"),
          );

          const companyDetails: CompanyDetails = {
            id: d.id,
            label: d.label,
            category: d.category,
            stageid: d.stageid,
            fields: filteredFields,
            description: descriptionField?.V || undefined,
          };

          onNodeClick(companyDetails);
        } catch (error) {
          console.error("Failed to fetch company details:", error);
          // Keep the basic details already shown
        } finally {
          // Stop loading
          onLoadingChange?.(false);
        }
      }
    });

    simulation.on("tick", () => {
      link.attr("d", (d: any) => {
        const sx = (d.source as Node).x!;
        const sy = (d.source as Node).y!;
        const tx = (d.target as Node).x!;
        const ty = (d.target as Node).y!;
        const dx = tx - sx;
        const dy = ty - sy;
        const dr = Math.sqrt(dx * dx + dy * dy) * 1.2; // منحنی
        return `M${sx},${sy}A${dr},${dr} 0 0,1 ${tx},${ty}`;
      });

      nodeGroup.attr("transform", (d) => `translate(${d.x},${d.y})`);
    });

    return () => {
      simulation.stop();
    };
  }, [nodes, links, isLoading, isMounted, onNodeClick, callAPI]);

  if (error) {
    return (
      <div className="w-full h-full flex items-center justify-center bg-gradient-to-br from-gray-900 to-gray-800">
        <div className="text-center p-8 bg-black bg-opacity-50 rounded-lg border border-gray-700">
          <div className="text-red-400 text-lg font-persian mb-4">
            ⚠️ خطای بارگذاری
          </div>
          <div className="text-gray-300 font-persian text-sm">{error}</div>
        </div>
      </div>
    );
  }

  if (!isMounted) {
    return (
      <div className="w-full h-full flex items-center justify-center bg-transparent">
        <div className="text-white font-persian text-sm">
          در حال بارگذاری...
        </div>
      </div>
    );
  }

  if (isLoading) {
    return (
      <div className="w-full h-full relative bg-transparent">
        <div className="w-full h-full flex items-center justify-center relative">
          <div className="w-12 h-12 rounded-lg bg-gray-600 animate-pulse relative z-10">
            <div className="absolute inset-0 rounded-lg bg-gradient-to-r from-gray-500 to-gray-600 animate-pulse"></div>
          </div>

          {Array.from({ length: 8 }).map((_, i) => {
            const angle = (i * 2 * Math.PI) / 8;
            const radius = 120;
            const x = Math.cos(angle) * radius;
            const y = Math.sin(angle) * radius;

            return (
              <div
                key={i}
                className="absolute w-8 h-8 rounded-full bg-gray-600 animate-pulse"
                style={{
                  left: `calc(50% + ${x}px - 16px)`,
                  top: `calc(50% + ${y}px - 16px)`,
                  animationDelay: `${i * 200}ms`,
                }}
              >
                <div className="w-full h-full rounded-full bg-gradient-to-r from-gray-500 to-gray-600 animate-pulse"></div>
                <div
                  className="absolute w-16 h-3 bg-gray-600 rounded animate-pulse"
                  style={{
                    transform: `rotate(${(i * 360) / 8}deg) translateX(32px)`,
                    transformOrigin: "left center",
                  }}
                ></div>
              </div>
            );
          })}
        </div>
      </div>
    );
  }

  return (
    <div className="w-full h-full">
      <svg
        ref={svgRef}
        className="w-full h-full bg-transparent"
        style={{ cursor: "grab" }}
      />
    </div>
  );
}


export default NetworkGraph;