"use client";

import * as React from "react";
import { useRouter } from "next/navigation";
import { useSession } from "next-auth/react";
import { toast } from "sonner";

import { Loading } from "@/components/ui/loading";
import { cn } from "@/lib/utils";
import { useTeamsQuery } from "@/hooks/use-teams-query";
import { getTeamRosterUserIds } from "@/lib/team-roster";
import { useGetProfileQuery } from "@/api/rtk/auth-api";
import { useGetRolesQuery } from "@/api/rtk";
import { useGetAllUsersQuery, type TeamUser } from "@/api/rtk/teams-api";
import { pickRoleIdFromOrgRoles } from "@/components/deals/contributor-user-picker";
import {
  useGetKpiBdrMetricsQuery,
  useGetBdrMetricsLeadsQuery,
  useLazyExportBdrMetricsPdfQuery,
  invalidateBdrMetricsCache,
  type BdrMetricsBucket,
  type BdrMetricsQueryParams,
} from "@/api/rtk/bdr-metrics-api";
import { useAppDispatch } from "@/store/hooks";
import { useInvalidateTeamsListCache } from "@/hooks/use-teams-query";
import {
  canSeeAllTeamsInApp,
  canViewSalesTargets,
  filterTeamsVisibleToUser,
  hasPermission,
  type PermissionSource,
} from "@/lib/permissions";
import { BdrMetricsPlannedTargetsBanner } from "./bdr-metrics-planned-targets-banner";
import { format } from "date-fns";
import { formatTeamLabelForUi } from "@/lib/deal-display";
import {
  appendBdrMetricsDateParams,
  bdrMetricsBucketLabel,
  formatBdrMetricsRangeLabel,
  getLastMonthDateRange,
  getLastYearDateRange,
  isCustomDateRangeValid,
  type BdrMetricsDateRangeMode,
} from "./bdr-metrics-date-range";
import { BdrMetricsPageHeader } from "./bdr-metrics-page-header";
import { BdrMetricsFunnel } from "./bdr-metrics-funnel";
import { BdrMetricsLeadsPanel } from "./bdr-metrics-leads-panel";
import { BdrMetricsKpiCard } from "./bdr-metrics-kpi-card";

const INITIAL_BUCKET_SEARCH: Record<BdrMetricsBucket, string> = {
  assigned: "",
  sql: "",
  meeting_booked: "",
};

const INITIAL_BUCKET_PAGE: Record<BdrMetricsBucket, number> = {
  assigned: 1,
  sql: 1,
  meeting_booked: 1,
};

function isBdrTeamUser(user: TeamUser, bdrRoleId?: string): boolean {
  const roleId = user.role?.id;
  if (bdrRoleId && roleId === bdrRoleId) return true;
  const roleName = (user.role?.name ?? "").trim().toUpperCase();
  return (
    roleName === "BDR" ||
    roleName === "BUSINESS DEVELOPMENT REPRESENTATIVE"
  );
}

const BUCKET_CONFIG: {
  value: BdrMetricsBucket;
  label: string;
  description: string;
}[] = [
  {
    value: "assigned",
    label: "Assigned",
    description: "Leads assigned to the selected BDR(s) in scope",
  },
  {
    value: "sql",
    label: "SQL qualified",
    description:
      "Reached SQL — Qualified at least once (includes leads now in later stages)",
  },
  {
    value: "meeting_booked",
    label: "Meeting booked",
    description:
      "Reached Discovery Meeting Booked after SQL (from move history)",
  },
];

