"use client";

import * as React from "react";
import { useQueryState, parseAsString } from "nuqs";
import { useRouter } from "next/navigation";
import { useAppSelector, useAppDispatch } from "@/store/hooks";
import {
  openDealsAddModal,
  openDealsEditModal,
  openDealsPipelineModal,
  closeDealsModals,
} from "@/store/slices/deals-modals-slice";
import {
  clearDealsModalsHandlers,
  setDealsModalsHandlers,
} from "@/lib/deals-modals-handlers-store";
import {
  clearDealsContentHandlers,
  setDealsContentHandlers,
} from "@/lib/deals-content-handlers-store";
import {
  dealsPipelineContentInitialState,
  replaceDealsPipelineContentState,
} from "@/store/slices/deals-pipeline-content-slice";
import { useAuthToken } from "@/hooks/use-auth-token"
import {
  useGetPipelinesQuery,
  useCreatePipelineMutation,
  useUpdatePipelineMutation,
} from "@/api/rtk/pipelines-api";
import {
  useGetDealsQuery,
  useCreateDealMutation,
  useUpdateDealMutation,
  useMoveDealMutation,
  useReorderDealsInStageMutation,
  useDeleteDealMutation,
  useLazyExportDealsToCSVQuery,
} from "@/api/rtk/deals-api";
import { useGetTeamsQuery } from "@/api/rtk/teams-api";
import { useGetConvertedDealIdsQuery } from "@/api/rtk/deals-api";
import { useGetProfileQuery } from "@/api/rtk/auth-api";
import { selectDealsByPipeline } from "@/store/slices/deals-slice";
import { selectSelectedTeam } from "@/store/slices/team-filter-slice";
import { teamFilterQueryParams } from "@/lib/team-filter";
import { setView as setHeaderView } from "@/store/slices/deals-header-slice";
import { DealsPageHeader } from "./deals-page-header";
import { DealsContent } from "./deals-content";
import { DealsModals } from "./deals-modals";
import type { Deal } from "@/components/deals/types";
import { Stage } from "@/api/rtk/pipelines-api";
import { toast } from "sonner";
import {
  canSeeAllTeamsInApp,
  filterTeamsVisibleToUser,
  isAdminUser,
  type PermissionSource,
} from "@/lib/permissions";
import { useSession } from "next-auth/react";

export interface DealsPipelinePageProps {
  /** Main heading (e.g. "Leads Pipeline" vs "Pipeline"). */
  pageTitle?: string;
}

