"use client";

import * as React from "react";
import dynamic from "next/dynamic";
import { useRouter } from "next/navigation";
import { useSession } from "next-auth/react";
import { format } from "date-fns";
import { toast } from "sonner";
import { CalendarPlus } from "lucide-react";

import { Loading } from "@/components/ui/loading";
import { NoDataFound } from "@/components/ui/no-data-found";
import { Button } from "@/components/ui/button";
import { SalesTargetsSalesDailyKpiGrid } from "@/components/dashboard/kpi-grid";
import { SalesTargetsBody } from "@/components/sales-targets/sales-targets-body";
import {
  SalesTargetsPageHeader,
  type SalesTargetsPageHeaderActions,
  type SalesTargetsPageHeaderState,
} from "@/components/sales-targets/sales-targets-page-header";
import type { SalesTargetsSummaryData } from "@/components/sales-targets/sales-targets-summary";
import { useGetProfileQuery } from "@/api/rtk/auth-api";
import {
  useCreateSalesTargetMonthMutation,
  useCopyPreviousSalesTargetMonthMutation,
  useGetAeAttainmentSummaryQuery,
  useGetSalesTargetMonthsQuery,
  useGetTeamSalesTargetsQuery,
  useLazyExportSalesTargetsPdfQuery,
} from "@/api/rtk/sales-targets-api";
import {
  compareYearMonth,
  useSalesTargetsPeriod,
} from "@/components/sales-targets/sales-targets-period";
import { useGetTeamsQuery } from "@/api/rtk/teams-api";
import { getApiEntityId } from "@/api/permissions/types";
import {
  buildRowStateFromTargets,
  buildTeamMemberAttainmentList,
} from "@/components/sales-targets/sales-targets-helpers";
import {
  canManageSalesTargetsInApp,
  canCreateSalesTargetMonthsInApp,
  canExportSalesTargetsPdfInApp,
  canViewSalesTargets,
  canSetTeamLevelSalesTarget,
  shouldScopeSalesTargetsToLedTeamsOnly,
  unwrapPermissionSource,
  type PermissionSource,
} from "@/lib/permissions";

const AssignRepTargetsModal = dynamic(
  () =>
    import("@/components/sales-targets/assign-rep-targets-modal").then(
      (m) => m.AssignRepTargetsModal,
    ),
  { ssr: false },
);

const SalesTargetsAdminPanel = dynamic(
  () =>
    import("@/components/sales-targets/sales-targets-admin-panel").then(
      (m) => m.SalesTargetsAdminPanel,
    ),
  { ssr: false, loading: () => <Loading variant="api" layout="section" /> },
);