export default function BdrMetricsPage() {
  const router = useRouter();
  const dispatch = useAppDispatch();
  const invalidateTeamsList = useInvalidateTeamsListCache();
  const { data: session } = useSession();
  const backendUser = (session as { backendUser?: PermissionSource } | null)
    ?.backendUser;
  const { data: profile } = useGetProfileQuery();
  const { data: teams = [] } = useTeamsQuery();
  const { data: allUsers = [] } = useGetAllUsersQuery();
  const { data: orgRoles = [] } = useGetRolesQuery();

  const permissionSource: PermissionSource = backendUser ?? profile ?? null;
  const viewerId = profile?.id ?? "";

  const allowed = React.useMemo(
    () => hasPermission(permissionSource, "READ", "BDR_METRICS"),
    [permissionSource],
  );

  React.useEffect(() => {
    if (!permissionSource) return;
    if (!allowed) router.replace("/");
  }, [permissionSource, allowed, router]);

  const visibleTeams = React.useMemo(
    () => filterTeamsVisibleToUser(teams, viewerId, permissionSource),
    [teams, viewerId, permissionSource],
  );

  const defaultTeamId = canSeeAllTeamsInApp(permissionSource)
    ? "all"
    : (visibleTeams[0]?.id ?? "all");

  const defaultDateRange = React.useMemo(() => getLastYearDateRange(), []);

  const [teamId, setTeamId] = React.useState(defaultTeamId);
  const [bdrId, setBdrId] = React.useState("all");
  const [dateRangeMode, setDateRangeMode] =
    React.useState<BdrMetricsDateRangeMode>("last_year");
  const [from, setFrom] = React.useState(defaultDateRange.from);
  const [to, setTo] = React.useState(defaultDateRange.to);
  const [bucket, setBucket] = React.useState<BdrMetricsBucket>("assigned");
  const [bucketSearch, setBucketSearch] = React.useState(INITIAL_BUCKET_SEARCH);
  const [bucketPage, setBucketPage] = React.useState(INITIAL_BUCKET_PAGE);

  React.useEffect(() => {
    setTeamId(defaultTeamId);
  }, [defaultTeamId]);

  React.useEffect(() => {
    setBucketPage(INITIAL_BUCKET_PAGE);
  }, [teamId, bdrId, dateRangeMode, from, to]);

  const queryParams = React.useMemo((): BdrMetricsQueryParams => {
    const q: BdrMetricsQueryParams = { bucket };
    if (teamId !== "all") q.teamId = teamId;
    if (bdrId !== "all") q.bdrId = bdrId;
    return appendBdrMetricsDateParams(q, dateRangeMode, from, to);
  }, [teamId, bdrId, dateRangeMode, from, to, bucket]);

  const summaryParams = React.useMemo(() => {
    const { bucket: _b, ...rest } = queryParams;
    return rest;
  }, [queryParams]);

  const customRangeValid =
    dateRangeMode !== "custom" ||
    !from ||
    !to ||
    isCustomDateRangeValid(from, to);

  const {
    data: kpiData,
    isLoading: summaryLoading,
    isFetching: summaryFetching,
    refetch: refetchSummary,
  } = useGetKpiBdrMetricsQuery(summaryParams, {
    skip: !allowed || !customRangeValid,
  });

  const summary = kpiData;

  const {
    data: leads = [],
    isLoading: leadsLoading,
    isFetching: leadsFetching,
    refetch: refetchLeads,
  } = useGetBdrMetricsLeadsQuery(queryParams, {
    skip: !allowed || !customRangeValid,
  });

  const [exportPdf, { isFetching: exporting }] =
    useLazyExportBdrMetricsPdfQuery();

  const bdrRoleId = React.useMemo(
    () =>
      pickRoleIdFromOrgRoles(orgRoles, [
        "bdr",
        "business development representative",
      ]),
    [orgRoles],
  );

  const bdrOptions = React.useMemo(() => {
    const teamMemberIds = new Set<string>();
    if (teamId === "all") {
      for (const t of visibleTeams) {
        for (const id of getTeamRosterUserIds(t)) teamMemberIds.add(id);
      }
    } else {
      const t = visibleTeams.find((x) => x.id === teamId);
      if (t) {
        for (const id of getTeamRosterUserIds(t)) teamMemberIds.add(id);
      }
    }

    return allUsers
      .filter((u) => isBdrTeamUser(u, bdrRoleId))
      .filter((u) => teamMemberIds.has(u.id))
      .sort((a, b) => (a.name || "").localeCompare(b.name || ""));
  }, [allUsers, visibleTeams, teamId, bdrRoleId]);

  React.useEffect(() => {
    if (bdrId === "all") return;
    if (!bdrOptions.some((u) => u.id === bdrId)) setBdrId("all");
  }, [bdrId, bdrOptions]);

  const handleTeamChange = React.useCallback((value: string) => {
    setTeamId(value);
    setBdrId("all");
  }, []);

  const handleDateRangeModeChange = React.useCallback(
    (mode: BdrMetricsDateRangeMode) => {
      setDateRangeMode(mode);
      if (mode === "last_year") {
        const range = getLastYearDateRange();
        setFrom(range.from);
        setTo(range.to);
      } else if (mode === "all_time") {
        setFrom("");
        setTo("");
      } else if (mode === "custom") {
        const range = getLastMonthDateRange();
        setFrom(range.from);
        setTo(range.to);
      }
    },
    [],
  );

  const handleFromChange = React.useCallback((value: string) => {
    setDateRangeMode("custom");
    setFrom(value);
  }, []);

  const handleToChange = React.useCallback((value: string) => {
    setDateRangeMode("custom");
    setTo(value);
  }, []);

  const handleRefresh = React.useCallback(() => {
    invalidateBdrMetricsCache(dispatch);
    void invalidateTeamsList();
    void Promise.all([refetchSummary(), refetchLeads()]);
  }, [dispatch, invalidateTeamsList, refetchSummary, refetchLeads]);

  const teamOptions = React.useMemo(
    () =>
      visibleTeams.map((t) => ({
        id: t.id,
        name: formatTeamLabelForUi(t.name),
      })),
    [visibleTeams],
  );

  const rangeLabel = React.useMemo(
    () => formatBdrMetricsRangeLabel(dateRangeMode, from, to),
    [dateRangeMode, from, to],
  );

  const exportScope = React.useMemo(() => {
    const teamLabel =
      teamId === "all"
        ? "All teams"
        : (teamOptions.find((t) => t.id === teamId)?.name ?? "Selected team");
    const bdrLabel =
      bdrId === "all"
        ? "All BDRs"
        : (bdrOptions.find((u) => u.id === bdrId)?.name ?? "Selected BDR");
    return {
      teamLabel,
      bdrLabel,
      dateRangeMode,
      rangeLabel,
      bucketLabel: bdrMetricsBucketLabel(bucket),
      from,
      to,
    };
  }, [
    teamId,
    bdrId,
    bucket,
    dateRangeMode,
    rangeLabel,
    from,
    to,
    teamOptions,
    bdrOptions,
  ]);

  const handleExport = async () => {
    if (
      dateRangeMode === "custom" &&
      from &&
      to &&
      !isCustomDateRangeValid(from, to)
    ) {
      toast.error("Fix the date range before exporting.");
      return;
    }

    const slug = (value: string) =>
      value
        .toLowerCase()
        .replace(/[^a-z0-9]+/g, "-")
        .replace(/^-|-$/g, "")
        .slice(0, 40);
    const rangeSlug = slug(rangeLabel);
    const filename = `bdr-report_${slug(exportScope.teamLabel)}_${slug(exportScope.bdrLabel)}_${rangeSlug}.pdf`;

    const toastId = toast.loading("Generating BDR report PDF…");
    try {
      const exportParams = { ...summaryParams, bucket };
      const blob = await exportPdf(exportParams).unwrap();
      const url = window.URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = url;
      link.download = filename;
      document.body.appendChild(link);
      link.click();
      link.remove();
      window.URL.revokeObjectURL(url);
      toast.success("Report ready — check your downloads", { id: toastId });
    } catch {
      toast.error("Could not generate the PDF. Try again.", { id: toastId });
    }
  };

  const clearFilters = () => {
    setTeamId(defaultTeamId);
    setBdrId("all");
    setDateRangeMode("last_year");
    const range = getLastYearDateRange();
    setFrom(range.from);
    setTo(range.to);
  };

  const hasNonDefaultFilters =
    teamId !== defaultTeamId ||
    bdrId !== "all" ||
    dateRangeMode !== "last_year" ||
    (dateRangeMode === "custom" &&
      (from !== defaultDateRange.from || to !== defaultDateRange.to));

  const plannedMonth = React.useMemo(() => {
    if (!from) return null;
    const d = new Date(from);
    if (Number.isNaN(d.getTime())) return null;
    if (to) {
      const d2 = new Date(to);
      if (
        !Number.isNaN(d2.getTime()) &&
        (d.getUTCFullYear() !== d2.getUTCFullYear() ||
          d.getUTCMonth() !== d2.getUTCMonth())
      ) {
        return null;
      }
    }
    return {
      year: d.getUTCFullYear(),
      month: d.getUTCMonth() + 1,
      label: format(d, "MMMM yyyy"),
    };
  }, [from, to]);

  const showPlannedTargets =
    canViewSalesTargets(permissionSource) &&
    teamId !== "all" &&
    plannedMonth != null;

  if (!allowed) {
    return (
      <Loading variant="api" layout="page" message="Checking access..." />
    );
  }

  if (summaryLoading && !summary) {
    return (
      <Loading variant="api" layout="page" message="Loading BDR reports..." />
    );
  }

  const k1 = summary?.assignedToSql;
  const k2 = summary?.sqlToMeetingBooked;
  const filtersBusy = summaryFetching;
  const refreshing = summaryFetching || leadsFetching;
  const activeBucketMeta = BUCKET_CONFIG.find((b) => b.value === bucket)!;

  const bucketCounts: Record<BdrMetricsBucket, number> = {
    assigned: k1?.assignedCount ?? 0,
    sql: k1?.sqlConvertedCount ?? 0,
    meeting_booked: k2?.meetingBookedCount ?? 0,
  };

  return (
    <div className="relative flex h-full min-h-0 flex-col gap-4 p-3 sm:p-4 md:p-5 overflow-y-auto scrollbar-themed">
      <div className="absolute top-[-10%] left-[-10%] -z-10 h-[320px] w-[320px] rounded-full bg-indigo-500/5 blur-[120px] pointer-events-none" />
      <div className="absolute bottom-[-10%] right-[-10%] -z-10 h-[320px] w-[320px] rounded-full bg-emerald-500/5 blur-[120px] pointer-events-none" />

      <BdrMetricsPageHeader
        teamId={teamId}
        bdrId={bdrId}
        dateRangeMode={dateRangeMode}
        from={from}
        to={to}
        showClearFilters={hasNonDefaultFilters}
        showAllTeamsOption={canSeeAllTeamsInApp(permissionSource)}
        teamOptions={teamOptions}
        bdrOptions={bdrOptions.map((u) => ({ id: u.id, name: u.name }))}
        filtersBusy={filtersBusy}
        refreshing={refreshing}
        exporting={exporting}
        exportScope={exportScope}
        onRefresh={handleRefresh}
        onTeamChange={handleTeamChange}
        onBdrChange={setBdrId}
        onDateRangeModeChange={handleDateRangeModeChange}
        onFromChange={handleFromChange}
        onToChange={handleToChange}
        onClearFilters={clearFilters}
        onExport={() => void handleExport()}
      />

      {showPlannedTargets && plannedMonth && (
        <BdrMetricsPlannedTargetsBanner
          permissionSource={permissionSource}
          teamId={teamId}
          year={plannedMonth.year}
          month={plannedMonth.month}
          monthLabel={plannedMonth.label}
        />
      )}

      {/* Main Dual-pane Grid */}
      <div className="grid grid-cols-1 gap-6 lg:grid-cols-12 min-h-0 flex-1">
        <div className="lg:col-span-4 flex flex-col gap-5 shrink-0">
          <div className="grid grid-cols-2 gap-3">
            <BdrMetricsKpiCard
              title="Assigned → SQL"
              ratio={k1?.ratio ?? null}
              numerator={k1?.sqlConvertedCount ?? 0}
              denominator={k1?.assignedCount ?? 0}
              accentColor="indigo"
              description=""
            />
            <BdrMetricsKpiCard
              title="SQL → Meeting booked"
              ratio={k2?.ratio ?? null}
              numerator={k2?.meetingBookedCount ?? 0}
              denominator={k2?.sqlConvertedCount ?? 0}
              accentColor="teal"
              description=""
            />
          </div>

          <BdrMetricsFunnel
            assigned={k1?.assignedCount ?? 0}
            sql={k1?.sqlConvertedCount ?? 0}
            meeting={k2?.meetingBookedCount ?? 0}
          />
        </div>

        <div className="lg:col-span-8 flex flex-col min-h-0">
          <section className="flex flex-col flex-1 min-h-[480px] overflow-hidden rounded-3xl border border-white/50 bg-white/40 backdrop-blur-xl transition-all duration-300">
            <div className="flex shrink-0 flex-col gap-3 border-b border-black/[0.05] p-5 sm:flex-row sm:items-center sm:justify-between sm:gap-4">
              <div className="min-w-0">
                <h2 className="font-['Lexend'] text-base font-bold text-[#1d1d39]">
                  Lead Drill-down
                </h2>
                <p className="mt-0.5 font-['Lexend_Deca'] text-[11px] text-gray-500 line-clamp-1">
                  {activeBucketMeta.description}
                </p>
              </div>

              <div
                className="flex max-w-full shrink-0 flex-nowrap items-center gap-1 overflow-x-auto rounded-xl bg-gray-100/80 p-1 border border-black/[0.03] [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
                role="tablist"
                aria-label="Lead buckets"
              >
                {BUCKET_CONFIG.map((b) => {
                  const active = bucket === b.value;
                  return (
                    <button
                      key={b.value}
                      type="button"
                      role="tab"
                      aria-selected={active}
                      onClick={() => setBucket(b.value)}
                      className={cn(
                        "shrink-0 whitespace-nowrap rounded-lg px-3 py-1.5 font-['Lexend_Deca'] text-[11px] transition-all duration-200 active:scale-95",
                        active
                          ? "bg-white font-bold text-[#1d1d39] ring-1 ring-black/[0.04]"
                          : "font-semibold text-gray-500 hover:text-[#1d1d39]",
                      )}
                    >
                      {b.label}
                      <span
                        className={cn(
                          "ml-1.5 tabular-nums text-[10px]",
                          active ? "text-indigo-600" : "text-gray-400",
                        )}
                      >
                        ({bucketCounts[b.value]})
                      </span>
                    </button>
                  );
                })}
              </div>
            </div>

            <BdrMetricsLeadsPanel
              leads={leads}
              bucketLabel={activeBucketMeta.label}
              loading={leadsLoading}
              search={bucketSearch[bucket]}
              onSearchChange={(value) => {
                setBucketSearch((prev) => ({ ...prev, [bucket]: value }));
                setBucketPage((prev) => ({ ...prev, [bucket]: 1 }));
              }}
              page={bucketPage[bucket]}
              onPageChange={(nextPage) =>
                setBucketPage((prev) => ({ ...prev, [bucket]: nextPage }))
              }
            />
          </section>
        </div>
      </div>
    </div>
  );
}