export function DealsPipelinePage({ pageTitle = "Leads Pipeline" }: DealsPipelinePageProps) {
  const { token } = useAuthToken();
  const { data: session } = useSession();
  const router = useRouter();
  const dispatch = useAppDispatch();
  const { data: pipelines, isLoading: pipelinesLoading, refetch: refetchPipelines } = useGetPipelinesQuery(undefined, {
    skip: !token,
    refetchOnFocus: true,
  });
  const [createPipeline, { isLoading: isCreatingPipeline }] = useCreatePipelineMutation();
  const [updatePipeline] = useUpdatePipelineMutation();

  const [pipelineParam, setPipelineParam] = useQueryState("pipeline", parseAsString);
  const [viewParam, setViewParam] = useQueryState("view", parseAsString.withDefault("grid"));
  const view: 'kanban' | 'list' = (viewParam === 'table' || viewParam === 'list') ? 'list' : 'kanban';
  const setView = (v: 'kanban' | 'list') => setViewParam(v === 'list' ? 'table' : 'grid');

  const firstPipelineId = pipelines?.[0]?.id ?? null;
  const activeBoardId = (() => {
    if (pipelineParam && pipelines?.some((p) => p.id === pipelineParam)) return pipelineParam;
    return firstPipelineId;
  })();

  // Sync default pipeline to URL only when pipelines exist and no pipeline in URL
  React.useEffect(() => {
    if (pipelines?.length && !pipelineParam && firstPipelineId) {
      setPipelineParam(firstPipelineId);
    }
  }, [pipelines, pipelineParam, firstPipelineId, setPipelineParam]);

  // Sync default view (grid) to URL when view param is missing
  React.useEffect(() => {
    if (viewParam === null || viewParam === undefined || viewParam === '') {
      setViewParam('grid');
    }
  }, [viewParam, setViewParam]);

  const teamFilterSlug = useAppSelector(selectSelectedTeam);
  const teamFilterParams = teamFilterQueryParams(teamFilterSlug);

  const { data: apiDeals, refetch: refetchDeals, isLoading: dealsLoading, isFetching: dealsFetching } = useGetDealsQuery(
    { pipelineId: activeBoardId || undefined, ...teamFilterParams },
    { skip: !activeBoardId || !token }
  );
  const persistedDeals = useAppSelector(selectDealsByPipeline(activeBoardId, teamFilterSlug));
  const deals: any[] = Array.isArray(apiDeals) ? apiDeals : Array.isArray(persistedDeals) ? persistedDeals : [];
  const [createDeal, { isLoading: isCreatingDeal }] = useCreateDealMutation();
  const [updateDeal, { isLoading: isUpdatingDeal }] = useUpdateDealMutation();
  const [moveDeal, { isLoading: isMovingDeal }] = useMoveDealMutation();
  const [reorderDealsInStage, { isLoading: isReorderingDeal }] = useReorderDealsInStageMutation();
  const [deleteDealMutation, { isLoading: isDeletingDeal }] = useDeleteDealMutation();
  const [triggerExportCSV, { isLoading: isExporting }] = useLazyExportDealsToCSVQuery();

  const { data: teams } = useGetTeamsQuery(undefined, { skip: !token });
  const { data: convertedIdsList } = useGetConvertedDealIdsQuery(undefined, { skip: !token });
  const { data: profile } = useGetProfileQuery(undefined, { skip: !token });
  const backendUser = (session as { backendUser?: PermissionSource } | null)?.backendUser;
  const convertedDealIds = React.useMemo(
    () => new Set((convertedIdsList ?? []) as string[]),
    [convertedIdsList]
  );

  const [search, setSearch] = React.useState("");

  const availableTeams = React.useMemo(() => {
    if (teams == null) return [];
    const permissionSource: PermissionSource = backendUser ?? profile ?? null;
    const viewerId =
      profile?.id ??
      (typeof backendUser === "object" && backendUser !== null && "id" in backendUser
        ? String((backendUser as { id: string }).id)
        : "");
    if (!canSeeAllTeamsInApp(permissionSource) && !viewerId) return [];
    return filterTeamsVisibleToUser(teams, viewerId, permissionSource);
  }, [teams, profile, backendUser]);

  const isAdmin = React.useMemo(() => isAdminUser(profile), [profile]);

  // Refetch deals when team filter changes
  React.useEffect(() => {
    if (activeBoardId && token) {
      refetchDeals();
    }
  }, [teamFilterSlug, activeBoardId, token, refetchDeals]);

  const rawBoard = pipelines?.find(b => b.id === activeBoardId) ?? { stages: [] as Stage[], name: "" };
  const COLORS = ['#6C63FF', '#8B83FF', '#F59E0B', '#FF8C42', '#22C55E', '#FF6B6B', '#10B981', '#3B82F6'];

  // Stage processing logic (simplified for this example)
  const normalizeStageId = (id: string) =>
    String(id ?? "").trim().toLowerCase().replace(/\s+/g, "_");

  const baseStages: any[] = (rawBoard.stages ?? []).map((stage: unknown, i: number) => {
    if (typeof stage === "string") {
      const id = normalizeStageId(stage);
      return {
        id,
        name: stage,
        color: COLORS[i % COLORS.length],
        prob: Math.min(100, (i + 1) * 20),
      }
    }
    const s = stage as { id?: string; name?: string; color?: string; prob?: number };
    const id = normalizeStageId(s.id ?? s.name ?? "");
    return {
      id,
      name: s.name ?? id,
      color: s.color ?? COLORS[i % COLORS.length],
      prob: typeof s.prob === "number" ? s.prob : Math.min(100, (i + 1) * 20),
    }
  });

  // Ensure every deal.stage has a column
  const activeBoardStages = (() => {
    const byId = new Map<string, any>();
    baseStages.forEach((s) => byId.set(s.id, s));
    deals.forEach((d) => {
      const stageId = d?.stage != null ? String(d.stage).trim() : "";
      if (stageId && !byId.has(stageId)) {
        const label = stageId.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
        byId.set(stageId, {
          id: stageId,
          name: label,
          color: COLORS[byId.size % COLORS.length],
          prob: stageId === "closed_won" ? 100 : stageId === "closed_lost" ? 0 : 50,
        });
      }
    });
    const list = Array.from(byId.values());
    return list.length > 0 ? list : baseStages.length > 0 ? baseStages : [];
  })();

  const activeBoard = {
    ...rawBoard,
    stages: activeBoardStages,
  };

  const filteredDeals = deals.filter(d => {
    const matchesSearch = !search || 
      d.customerName?.toLowerCase().includes(search.toLowerCase()) ||
      d.companyName?.toLowerCase().includes(search.toLowerCase());
    return matchesSearch;
  });

  // Event handlers
  const handlePipelineChange = (value: string) => {
    if (value === "new-pipeline") {
      dispatch(openDealsPipelineModal());
    } else {
      void setPipelineParam(value);
    }
  };

  const handleAddPipeline = () => {
    dispatch(openDealsPipelineModal());
  };

  const handleRefresh = () => {
    refetchPipelines();
    refetchDeals();
  };

  const handleExport = async () => {
    try {
      const blob = await triggerExportCSV().unwrap();
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = `all-deals-export-${new Date().toISOString().split("T")[0]}.csv`;
      a.click();
      URL.revokeObjectURL(url);
      toast.success("All deals exported to CSV");
    } catch (error: unknown) {
      console.error("Export failed:", error);
      const status =
        error &&
        typeof error === "object" &&
        "status" in error &&
        typeof (error as { status: unknown }).status === "number"
          ? (error as { status: number }).status
          : undefined;
      if (status === 403) {
        toast.error(
          "Export not allowed. Ask an admin to grant READ on EXCEL_EXPORT for your role.",
        );
        return;
      }
      const message =
        typeof error === "object" && error !== null
          ? (error as { data?: { message?: string }; message?: string }).data
              ?.message ||
            (error as { message?: string }).message ||
            "Failed to export deals"
          : "Failed to export deals";
      toast.error(message);
    }
  };

  const handleAddDeal = () => {
    dispatch(openDealsAddModal(undefined));
  };

  const handleModalCreateDeal = React.useCallback(
    async (d: Partial<Deal>) => {
      await createDeal(d as never).unwrap();
      void refetchDeals();
    },
    [createDeal, refetchDeals],
  );

  const handleModalSaveDeal = React.useCallback(
    async (d: Deal) => {
      await updateDeal({ id: d.id as string, body: d as never }).unwrap();
      dispatch(closeDealsModals());
      void refetchDeals();
    },
    [dispatch, refetchDeals, updateDeal],
  );

  const handleModalCreatePipeline = React.useCallback(
    async (
      name: string,
      isPublic?: boolean,
      moduleDependencies?: string[],
    ) => {
      const result = await createPipeline({
        name,
        isPublic,
        moduleDependencies,
      } as never).unwrap();
      void setPipelineParam(result.id ?? null);
      dispatch(closeDealsModals());
      toast.success(`Pipeline created: ${name}`);
    },
    [createPipeline, dispatch, setPipelineParam],
  );

  React.useEffect(() => {
    setDealsModalsHandlers({
      onCreateDeal: handleModalCreateDeal,
      onSaveDeal: handleModalSaveDeal,
      onCreatePipeline: handleModalCreatePipeline,
    });
    return () => {
      clearDealsModalsHandlers();
    };
  }, [handleModalCreateDeal, handleModalCreatePipeline, handleModalSaveDeal]);

  const boardUiKey = `legacy::${activeBoardId ?? "default"}::${teamFilterSlug || "all"}`;

  React.useEffect(() => {
    dispatch(setHeaderView(view));
  }, [dispatch, view]);

  React.useEffect(() => {
    dispatch(
      replaceDealsPipelineContentState({
        ...dealsPipelineContentInitialState,
        pipelinesLoading,
        dealsLoading,
        dealsFetching,
        pipelineCount: pipelines?.length ?? 0,
        convertedDealIdList: Array.from(convertedDealIds),
        isAdmin,
        isAddingStage: false,
        isMovingDeal,
        isReorderingDeal,
        assignTaskEnabled: true,
      }),
    );
  }, [
    dispatch,
    pipelinesLoading,
    dealsLoading,
    dealsFetching,
    pipelines?.length,
    convertedDealIds,
    isAdmin,
    isMovingDeal,
    isReorderingDeal,
  ]);

  React.useEffect(() => {
    setDealsContentHandlers({
      onCreatePipeline: handleAddPipeline,
      onOpenDeal: (deal) => {
        router.push(`/leads/${deal.id}`);
      },
      onEditDeal: (deal) => {
        dispatch(openDealsEditModal({ deal }));
      },
      onDeleteDeal: (id) => {
        void deleteDealMutation(id);
      },
      onMoveDeal: (id, stage) => {
        void moveDeal({
          id,
          stageId: stage,
          prob: 50,
          pipelineId: activeBoardId || undefined,
        });
      },
      onReorderInStage: (stageId, dealIds) => {
        void reorderDealsInStage({
          stageId,
          dealIds,
          pipelineId: activeBoardId || undefined,
        });
      },
      onAddStage: () => {},
      onAssignTask: (deal) => {
        router.push(`/leads/${deal.id}?tab=tasks`);
      },
      onSort: () => {},
    });
    return () => {
      clearDealsContentHandlers();
    };
  }, [
    activeBoardId,
    deleteDealMutation,
    dispatch,
    handleAddPipeline,
    moveDeal,
    reorderDealsInStage,
    router,
  ]);

  return (
    <div className="flex flex-col h-full bg-background">
      <DealsPageHeader
        pageTitle={pageTitle}
        filteredDealsCount={filteredDeals.length}
        pipelines={pipelines}
        activeBoardId={activeBoardId}
      />

      <DealsContent
        sortedDeals={filteredDeals}
        activeBoard={activeBoard}
        boardUiKey={boardUiKey}
        boardListParams={{
          pipelineId: activeBoardId ?? undefined,
          stageType: "Lead",
        }}
      />

      <DealsModals
        stages={activeBoard.stages as never}
        pipelineId={activeBoardId}
        boardUiKey={boardUiKey}
      />
    </div>
  );
}