export default function SalesTargetsPage() {
  const router = useRouter();
  const { data: session } = useSession();
  const backendUser = (session as { backendUser?: PermissionSource } | null)
    ?.backendUser;
  const { data: profile } = useGetProfileQuery();
  const permissionSource: PermissionSource = backendUser ?? profile ?? null;

  const { data: allTeams = [] } = useGetTeamsQuery(undefined, {
    skip: !permissionSource,
  });

  const allowed = React.useMemo(
    () => canViewSalesTargets(permissionSource, allTeams),
    [permissionSource, allTeams],
  );
  const canAddMonth = React.useMemo(
    () => canCreateSalesTargetMonthsInApp(permissionSource, allTeams),
    [permissionSource, allTeams],
  );
  const showExportPdf = React.useMemo(
    () => canExportSalesTargetsPdfInApp(permissionSource, allTeams),
    [permissionSource, allTeams],
  );

  const { year, month, goPreviousMonth, goNextMonth } = useSalesTargetsPeriod();

  const [assignModalOpen, setAssignModalOpen] = React.useState(false);
  const [assignTeamId, setAssignTeamId] = React.useState<string | undefined>();
  const [teamFilterId, setTeamFilterId] = React.useState("all");

  const salesTargetsLiveQueryOptions = React.useMemo(
    () =>
      ({
        skip: !allowed,
      }) as const,
    [allowed],
  );

  const userId = React.useMemo(
    () => getApiEntityId(unwrapPermissionSource(permissionSource) ?? undefined),
    [permissionSource],
  );
  const ledTeamIds = React.useMemo(() => {
    const ids = new Set<string>();
    if (!userId) return ids;
    for (const t of allTeams) {
      if (
        t.teamLead?.userId === userId ||
        t.lead === userId ||
        t.ownerId === userId
      ) {
        ids.add(t.id);
      }
    }
    return ids;
  }, [allTeams, userId]);

  const scopeToLedTeamsOnly = React.useMemo(
    () => shouldScopeSalesTargetsToLedTeamsOnly(permissionSource, allTeams),
    [permissionSource, allTeams],
  );

  const canAssignReps = React.useMemo(
    () => canManageSalesTargetsInApp(permissionSource, allTeams),
    [permissionSource, allTeams],
  );

  const visibleTeams = React.useMemo(() => {
    if (!scopeToLedTeamsOnly) return allTeams;
    return allTeams.filter((t) => ledTeamIds.has(t.id));
  }, [allTeams, scopeToLedTeamsOnly, ledTeamIds]);

  const { data: salesTargetMonths = [] } = useGetSalesTargetMonthsQuery(year, {
    skip: !allowed || scopeToLedTeamsOnly,
  });

  const calendarCap = React.useMemo(() => {
    const today = new Date();
    return { year: today.getFullYear(), month: today.getMonth() + 1 };
  }, []);

  const nextMonthDisabled =
    compareYearMonth({ year, month }, calendarCap) >= 0;

  const assignableTeams = visibleTeams;

  const openAssignModal = React.useCallback((teamId?: string) => {
    setAssignTeamId(teamId);
    setAssignModalOpen(true);
  }, []);

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

  const [createMonth, { isLoading: creatingMonth }] =
    useCreateSalesTargetMonthMutation();
  const [copyPreviousMonth, { isLoading: copyingPreviousMonth }] =
    useCopyPreviousSalesTargetMonthMutation();
  const [exportPdf, { isFetching: exportingPdf }] =
    useLazyExportSalesTargetsPdfQuery();

  const isSelectedMonthInitialized = React.useMemo(
    () => salesTargetMonths.some((m) => m.year === year && m.month === month),
    [salesTargetMonths, year, month],
  );

  const {
    data: targetsData,
    isLoading: targetsLoading,
    isError: targetsError,
    error: targetsQueryError,
    refetch,
    isFetching: targetsFetching,
  } = useGetTeamSalesTargetsQuery(
    { year, month },
    salesTargetsLiveQueryOptions,
  );

  const {
    data: attainmentSummary,
    isLoading: attainmentLoading,
    isError: attainmentError,
    refetch: refetchAttainment,
    isFetching: attainmentFetching,
  } = useGetAeAttainmentSummaryQuery(
    { year, month },
    salesTargetsLiveQueryOptions,
  );

  const refreshing = targetsFetching || attainmentFetching;

  const handleRefresh = React.useCallback(() => {
    void Promise.all([refetch(), refetchAttainment()]);
  }, [refetch, refetchAttainment]);

  const teamLeadUserIdsByTeam = React.useMemo(() => {
    const map = new Map<string, Set<string>>();
    for (const t of allTeams) {
      const ids = new Set<string>();
      const leadUserId = t.teamLead?.userId?.trim();
      if (leadUserId) ids.add(leadUserId);
      const ownerId = (t.ownerId ?? t.lead)?.trim();
      if (ownerId) ids.add(ownerId);
      map.set(t.id, ids);
    }
    return map;
  }, [allTeams]);

  const attainmentByTeam = React.useMemo(() => {
    const m = new Map<
      string,
      { attained: number; pct: number | null; target: number | null }
    >();
    for (const t of attainmentSummary?.teams ?? []) {
      if (scopeToLedTeamsOnly && !ledTeamIds.has(t.teamId)) continue;
      m.set(t.teamId, {
        attained: t.attained,
        pct: t.pct,
        target: t.target,
      });
    }
    return m;
  }, [attainmentSummary, scopeToLedTeamsOnly, ledTeamIds]);

  const membersByTeam = React.useMemo(() => {
    const m = new Map<
      string,
      ReturnType<typeof buildTeamMemberAttainmentList>
    >();
    for (const t of attainmentSummary?.teams ?? []) {
      if (scopeToLedTeamsOnly && !ledTeamIds.has(t.teamId)) continue;
      m.set(
        t.teamId,
        buildTeamMemberAttainmentList(
          t.teamId,
          t.byMember,
          teamLeadUserIdsByTeam,
          t.teamLeads,
        ),
      );
    }
    return m;
  }, [
    attainmentSummary,
    scopeToLedTeamsOnly,
    ledTeamIds,
    teamLeadUserIdsByTeam,
  ]);

  const teamFilterOptions = React.useMemo(
    () =>
      [...visibleTeams]
        .map((t) => ({ id: t.id, name: t.name }))
        .sort((a, b) => a.name.localeCompare(b.name)),
    [visibleTeams],
  );

  const firstTeamFilterId = teamFilterOptions[0]?.id ?? "";

  React.useEffect(() => {
    if (!firstTeamFilterId) {
      // eslint-disable-next-line react-hooks/set-state-in-effect
      setTeamFilterId(scopeToLedTeamsOnly ? "" : "all");
      return;
    }
    setTeamFilterId(scopeToLedTeamsOnly ? firstTeamFilterId : "all");
  }, [year, month, firstTeamFilterId, scopeToLedTeamsOnly]);

  const showTeamFilter =
    !scopeToLedTeamsOnly || teamFilterOptions.length > 1;

  const matchesTeamFilter = React.useCallback(
    (teamId: string) => teamFilterId === "all" || teamFilterId === teamId,
    [teamFilterId],
  );

  const allTeamRows = React.useMemo(() => {
    if (!targetsData?.teams) return [];
    const rows = Object.values(buildRowStateFromTargets(targetsData.teams)).filter(
      (row) => (scopeToLedTeamsOnly ? ledTeamIds.has(row.teamId) : true),
    );
    return rows.sort((a, b) => a.teamName.localeCompare(b.teamName));
  }, [targetsData, scopeToLedTeamsOnly, ledTeamIds]);

  const teamLeadSummaryCards = React.useMemo(() => {
    const list = (attainmentSummary?.teams ?? []).filter(
      (t) =>
        (scopeToLedTeamsOnly ? ledTeamIds.has(t.teamId) : true) &&
        matchesTeamFilter(t.teamId),
    );
    return [...list].sort((a, b) => a.teamName.localeCompare(b.teamName));
  }, [attainmentSummary, scopeToLedTeamsOnly, ledTeamIds, matchesTeamFilter]);

  const teamLeadSummary = React.useMemo((): SalesTargetsSummaryData => {
    let totalTarget = 0;
    let totalAttained = 0;
    let teamsWithTarget = 0;
    let pctSum = 0;
    let pctCount = 0;

    for (const t of teamLeadSummaryCards) {
      if (t.target != null && t.target > 0) {
        totalTarget += t.target;
        teamsWithTarget += 1;
      }
      totalAttained += t.attained ?? 0;
      if (t.pct != null && !Number.isNaN(t.pct)) {
        pctSum += t.pct;
        pctCount += 1;
      }
    }

    return {
      teamCount: teamLeadSummaryCards.length,
      teamsWithTarget,
      totalTarget,
      totalAttained,
      avgPct: pctCount > 0 ? pctSum / pctCount : null,
    };
  }, [teamLeadSummaryCards]);

  const monthLabel =
    targetsData?.label ??
    attainmentSummary?.teams?.[0]?.label ??
    format(new Date(year, month - 1, 1), "MMMM yyyy");

  const monthTargetLagKpi = React.useMemo(() => {
    const { totalTarget, totalAttained } = teamLeadSummary;
    if (totalTarget <= 0) return undefined;
    return {
      lag: Math.max(0, totalTarget - totalAttained),
      target: totalTarget,
      attained: totalAttained,
      monthLabel,
    };
  }, [teamLeadSummary, monthLabel]);

  const assignMemberTargetSeed = React.useMemo(() => {
    const teamId =
      assignTeamId ??
      (assignableTeams.length === 1 ? assignableTeams[0]?.id : undefined);
    if (!teamId) return undefined;
    const members = membersByTeam.get(teamId);
    if (!members?.length) return undefined;
    return Object.fromEntries(members.map((m) => [m.userId, m.target]));
  }, [assignTeamId, assignableTeams, membersByTeam]);

  const monthNeedsInit =
    !scopeToLedTeamsOnly && targetsError && !targetsData && !isSelectedMonthInitialized;

  const exportPdfDisabled =
    scopeToLedTeamsOnly
      ? attainmentError && !attainmentSummary
      : targetsError && !targetsData;

  const handleExportPdf = React.useCallback(async () => {
    if (!showExportPdf) return;
    if (exportPdfDisabled) {
      toast.error(
        scopeToLedTeamsOnly
          ? "Load team progress before exporting."
          : "Initialize this month or load targets before exporting.",
      );
      return;
    }

    const slug = (value: string) =>
      value
        .toLowerCase()
        .replace(/[^a-z0-9]+/g, "-")
        .replace(/^-|-$/g, "")
        .slice(0, 40);
    const filename = `sales-targets_${slug(monthLabel)}.pdf`;
    const toastId = toast.loading("Generating sales targets PDF…");

    try {
      const blob = await exportPdf({ year, month }).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 });
    }
  }, [exportPdf, exportPdfDisabled, month, monthLabel, scopeToLedTeamsOnly, showExportPdf, year]);

  const handleEnsureMonth = React.useCallback(async () => {
    try {
      await createMonth({ year, month }).unwrap();
      toast.success(`${monthLabel} initialized`);
      void refetch();
    } catch (e: unknown) {
      const msg =
        e && typeof e === "object" && "data" in e
          ? String((e as { data?: { message?: string } }).data?.message ?? "Failed")
          : "Failed to initialize month";
      toast.error(msg);
    }
  }, [createMonth, month, monthLabel, refetch, year]);

  const showCopyPreviousMonth = React.useMemo(
    () => canAddMonth && canSetTeamLevelSalesTarget(permissionSource, allTeams),
    [canAddMonth, permissionSource, allTeams],
  );

  const handleCopyPreviousMonth = React.useCallback(async () => {
    try {
      await copyPreviousMonth({ year, month }).unwrap();
      toast.success(`${monthLabel} copied from previous month`);
      void Promise.all([refetch(), refetchAttainment()]);
    } catch (e: unknown) {
      const msg =
        e && typeof e === "object" && "data" in e
          ? String((e as { data?: { message?: string } }).data?.message ?? "Failed")
          : "Failed to copy previous month";
      toast.error(msg);
    }
  }, [copyPreviousMonth, month, monthLabel, refetch, refetchAttainment, year]);

  const assignRepTargetsDisabled = !scopeToLedTeamsOnly && monthNeedsInit;

  const handleOpenAssignReps = React.useCallback(
    (teamId?: string) => {
      if (assignRepTargetsDisabled) {
        toast.error(`Initialize ${monthLabel} before assigning rep targets.`);
        return;
      }
      openAssignModal(teamId);
    },
    [assignRepTargetsDisabled, monthLabel, openAssignModal],
  );

  const teamLeadCardsForBody = React.useMemo(
    () =>
      teamLeadSummaryCards.map((team) => ({
        teamId: team.teamId,
        teamName: team.teamName,
        target: team.target,
        attained: team.attained,
        pct: team.pct,
        byMember: team.byMember,
        teamLeads: team.teamLeads,
      })),
    [teamLeadSummaryCards],
  );

  const summaryLoadingPartial =
    refreshing && (scopeToLedTeamsOnly ? !attainmentSummary : !targetsData);

  const headerState = React.useMemo(
    (): SalesTargetsPageHeaderState => ({
      scopeToLedTeamsOnly,
      monthLabel,
      refreshing,
      creatingMonth,
      copyingPreviousMonth,
      exportingPdf,
      exportPdfDisabled,
      showExportPdf,
      monthNeedsInit,
      selectedMonthInitialized: isSelectedMonthInitialized,
      canAddMonth,
      showCopyPreviousMonth,
      showAssignRepTargetsButton: canAssignReps && assignableTeams.length > 0,
      assignRepTargetsDisabled,
      previousMonthDisabled: false,
      nextMonthDisabled,
      teamFilterId: teamFilterId || teamFilterOptions[0]?.id || "all",
      teamFilterOptions,
      showTeamFilter,
    }),
    [
      scopeToLedTeamsOnly,
      monthLabel,
      refreshing,
      creatingMonth,
      copyingPreviousMonth,
      exportingPdf,
      exportPdfDisabled,
      showExportPdf,
      monthNeedsInit,
      isSelectedMonthInitialized,
      canAddMonth,
      showCopyPreviousMonth,
      canAssignReps,
      assignableTeams.length,
      assignRepTargetsDisabled,
      nextMonthDisabled,
      teamFilterId,
      teamFilterOptions,
      showTeamFilter,
    ],
  );

  const headerActions = React.useMemo(
    (): SalesTargetsPageHeaderActions => ({
      onOpenAssignReps: () => handleOpenAssignReps(),
      onRefresh: () => void handleRefresh(),
      onExportPdf: () => void handleExportPdf(),
      onEnsureMonth: () => void handleEnsureMonth(),
      onCopyPreviousMonth: () => void handleCopyPreviousMonth(),
      onPreviousMonth: goPreviousMonth,
      onNextMonth: goNextMonth,
      onTeamFilterChange: setTeamFilterId,
    }),
    [
      goPreviousMonth,
      goNextMonth,
      handleRefresh,
      handleExportPdf,
      handleEnsureMonth,
      handleCopyPreviousMonth,
      handleOpenAssignReps,
    ],
  );

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

  if (scopeToLedTeamsOnly) {
    if (attainmentLoading && !attainmentSummary) {
      return (
        <Loading variant="api" layout="page" message="Loading team progress..." />
      );
    }
  } else if (targetsLoading && !targetsData) {
    return <Loading variant="api" layout="page" message="Loading sales targets..." />;
  }

  return (
    <div className="relative mx-auto flex h-full min-h-0 w-full max-w-[1600px] flex-1 flex-col gap-5 overflow-y-auto pb-6 scrollbar-themed animate-in fade-in duration-500 md:gap-6">
      <SalesTargetsPageHeader state={headerState} actions={headerActions} />

      <section aria-label="Daily sales benchmarks">
        <SalesTargetsSalesDailyKpiGrid monthTargetLag={monthTargetLagKpi} />
      </section>

      {assignModalOpen && (
        <AssignRepTargetsModal
          open={assignModalOpen}
          onOpenChange={(open) => {
            setAssignModalOpen(open);
            if (!open) setAssignTeamId(undefined);
          }}
          year={year}
          month={month}
          teams={assignableTeams}
          initialTeamId={assignTeamId ?? assignableTeams[0]?.id}
          lockTeam={Boolean(assignTeamId) || assignableTeams.length === 1}
          memberTargetSeed={assignMemberTargetSeed}
          onSaved={() => {
            void refetch();
            void refetchAttainment();
          }}
        />
      )}

      {scopeToLedTeamsOnly && attainmentError && !attainmentSummary ? (
        <div className="rounded-xl border border-destructive/40 bg-destructive/5 p-4 text-sm">
          <p className="font-medium text-destructive">
            Could not load team progress for this month.
          </p>
          <Button
            type="button"
            size="sm"
            variant="outline"
            className="mt-3"
            onClick={() => void refetchAttainment()}
          >
            Retry
          </Button>
        </div>
      ) : !scopeToLedTeamsOnly && targetsError && !targetsData ? (
        <div className="rounded-xl border border-destructive/40 bg-destructive/5 p-4 text-sm">
          <p className="font-medium text-destructive">
            Could not load targets for {monthLabel}.
          </p>
          <p className="mt-1 text-muted-foreground">
            {targetsQueryError &&
            "data" in targetsQueryError &&
            targetsQueryError.data &&
            typeof targetsQueryError.data === "object" &&
            "message" in targetsQueryError.data
              ? String((targetsQueryError.data as { message?: unknown }).message)
              : "This period may not exist yet. Initialize the month to load teams."}
          </p>
          <div className="mt-3 flex flex-wrap gap-2">
            {canAddMonth && (
              <Button
                type="button"
                size="sm"
                variant="default"
                disabled={creatingMonth}
                onClick={() => void handleEnsureMonth()}
              >
                <CalendarPlus className="mr-1 h-4 w-4" />
                Initialize {monthLabel}
              </Button>
            )}
            <Button
              type="button"
              size="sm"
              variant="outline"
              onClick={() => void refetch()}
            >
              Retry
            </Button>
          </div>
        </div>
      ) : scopeToLedTeamsOnly ? (
        teamLeadSummaryCards.length === 0 ? (
          <NoDataFound
            message="No team target data"
            description="No target or attainment for your team this month yet."
          />
        ) : (
          <SalesTargetsBody
            scopeToLedTeamsOnly
            monthLabel={monthLabel}
            summary={teamLeadSummary}
            summaryLoading={summaryLoadingPartial}
            overviewTeamRows={[]}
            attainmentByTeam={attainmentByTeam}
            membersByTeam={membersByTeam}
            membersLoading={attainmentLoading && !attainmentSummary}
            permissionSource={permissionSource}
            allTeams={allTeams}
            canAssignReps={canAssignReps}
            onAssignTeam={handleOpenAssignReps}
            teamFilterId={teamFilterId || teamFilterOptions[0]?.id || ""}
            onTeamFilterChange={setTeamFilterId}
            teamLeadCards={teamLeadCardsForBody}
            teamLeadUserIdsByTeam={teamLeadUserIdsByTeam}
          />
        )
      ) : allTeamRows.length === 0 ? (
        <NoDataFound
          message="No teams to set targets on"
          description={`Add active teams under Teams, then initialize ${monthLabel} if this period is new.`}
        />
      ) : (
        <SalesTargetsAdminPanel
          monthLabel={monthLabel}
          overviewTeamRows={allTeamRows}
          attainmentByTeam={attainmentByTeam}
          attainmentTeams={attainmentSummary?.teams}
          attainmentLoading={attainmentLoading && !attainmentSummary}
          membersByTeam={membersByTeam}
          membersLoading={attainmentLoading && !attainmentSummary}
          summaryLoading={summaryLoadingPartial}
          permissionSource={permissionSource}
          allTeams={allTeams}
          canAssignReps={canAssignReps}
          onAssignTeam={handleOpenAssignReps}
          teamFilterId={teamFilterId}
          onTeamFilterChange={setTeamFilterId}
          periodYear={year}
          periodMonth={month}
        />
      )}
    </div>
  );
}
