import { useEffect, useState } from "react";
import Link from "next/link";
import { observer } from "mobx-react-lite";
// hooks
import { useDashboard } from "hooks/store";
// components
import { MarimekkoGraph } from "components/ui";
import {
  DurationFilterDropdown,
  IssuesByPriorityEmptyState,
  WidgetLoader,
  WidgetProps,
} from "components/dashboard/widgets";
// ui
import { PriorityIcon } from "@plane/ui";
// helpers
import { getCustomDates } from "helpers/dashboard.helper";
// types
import { TIssuesByPriorityWidgetFilters, TIssuesByPriorityWidgetResponse } from "@plane/types";
// constants
import { PRIORITY_GRAPH_GRADIENTS } from "constants/dashboard";
import { ISSUE_PRIORITIES } from "constants/issue";

const TEXT_COLORS = {
  urgent: "#F4A9AA",
  high: "#AB4800",
  medium: "#AB6400",
  low: "#1F2D5C",
  none: "#60646C",
};

const CustomBar = (props: any) => {
  const { bar, workspaceSlug } = props;
  // states
  const [isMouseOver, setIsMouseOver] = useState(false);

  return (
    <Link href={`/${workspaceSlug}/workspace-views/assigned?priority=${bar?.id}`}>
      <g
        transform={`translate(${bar?.x},${bar?.y})`}
        onMouseEnter={() => setIsMouseOver(true)}
        onMouseLeave={() => setIsMouseOver(false)}
      >
        <rect
          x={0}
          y={isMouseOver ? -6 : 0}
          width={bar?.width}
          height={isMouseOver ? bar?.height + 6 : bar?.height}
          fill={bar?.fill}
          stroke={bar?.borderColor}
          strokeWidth={bar?.borderWidth}
          rx={4}
          ry={4}
          className="duration-300"
        />
        <text
          x={-bar?.height + 10}
          y={18}
          fill={TEXT_COLORS[bar?.id as keyof typeof TEXT_COLORS]}
          className="capitalize font-medium text-lg -rotate-90"
          dominantBaseline="text-bottom"
        >
          {bar?.id}
        </text>
      </g>
    </Link>
  );
};

const WIDGET_KEY = "issues_by_priority";

export const IssuesByPriorityWidget: React.FC<WidgetProps> = observer((props) => {
  const { dashboardId, workspaceSlug } = props;
  // store hooks
  const { fetchWidgetStats, getWidgetDetails, getWidgetStats, updateDashboardWidgetFilters } = useDashboard();
  // derived values
  const widgetDetails = getWidgetDetails(workspaceSlug, dashboardId, WIDGET_KEY);
  const widgetStats = getWidgetStats<TIssuesByPriorityWidgetResponse[]>(workspaceSlug, dashboardId, WIDGET_KEY);
  const selectedDuration = widgetDetails?.widget_filters.duration ?? "none";

  const handleUpdateFilters = async (filters: Partial<TIssuesByPriorityWidgetFilters>) => {
    if (!widgetDetails) return;

    await updateDashboardWidgetFilters(workspaceSlug, dashboardId, widgetDetails.id, {
      widgetKey: WIDGET_KEY,
      filters,
    });

    const filterDates = getCustomDates(filters.duration ?? selectedDuration);
    fetchWidgetStats(workspaceSlug, dashboardId, {
      widget_key: WIDGET_KEY,
      ...(filterDates.trim() !== "" ? { target_date: filterDates } : {}),
    });
  };

  useEffect(() => {
    const filterDates = getCustomDates(selectedDuration);
    fetchWidgetStats(workspaceSlug, dashboardId, {
      widget_key: WIDGET_KEY,
      ...(filterDates.trim() !== "" ? { target_date: filterDates } : {}),
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  if (!widgetDetails || !widgetStats) return <WidgetLoader widgetKey={WIDGET_KEY} />;

  const totalCount = widgetStats.reduce((acc, item) => acc + item?.count, 0);
  const chartData = widgetStats
    .filter((i) => i.count !== 0)
    .map((item) => ({
      priority: item?.priority,
      percentage: (item?.count / totalCount) * 100,
      urgent: item?.priority === "urgent" ? 1 : 0,
      high: item?.priority === "high" ? 1 : 0,
      medium: item?.priority === "medium" ? 1 : 0,
      low: item?.priority === "low" ? 1 : 0,
      none: item?.priority === "none" ? 1 : 0,
    }));

  const CustomBarsLayer = (props: any) => {
    const { bars } = props;

    return (
      <g>
        {bars
          ?.filter((b: any) => b?.value === 1) // render only bars with value 1
          .map((bar: any) => (
            <CustomBar key={bar?.key} bar={bar} workspaceSlug={workspaceSlug} />
          ))}
      </g>
    );
  };

  return (
    <div className="bg-neutral-component-surface-light rounded-xl border-[0.5px] border-neutral-border-medium w-full py-6 hover:shadow-custom-shadow-4xl duration-300 overflow-hidden min-h-96 flex flex-col">
      <div className="flex items-center justify-between gap-2 pl-7 pr-6">
        <Link
          href={`/${workspaceSlug}/workspace-views/assigned`}
          className="text-lg font-semibold text-neutral-text-medium hover:underline"
        >
          Assigned by priority
        </Link>
        <DurationFilterDropdown
          value={selectedDuration}
          onChange={(val) =>
            handleUpdateFilters({
              duration: val,
            })
          }
        />
      </div>
      {totalCount > 0 ? (
        <div className="flex items-center px-11 h-full">
          <div className="w-full -mt-[11px]">
            <MarimekkoGraph
              data={chartData}
              id="priority"
              value="percentage"
              dimensions={ISSUE_PRIORITIES.map((p) => ({
                id: p.key,
                value: p.key,
              }))}
              axisBottom={null}
              axisLeft={null}
              height="119px"
              margin={{
                top: 11,
                right: 0,
                bottom: 0,
                left: 0,
              }}
              defs={PRIORITY_GRAPH_GRADIENTS}
              fill={ISSUE_PRIORITIES.map((p) => ({
                match: {
                  id: p.key,
                },
                id: `gradient${p.title}`,
              }))}
              tooltip={() => <></>}
              enableGridX={false}
              enableGridY={false}
              layers={[CustomBarsLayer]}
            />
            <div className="flex items-center gap-1 w-full mt-3 text-sm font-semibold text-neutral-text-medium">
              {chartData.map((item) => (
                <p
                  key={item.priority}
                  className="flex items-center gap-1 flex-shrink-0"
                  style={{
                    width: `${item.percentage}%`,
                  }}
                >
                  <PriorityIcon priority={item.priority} withContainer />
                  {item.percentage.toFixed(0)}%
                </p>
              ))}
            </div>
          </div>
        </div>
      ) : (
        <div className="h-full grid place-items-center">
          <IssuesByPriorityEmptyState />
        </div>
      )}
    </div>
  );
});
