"use client";

import { useEffect } from "react";
import { usePathname } from "next/navigation";

const VISITOR_KEY = "tghr_visitor_id";
const SESSION_KEY = "tghr_session";
const LAST_PAGEVIEW_KEY = "tghr_last_pageview";

const SESSION_TIMEOUT = 30 * 60 * 1000; // 30 minutes
const DUPLICATE_WINDOW = 2000; // 2 seconds

function generateId(): string {
  if (typeof crypto !== "undefined" && crypto.randomUUID) {
    return crypto.randomUUID();
  }

  return `${Date.now()}-${Math.random().toString(36).slice(2)}`;
}

function getVisitorId(): string {
  const existing = localStorage.getItem(VISITOR_KEY);

  if (existing) {
    return existing;
  }

  const visitorId = generateId();

  localStorage.setItem(VISITOR_KEY, visitorId);

  return visitorId;
}

function getSessionId(): string {
  const now = Date.now();
  const stored = localStorage.getItem(SESSION_KEY);

  if (stored) {
    try {
      const session = JSON.parse(stored) as {
        id: string;
        lastActivity: number;
      };

      if (now - session.lastActivity < SESSION_TIMEOUT) {
        session.lastActivity = now;

        localStorage.setItem(
          SESSION_KEY,
          JSON.stringify(session)
        );

        return session.id;
      }
    } catch {
      // Create a new session if stored data is invalid.
    }
  }

  const sessionId = generateId();

  localStorage.setItem(
    SESSION_KEY,
    JSON.stringify({
      id: sessionId,
      lastActivity: now,
    })
  );

  return sessionId;
}

function getDevice(): "Desktop" | "Tablet" | "Mobile" | "Unknown" {
  const userAgent = navigator.userAgent.toLowerCase();

  if (/ipad|tablet|playbook|silk/.test(userAgent)) {
    return "Tablet";
  }

  if (
    /mobi|android|iphone|ipod|blackberry|windows phone/.test(
      userAgent
    )
  ) {
    return "Mobile";
  }

  if (/windows|macintosh|linux|x11/.test(userAgent)) {
    return "Desktop";
  }

  return "Unknown";
}

function getBrowser(): string {
  const userAgent = navigator.userAgent;

  if (/edg/i.test(userAgent)) {
    return "Edge";
  }

  if (/opr|opera/i.test(userAgent)) {
    return "Opera";
  }

  if (/firefox/i.test(userAgent)) {
    return "Firefox";
  }

  if (/chrome|crios/i.test(userAgent)) {
    return "Chrome";
  }

  if (/safari/i.test(userAgent)) {
    return "Safari";
  }

  return "Unknown";
}

export default function WebsiteTrafficTracker() {
  const pathname = usePathname();

  useEffect(() => {
    if (!pathname) {
      return;
    }

    const apiUrl = process.env.NEXT_PUBLIC_BACKEND_URL;

    if (!apiUrl) {
      console.warn(
        "NEXT_PUBLIC_BACKEND_URL is not configured."
      );
      return;
    }

    const now = Date.now();

    try {
      const previous = sessionStorage.getItem(
        LAST_PAGEVIEW_KEY
      );

      if (previous) {
        const data = JSON.parse(previous) as {
          page: string;
          timestamp: number;
        };

        if (
          data.page === pathname &&
          now - data.timestamp < DUPLICATE_WINDOW
        ) {
          return;
        }
      }

      sessionStorage.setItem(
        LAST_PAGEVIEW_KEY,
        JSON.stringify({
          page: pathname,
          timestamp: now,
        })
      );
    } catch {
      // Ignore storage errors.
    }

    const payload = {
      visitorId: getVisitorId(),
      sessionId: getSessionId(),
      page: pathname,
      referrer: document.referrer || "Direct",
      device: getDevice(),
      browser: getBrowser(),
      eventType: "page_view",
    };

    const timeoutId = window.setTimeout(() => {
      fetch(`${apiUrl}/api/analytics/track`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(payload),
        keepalive: true,
      }).catch(() => {
        // Analytics failure must never affect the website.
      });
    }, 0);

    return () => {
      window.clearTimeout(timeoutId);
    };
  }, [pathname]);

  return null;
}