import { useQuery } from "@tanstack/react-query";
import { formatMetricValue } from "./platformMetrics";

interface Props {
  platformType: string;
  channelId: string;
}

async function fetchSub(platform: string, channelId: string, sub: string, params?: Record<string, string>) {
  const baseUrl = (window as any).viralyWP.restUrl.replace(/\/+$/, "");
  const nonce = (window as any).viralyWP.restNonce;
  const qs = params ? "?" + new URLSearchParams(params).toString() : "";
  const res = await fetch(`${baseUrl}/analytics/${platform.toLowerCase()}/${channelId}/${sub}${qs}`, {
    credentials: "same-origin",
    headers: { "X-WP-Nonce": nonce, "Content-Type": "application/json" },
  });
  const text = await res.text();
  try { return JSON.parse(text); } catch { return null; }
}

interface BarItem { label: string; value: number; pct: number }

function HorizontalBars({ items, title, maxItems = 8 }: { items: BarItem[]; title: string; maxItems?: number }) {
  const display = items.slice(0, maxItems);
  if (display.length === 0) return null;

  return (
    <div>
      <h5 className="vr-text-xs vr-font-semibold vr-text-gray-600 vr-mb-2">{title}</h5>
      <div className="vr-space-y-1.5">
        {display.map((item, i) => (
          <div key={i} className="vr-flex vr-items-center vr-gap-2">
            <span className="vr-text-xs vr-text-gray-600 vr-w-20 vr-truncate vr-text-right vr-flex-shrink-0">{item.label}</span>
            <div className="vr-flex-1 vr-h-4 vr-bg-gray-100 vr-rounded-full vr-overflow-hidden">
              <div
                className="vr-h-full vr-rounded-full"
                style={{ width: `${Math.max(item.pct, 2)}%`, backgroundColor: "#E03058" }}
              />
            </div>
            <span className="vr-text-xs vr-text-gray-500 vr-w-12 vr-flex-shrink-0">{formatMetricValue(item.value)}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

function InstagramDemographics({ channelId }: { channelId: string }) {
  const { data, isLoading } = useQuery({
    queryKey: ["analytics-demographics", "instagram", channelId],
    queryFn: () => fetchSub("instagram", channelId, "demographics"),
    staleTime: 600_000,
  });

  const { data: followerCount } = useQuery({
    queryKey: ["analytics-followers", "instagram", channelId],
    queryFn: () => fetchSub("instagram", channelId, "followers-count"),
    staleTime: 600_000,
  });

  if (isLoading) return <DemoLoading />;

  const demo = data?.data;
  if (!demo) return null;

  const countries = extractBreakdown(demo?.country, "country");
  const cities = extractBreakdown(demo?.city, "city");
  const ages = extractBreakdown(demo?.age, "age");
  const genders = extractBreakdown(demo?.gender, "gender");

  return (
    <div className="vr-space-y-4">
      {followerCount?.data != null && (
        <div className="vr-text-center vr-py-3 vr-bg-gray-50 vr-rounded-lg">
          <p className="vr-text-2xl vr-font-bold vr-text-gray-900">{formatMetricValue(followerCount.data)}</p>
          <p className="vr-text-xs vr-text-gray-500">Total Followers</p>
        </div>
      )}
      <div className="vr-grid vr-grid-cols-1 sm:vr-grid-cols-2 vr-gap-5">
        <HorizontalBars items={countries} title="Top Countries" />
        <HorizontalBars items={cities} title="Top Cities" />
        <HorizontalBars items={ages} title="Age Groups" />
        <HorizontalBars items={genders} title="Gender" />
      </div>
    </div>
  );
}

function YouTubeDemographics({ channelId }: { channelId: string }) {
  const { data: demoData, isLoading: demoLoading } = useQuery({
    queryKey: ["analytics-demographics", "youtube", channelId],
    queryFn: () => fetchSub("youtube", channelId, "demographics"),
    staleTime: 600_000,
  });

  const { data: deviceData } = useQuery({
    queryKey: ["analytics-device", "youtube", channelId],
    queryFn: () => fetchSub("youtube", channelId, "device"),
    staleTime: 600_000,
  });

  if (demoLoading) return <DemoLoading />;

  const demoItems = demoData?.data;
  const deviceItems = deviceData?.data;

  // Demographics: array of { dimensionKey, viewerPercentage }
  const demographics: BarItem[] = Array.isArray(demoItems)
    ? demoItems.map((d: any) => ({
        label: d.dimensionKey || "Unknown",
        value: d.viewerPercentage || 0,
        pct: d.viewerPercentage || 0,
      })).sort((a: BarItem, b: BarItem) => b.value - a.value)
    : [];

  // Device: array of { deviceType, views, estimatedMinutesWatched }
  const devices: BarItem[] = Array.isArray(deviceItems)
    ? (() => {
        const total = deviceItems.reduce((s: number, d: any) => s + (d.views || 0), 0);
        return deviceItems.map((d: any) => ({
          label: d.deviceType || "Unknown",
          value: d.views || 0,
          pct: total > 0 ? ((d.views || 0) / total) * 100 : 0,
        })).sort((a: BarItem, b: BarItem) => b.value - a.value);
      })()
    : [];

  return (
    <div className="vr-grid vr-grid-cols-1 sm:vr-grid-cols-2 vr-gap-5">
      <HorizontalBars items={demographics} title="Audience Demographics" />
      <HorizontalBars items={devices} title="Device Breakdown" />
    </div>
  );
}

function ThreadsDemographics({ channelId }: { channelId: string }) {
  const breakdowns = ["country", "age", "gender"] as const;
  const queries = breakdowns.map((b) =>
    // eslint-disable-next-line react-hooks/rules-of-hooks
    useQuery({
      queryKey: ["analytics-demographics", "threads", channelId, b],
      queryFn: () => fetchSub("threads", channelId, "demographics", { breakdown: b }),
      staleTime: 600_000,
    })
  );

  const isLoading = queries.some((q) => q.isLoading);
  if (isLoading) return <DemoLoading />;

  const results = breakdowns.map((b, i) => {
    const raw = queries[i].data?.data;
    if (!Array.isArray(raw) || raw.length === 0) return [];
    const item = raw[0];
    const breakdownData = item?.totalValue?.breakdowns?.[0]?.results;
    if (!Array.isArray(breakdownData)) return [];
    const total = breakdownData.reduce((s: number, r: any) => s + (r.value || 0), 0);
    return breakdownData.map((r: any) => ({
      label: r.dimensionValues?.[0] || "Unknown",
      value: r.value || 0,
      pct: total > 0 ? ((r.value || 0) / total) * 100 : 0,
    })).sort((a: BarItem, b: BarItem) => b.value - a.value);
  });

  return (
    <div className="vr-grid vr-grid-cols-1 sm:vr-grid-cols-2 vr-gap-5">
      <HorizontalBars items={results[0]} title="Top Countries" />
      <HorizontalBars items={results[1]} title="Age Groups" />
      <HorizontalBars items={results[2]} title="Gender" />
    </div>
  );
}

function FacebookDemographics({ data }: { data: any }) {
  // Facebook aggregated already includes fansByCountry and fansByCity in the current period
  const current = data?.current;
  if (!current) return null;

  const countries = parseObjectBreakdown(current.pageFansCountry || current.fansByCountry);
  const cities = parseObjectBreakdown(current.pageFansCity || current.fansByCity);

  if (countries.length === 0 && cities.length === 0) return null;

  return (
    <div className="vr-grid vr-grid-cols-1 sm:vr-grid-cols-2 vr-gap-5">
      <HorizontalBars items={countries} title="Fans by Country" />
      <HorizontalBars items={cities} title="Fans by City" maxItems={6} />
    </div>
  );
}

// Helpers

function extractBreakdown(items: any[], dimensionName: string): BarItem[] {
  if (!Array.isArray(items) || items.length === 0) return [];
  // Find the first metric that has breakdowns
  for (const item of items) {
    const breakdowns = item?.breakdowns;
    if (!Array.isArray(breakdowns)) continue;
    const total = breakdowns.reduce((s: number, b: any) => s + (b.value || 0), 0);
    return breakdowns
      .map((b: any) => {
        const label = Array.isArray(b.dimensionValues) ? b.dimensionValues[0] : (b[dimensionName] || "Unknown");
        return {
          label,
          value: b.value || 0,
          pct: total > 0 ? ((b.value || 0) / total) * 100 : 0,
        };
      })
      .sort((a: BarItem, b: BarItem) => b.value - a.value);
  }
  return [];
}

function parseObjectBreakdown(obj: any): BarItem[] {
  if (!obj) return [];
  // Could be array of { countryCode/cityName, metricValue } or a plain dictionary
  if (Array.isArray(obj)) {
    const total = obj.reduce((s: number, item: any) => s + (item.metricValue || item.value || 0), 0);
    return obj
      .map((item: any) => ({
        label: item.countryCode || item.cityName || item.key || "Unknown",
        value: item.metricValue || item.value || 0,
        pct: total > 0 ? ((item.metricValue || item.value || 0) / total) * 100 : 0,
      }))
      .sort((a: BarItem, b: BarItem) => b.value - a.value);
  }
  // Plain object { "US": 100, "UK": 50 }
  if (typeof obj === "object") {
    const entries = Object.entries(obj) as [string, number][];
    const total = entries.reduce((s, [, v]) => s + (Number(v) || 0), 0);
    return entries
      .map(([k, v]) => ({
        label: k,
        value: Number(v) || 0,
        pct: total > 0 ? ((Number(v) || 0) / total) * 100 : 0,
      }))
      .sort((a, b) => b.value - a.value);
  }
  return [];
}

function DemoLoading() {
  return (
    <div className="vr-flex vr-items-center vr-justify-center vr-gap-2 vr-py-4 vr-text-gray-400 vr-text-xs">
      <div className="vr-w-3.5 vr-h-3.5 vr-border-2 vr-border-gray-200 vr-border-t-primary-600 vr-rounded-full vr-animate-spin" />
      Loading demographics...
    </div>
  );
}

// Main component that delegates to platform-specific views
export default function AnalyticsDemographics({ platformType, channelId }: Props) {
  // Only show for platforms that have demographics data
  switch (platformType) {
    case "Instagram":
      return (
        <div>
          <h4 className="vr-text-xs vr-font-semibold vr-text-gray-700 vr-mb-3">Audience & Demographics</h4>
          <InstagramDemographics channelId={channelId} />
        </div>
      );
    case "YouTube":
      return (
        <div>
          <h4 className="vr-text-xs vr-font-semibold vr-text-gray-700 vr-mb-3">Audience & Devices</h4>
          <YouTubeDemographics channelId={channelId} />
        </div>
      );
    case "Threads":
      return (
        <div>
          <h4 className="vr-text-xs vr-font-semibold vr-text-gray-700 vr-mb-3">Audience Demographics</h4>
          <ThreadsDemographics channelId={channelId} />
        </div>
      );
    default:
      return null;
  }
}

// Exported separately so Facebook can use it with data already fetched
export { FacebookDemographics };
