"use client";

import { useState, useMemo } from "react";
import { useTranslations } from "next-intl";
import {
  usePractitionerDashboardControllerGetPendingScreeningsV1,
  usePractitionerDashboardControllerGetCompletedScreeningsV1,
} from "@/api/user/practitioner-dashboard/practitioner-dashboard";
import { PendingScreeningData, CompletedScreeningData } from "@/api/user/generated.schemas";

interface ChartDataPoint {
  label: string;
  value: number;
}

export default function ScreeningsChart() {
  const t = useTranslations("practitioner");
  const [period, setPeriod] = useState("Monthly");
  const [hoveredPoint, setHoveredPoint] = useState<number | null>(null);

  // Fetch pending screenings (backend max limit is 100)
  const { data: pendingResponse, isLoading: isPendingLoading } = usePractitionerDashboardControllerGetPendingScreeningsV1(
    { page: 1, limit: 100 }
  );

  // Fetch completed screenings (backend max limit is 100)
  const { data: completedResponse, isLoading: isCompletedLoading } = usePractitionerDashboardControllerGetCompletedScreeningsV1(
    { page: 1, limit: 100 }
  );

  const isLoading = isPendingLoading || isCompletedLoading;

  // Aggregate data by period
  const chartData = useMemo((): ChartDataPoint[] => {
    const pendingScreenings: PendingScreeningData[] = (pendingResponse as any)?.data || [];
    const completedScreenings: CompletedScreeningData[] = (completedResponse as any)?.data || [];

    // Combine all screenings with their dates
    const allDates: Date[] = [
      ...pendingScreenings.map((s) => new Date(s.created_at)),
      ...completedScreenings.map((s) => new Date(s.completed_at)),
    ].filter((d) => !isNaN(d.getTime()));

    if (allDates.length === 0) {
      // Return empty structure based on period
      if (period === "Weekly") {
        return ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"].map((label) => ({ label, value: 0 }));
      } else if (period === "Yearly") {
        const currentYear = new Date().getFullYear();
        return Array.from({ length: 5 }, (_, i) => ({ label: String(currentYear - 4 + i), value: 0 }));
      }
      return ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"].map((label) => ({ label, value: 0 }));
    }

    const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
    const dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];

    if (period === "Weekly") {
      // Group by day of week for current week
      const counts: Record<string, number> = {};
      dayNames.forEach((d) => (counts[d] = 0));

      const now = new Date();
      const startOfWeek = new Date(now);
      startOfWeek.setDate(now.getDate() - now.getDay());
      startOfWeek.setHours(0, 0, 0, 0);

      allDates.forEach((date) => {
        if (date >= startOfWeek) {
          const day = dayNames[date.getDay()];
          counts[day] = (counts[day] || 0) + 1;
        }
      });

      // Reorder to start from Monday
      return ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"].map((label) => ({
        label,
        value: counts[label] || 0,
      }));
    } else if (period === "Yearly") {
      // Group by year
      const counts: Record<string, number> = {};
      const currentYear = new Date().getFullYear();

      // Initialize last 5 years
      for (let i = currentYear - 4; i <= currentYear; i++) {
        counts[String(i)] = 0;
      }

      allDates.forEach((date) => {
        const year = String(date.getFullYear());
        if (counts[year] !== undefined) {
          counts[year] = (counts[year] || 0) + 1;
        }
      });

      return Object.entries(counts)
        .sort(([a], [b]) => Number(a) - Number(b))
        .map(([label, value]) => ({ label, value }));
    } else {
      // Monthly - group by month for current year
      const counts: Record<string, number> = {};
      monthNames.forEach((m) => (counts[m] = 0));

      const currentYear = new Date().getFullYear();

      allDates.forEach((date) => {
        if (date.getFullYear() === currentYear) {
          const month = monthNames[date.getMonth()];
          counts[month] = (counts[month] || 0) + 1;
        }
      });

      return monthNames.map((label) => ({
        label,
        value: counts[label] || 0,
      }));
    }
  }, [pendingResponse, completedResponse, period]);

  // Calculate max value dynamically
  const maxDataValue = Math.max(...chartData.map((d) => d.value), 1);
  const maxValue = Math.ceil(maxDataValue / 10) * 10 || 10; // Round up to nearest 10

  const chartWidth = 500;
  const chartHeight = 250;
  const padding = { top: 20, right: 20, bottom: 30, left: 40 };
  const innerWidth = chartWidth - padding.left - padding.right;
  const innerHeight = chartHeight - padding.top - padding.bottom;

  const xScale = (index: number) => {
    if (chartData.length <= 1) return padding.left + innerWidth / 2;
    const divisor = Math.max(chartData.length - 1, 1);
    return padding.left + (index * innerWidth) / divisor;
  };
  const yScale = (value: number) => {
    const safeMaxValue = Math.max(maxValue, 1);
    const scaledValue = Math.max(0, Math.min(value / safeMaxValue, 1)) * innerHeight;
    return padding.top + innerHeight - scaledValue;
  };

  const linePath = chartData
    .map((d, i) => `${i === 0 ? "M" : "L"} ${xScale(i)} ${yScale(d.value)}`)
    .join(" ");

  const areaPath = chartData.length > 0
    ? `${linePath} L ${xScale(chartData.length - 1)} ${padding.top + innerHeight} L ${padding.left} ${padding.top + innerHeight} Z`
    : "";

  // Dynamic y-axis ticks based on max value
  const yAxisTicks = useMemo(() => {
    const tickCount = 5;
    const step = Math.ceil(maxValue / tickCount);
    return Array.from({ length: tickCount + 1 }, (_, i) => i * step);
  }, [maxValue]);

  return (
    <div className="bg-white rounded-xl border border-gray-300 shadow-sm p-5">
      <div className="flex items-center justify-between mb-4">
        <h3 className="text-lg font-semibold text-gray-900">{t("dashboard.screeningsOverTime")}</h3>
        <select
          value={period}
          onChange={(e) => setPeriod(e.target.value)}
          className="px-3 py-1.5 text-sm text-gray-600 border border-gray-200 rounded-lg bg-white focus:outline-none focus:ring-2 focus:ring-[#3B9EC9]/20 cursor-pointer"
        >
          <option value="Monthly">{t("dashboard.monthly")}</option>
          <option value="Weekly">{t("dashboard.weekly")}</option>
          <option value="Yearly">{t("dashboard.yearly")}</option>
        </select>
      </div>

      <div className="relative">
        {isLoading ? (
          <div className="flex justify-center items-center h-[250px]">
            <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-[#3B9EC9]"></div>
          </div>
        ) : (
        <svg viewBox={`0 0 ${chartWidth} ${chartHeight}`} className="w-full h-auto">
          {/* Y-axis grid lines */}
          {yAxisTicks.map((tick) => (
            <g key={tick}>
              <line
                x1={padding.left}
                y1={yScale(tick)}
                x2={chartWidth - padding.right}
                y2={yScale(tick)}
                stroke="#E5E7EB"
                strokeDasharray="4,4"
              />
              <text
                x={padding.left - 8}
                y={yScale(tick)}
                textAnchor="end"
                alignmentBaseline="middle"
                className="text-xs fill-gray-400"
              >
                {tick === 0 ? "0" : tick.toLocaleString()}
              </text>
            </g>
          ))}

          {/* Area fill */}
          <defs>
            <linearGradient id="areaGradient" x1="0%" y1="0%" x2="0%" y2="100%">
              <stop offset="0%" stopColor="#3B9EC9" stopOpacity="0.3" />
              <stop offset="100%" stopColor="#3B9EC9" stopOpacity="0.05" />
            </linearGradient>
          </defs>
          <path d={areaPath} fill="url(#areaGradient)" />

          {/* Line */}
          <path d={linePath} fill="none" stroke="#3B9EC9" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" />

          {/* Data points */}
          {chartData.map((d, i) => (
            <g key={i}>
              <circle
                cx={xScale(i)}
                cy={yScale(d.value)}
                r={hoveredPoint === i ? 6 : 4}
                fill="#3B9EC9"
                stroke="white"
                strokeWidth="2"
                className="cursor-pointer transition-all"
                onMouseEnter={() => setHoveredPoint(i)}
                onMouseLeave={() => setHoveredPoint(null)}
              />
              {hoveredPoint === i && (
                <g>
                  <rect
                    x={xScale(i) - 25}
                    y={yScale(d.value) - 35}
                    width="50"
                    height="24"
                    rx="6"
                    fill="#3B9EC9"
                  />
                  <text
                    x={xScale(i)}
                    y={yScale(d.value) - 18}
                    textAnchor="middle"
                    className="text-xs fill-white font-medium"
                  >
                    {d.value}
                  </text>
                </g>
              )}
            </g>
          ))}

          {/* X-axis labels */}
          {chartData.map((d, i) => (
            <text
              key={i}
              x={xScale(i)}
              y={chartHeight - 8}
              textAnchor="middle"
              className="text-xs fill-gray-400"
            >
              {d.label}
            </text>
          ))}
        </svg>
        )}
      </div>
    </div>
  );
}
