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

// Get API base URL at module level to avoid process.env access in browser
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;
}

// Helper to robustly parse backend response
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 : [];
}

// Check if we're in browser environment
function isBrowser(): boolean {
  return typeof window !== "undefined";
}

export function NetworkGraph({ onNodeClick }: 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();

  // Ensure component only renders on client side
  useEffect(() => {
    if (isBrowser()) {
      const timer = setTimeout(() => setIsMounted(true), 100);
      return () => clearTimeout(timer);
    }
  }, []);

  // Fetch data from API
  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] || {}),
        );

        // Create center node
        const centerNode: Node = {
          id: "center",
          label: "", //مرکز زیست بوم
          category: "center",
          stageid: 0,
          isCenter: true,
        };

        // Create ecosystem nodes
        const ecosystemNodes: Node[] = data.map((item: any) => ({
          id: String(item.stageid),
          label: item.title,
          category: item.category,
          stageid: item.stageid,
          imageUrl: getImageUrl(item.stageid),
          rawData: item,
        }));

        // Create links (all nodes connected to center)
        const graphLinks: Link[] = ecosystemNodes.map((node) => ({
          source: "center",
          target: node.id,
        }));

        setNodes([centerNode, ...ecosystemNodes]);
        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]);

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

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

  // Initialize D3 graph
  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;

    // Clear previous content
    svg.selectAll("*").remove();

    // Create defs for patterns and filters
    const defs = svg.append("defs");

    // Add glow filter for hover effect
    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");

    // Create zoom behavior
    const zoom = d3
      .zoom<SVGSVGElement, unknown>()
      .scaleExtent([0.8, 2.5]) // Limit zoom out to 1x, zoom in to 2.5x
      .on("zoom", (event) => {
        container.attr("transform", event.transform);
      });

    svg.call(zoom);

    // Create container group
    const container = svg.append("g");

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

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

    const initialScale = 0.85;
    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 position
    const centerNode = nodes.find((n) => n.isCenter);
    if (centerNode) {
      centerNode.fx = width / 2;
      centerNode.fy = height / 2;
    }

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

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

    // Add drag behavior
    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);

    // Add node circles/rectangles
    nodeGroup.each(function (d) {
      const group = d3.select(this);

      if (d.isCenter) {
        // Center node as rectangle
        const rect = group
          .append("rect")
          .attr("width", 150)
          .attr("height", 60)
          .attr("x", -75)
          .attr("y", -30)
          .attr("rx", 8)
          .attr("ry", 8)
          .attr("fill", categoryToColor[d.category] || "#94A3B8")
          .attr("stroke", "#FFFFFF")
          .attr("stroke-width", 3)
          .style("pointer-events", "none");

        // Add center image if available
        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", 150)
            .attr("height", 60)
            .attr("href", d.isCenter ? "/main-circle.png" : d.imageUrl)
            .attr("preserveAspectRatio", "xMidYMid slice");

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

        // Add node image if available
        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("backgroundColor", "#fff")
            .attr("preserveAspectRatio", "xMidYMid slice");

          // Create circular clip path
          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})`);
        }
      }
    });

    // Add labels below nodes
    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");

    // Add hover effects
    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);
      });

    // Add click handlers
    nodeGroup.on("click", async function (event, d) {
      event.stopPropagation();

      // Don't handle center node clicks
      if (d.isCenter) return;

      if (onNodeClick && d.stageid) {
        try {
          // Fetch detailed company data
          const res = await callAPI(d.stageid);

          const responseData = JSON.parse(res.data);
          const fieldValues =
            JSON.parse(responseData?.getvalue)?.[0]?.FieldValues || [];
          // Filter out image fields and find description
          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);
          // Fallback to basic info
          const basicDetails: CompanyDetails = {
            id: d.id,
            label: d.label,
            category: d.category,
            stageid: d.stageid,
            fields: [],
          };
          onNodeClick(basicDetails);
        }
      }
    });

    // Update positions on simulation tick
    simulation.on("tick", () => {
      link
        .attr("x1", (d) => (d.source as Node).x!)
        .attr("y1", (d) => (d.source as Node).y!)
        .attr("x2", (d) => (d.target as Node).x!)
        .attr("y2", (d) => (d.target as Node).y!);

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

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

  // Show error message
  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>
    );
  }

  // Don't render on server side
  if (!isMounted) {
    return (
      <div className="w-full h-full flex items-center justify-center bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)]">
        <div className="text-white font-persian text-sm">
          در حال بارگذاری...
        </div>
      </div>
    );
  }

  if (isLoading) {
    return (
      <div className="w-full h-full relative bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)]">
        {/* Skeleton Graph Container */}
        <div className="w-full h-full flex items-center justify-center relative">
          {/* Center Node Skeleton */}
          <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>

          {/* Outer Ring Nodes Skeleton */}
          {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={{
                    left: "50%",
                    top: "40px",
                    transform: "translateX(-50%)",
                    animationDelay: `${i * 200 + 100}ms`,
                  }}
                ></div>
                <div
                  className="absolute w-0.5 bg-gray-600 animate-pulse opacity-30"
                  style={{
                    left: "50%",
                    top: "50%",
                    height: `${radius - 16}px`,
                    transformOrigin: "top",
                    transform: `translateX(-50%) rotate(${angle + Math.PI}rad)`,
                    animationDelay: `${i * 100}ms`,
                  }}
                ></div>
              </div>
            );
          })}
        </div>

        <div className="absolute bottom-6 left-1/2 transform -translate-x-1/2">
          <div className="text-white font-persian text-sm animate-pulse">
            در حال بارگذاری نمودار...
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="w-full h-full relative bg-[linear-gradient(to_bottom_left,#464861,10%,#111628)] overflow-hidden">
      <svg ref={svgRef} className="w-full h-full" style={{ minHeight: 500 }} />
    </div>
  );
}

export default NetworkGraph;
