"use client";

import * as React from "react";
import { useQueryState, parseAsInteger, parseAsString } from "nuqs";
import {
  GitBranch,
  Layers,
  Search,
  RefreshCw,
  Plus,
} from "lucide-react";
import {
  usePipelines,
  usePipelineStages,
  useCreatePipelineStage,
  useCreateSubStage,
  useUpdateSubStage,
  useDeleteSubStage,
  useUpdatePipeline,
  useUpdatePipelineStage,
} from "@/hooks/use-pipeline-stages";
import type { Stage, SubStage } from "@/api/rtk/pipelines-api";
import { useGetProfileQuery } from "@/api/rtk/auth-api";
import { useAppSelector, useAppDispatch } from "@/store/hooks";
import { useAuthToken } from "@/hooks/use-auth-token"
import {
  selectEditStageDialog,
  openEditDialog,
  closeEditDialog,
} from "@/store/slices/edit-stage-slice";
import {
  selectAddStageDialog,
  closeAddDialog,
  openAddDialog,
} from "@/store/slices/add-stage-slice";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Skeleton } from "@/components/ui/skeleton";
import { ReactSelect } from "@/components/ui/react-select";
import { toast } from "sonner";
import { DeleteDialog } from "@/components/ui/delete-dialog";
import { EditStageDialog } from "@/components/dialog/edit-stage-dialog";
import { AddStageDialog } from "@/components/dialog/add-stage-dialog";
import { SubStageDialog } from "@/components/dialog/sub-stage-dialog";
import { StagesTable } from "@/components/table/stages-table";
import { hasPermission } from "@/lib/permissions";
import { useSession } from "next-auth/react";
import { cn } from "@/lib/utils";

type StagesPageProps = {
  embedded?: boolean;
};

const PAGE_SIZE = 10;
const SEARCH_DEBOUNCE_MS = 400;

export default function StagesPage({ embedded = false }: StagesPageProps) {
  const { token } = useAuthToken();
  const { data: session } = useSession();
  const dispatch = useAppDispatch();
  const editState = useAppSelector(selectEditStageDialog);
  const addState = useAppSelector(selectAddStageDialog);
  const { data: profile } = useGetProfileQuery(undefined, { skip: !token });
  const permissionSource = (session as { backendUser?: unknown } | null)?.backendUser ?? profile;
  const canCreateStage = hasPermission(permissionSource, ["CREATE", "UPDATE"], "PIPELINE");
  const canUpdateStage = hasPermission(permissionSource, "UPDATE", "PIPELINE");
  const canDeleteStage = hasPermission(permissionSource, "DELETE", "PIPELINE");
  const canManageStages = canCreateStage || canUpdateStage || canDeleteStage;

  const [q, setQ] = useQueryState("q", parseAsString.withDefault(""));
  const [pipelineId, setPipelineId] = useQueryState(
    "pipelineId",
    parseAsString,
  );
  const [stageTypeFilter, setStageTypeFilter] = useQueryState(
    "stageType",
    parseAsString,
  );
  const [page, setPage] = useQueryState("page", parseAsInteger.withDefault(1));

  const [searchInput, setSearchInput] = React.useState(q);
  const searchDebounceRef = React.useRef<ReturnType<typeof setTimeout> | null>(
    null,
  );

  React.useEffect(() => {
    setSearchInput(q);
  }, [q]);

  const applySearchToUrl = React.useCallback(
    (value: string) => {
      void setQ(value === "" ? null : value);
      void setPage(1);
    },
    [setQ, setPage],
  );

  const handleSearchChange = React.useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const value = e.target.value;
      setSearchInput(value);
      if (searchDebounceRef.current) clearTimeout(searchDebounceRef.current);
      searchDebounceRef.current = setTimeout(() => {
        searchDebounceRef.current = null;
        applySearchToUrl(value);
      }, SEARCH_DEBOUNCE_MS);
    },
    [applySearchToUrl],
  );

  React.useEffect(
    () => () => {
      if (searchDebounceRef.current) clearTimeout(searchDebounceRef.current);
    },
    [],
  );

  const pipelinesQuery = usePipelines();
  const pipelinesRaw = (pipelinesQuery.data as any)?.data ?? pipelinesQuery.data;
  const pipelines = Array.isArray(pipelinesRaw) ? pipelinesRaw : [];


  const {
    data: stagesPage,
    isLoading,
    isFetching,
  } = usePipelineStages({
    search: q.trim() || undefined,
    pipelineId: pipelineId ?? undefined,
    stageType:
      stageTypeFilter === "Lead" || stageTypeFilter === "Deal"
        ? stageTypeFilter
        : undefined,
    page,
    limit: PAGE_SIZE,
  });

  // Handle wrapped response: { success, message, data: { data, total, ... } }
  const paginatedData = (stagesPage as any)?.data;
  const rows = paginatedData?.data ?? [];
  const total = paginatedData?.total ?? 0;
  const totalPages = Math.max(1, paginatedData?.totalPages ?? 1);

  const [deleteRowId, setDeleteRowId] = React.useState<string | null>(null);
  const [subStageDialog, setSubStageDialog] = React.useState<any | null>(null);
  const [subStageName, setSubStageName] = React.useState("");
  const [editingSubStage, setEditingSubStage] = React.useState<{
    row: any;
    subStage: SubStage;
  } | null>(null);
  const [deleteSubStageState, setDeleteSubStageState] = React.useState<{
    row: any;
    subStage: SubStage;
  } | null>(null);
  const [editSubStageName, setEditSubStageName] = React.useState("");

  const createStageMutation = useCreatePipelineStage(addState.addPipelineId ?? "");
  const updateStageMutation = useUpdatePipelineStage(editState.editPipelineId ?? "", editState.editingRowId ?? "");
  const deleteStageMutation = useUpdatePipeline();
  const createSubStageMutation = useCreateSubStage();
  const updateSubStageMutation = useUpdateSubStage();
  const deleteSubStageMutation = useDeleteSubStage();

  const getPipelineStages = React.useCallback(
    (targetPipelineId: string) => {
      const stages = pipelines.find((p: any) => p.id === targetPipelineId)?.stages;
      if (!Array.isArray(stages)) return [];
      return stages.filter((stage: any) => {
        if (!stage || typeof stage !== "object") return false;
        const candidate = stage as unknown as Record<string, unknown>;
        return (
          typeof candidate.id === "string" &&
          typeof candidate.name === "string"
        );
      }) as Stage[];
    },
    [pipelines],
  );

  const getStageSubStages = React.useCallback(
    (row: any): SubStage[] => {
      const stage = pipelines
        .find((pipeline: any) => pipeline.id === row.pipelineId)
        ?.stages?.find((candidate: any) => candidate.id === row.id);

      return Array.isArray(stage?.subStages) ? stage.subStages : [];
    },
    [pipelines],
  );

  const handlePipelineFilterChange = (value: string) => {
    void setPipelineId(value === "all" ? null : value);
    void setPage(1);
  };

  const handleAddStage = async (e: React.FormEvent) => {
    e.preventDefault();
    const trimmedName = addState.addName.trim();
    if (!trimmedName) {
      toast.error("Please enter a stage name");
      return;
    }
    if (!addState.addPipelineId) {
      toast.error("Select a pipeline");
      return;
    }

    try {
      if (!canCreateStage) {
        toast.error("You don't have permission to add stages");
        return;
      }
      await createStageMutation.mutateAsync({
        name: trimmedName,
        stageType: addState.addStageType,
      });
      toast.success("Stage added");
      dispatch(closeAddDialog());
    } catch (err: unknown) {
      toast.error("Failed to add stage");
    }
  };

  const handleOpenEdit = React.useCallback(
    (row: any) => {
      dispatch(
        openEditDialog({
          id: row.id,
          name: row.stageName,
          pipelineId: row.pipelineId,
          stageType: row.stageType ?? "Lead",
        })
      );
    },
    [dispatch],
  );

  const handleSaveEdit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!editState.editingRowId) return;

    const trimmedName = editState.editName.trim();
    if (!trimmedName) {
      toast.error("Please enter a stage name");
      return;
    }

    const row = rows.find((item: any) => item.id === editState.editingRowId);
    if (!row) {
      toast.error("Stage not found");
      return;
    }

    try {
      if (!canUpdateStage) {
        toast.error("You don't have permission to update stages");
        return;
      }
      await updateStageMutation.mutateAsync({
        name: trimmedName,
        stageType: editState.editStageType,
      });

      toast.success("Stage updated");
      dispatch(closeEditDialog());
    } catch (err: unknown) {
      toast.error("Failed to update stage");
    }
  };

  const handleDeleteStage = async () => {
    if (!deleteRowId) return;
    const row = rows.find((item: any) => item.id === deleteRowId);
    if (!row) {
      setDeleteRowId(null);
      return;
    }

    const currentStages = getPipelineStages(row.pipelineId);
    const nextStages = currentStages.filter((stage: any) => stage.id !== deleteRowId) as Stage[];

    try {
      if (!canDeleteStage) {
        toast.error("You don't have permission to delete stages");
        return;
      }
      await deleteStageMutation.mutateAsync({
        id: row.pipelineId,
        body: { stages: nextStages },
      });
      toast.success("Stage deleted");
      setDeleteRowId(null);
    } catch (err: unknown) {
      toast.error("Failed to delete stage");
    }
  };

  const handleOpenAddSubStage = React.useCallback((row: any) => {
    setSubStageDialog(row);
    setSubStageName("");
  }, []);

  const handleCloseAddSubStage = React.useCallback(() => {
    setSubStageDialog(null);
    setSubStageName("");
  }, []);

  const handleCreateSubStage = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!subStageDialog) return;

    const trimmedName = subStageName.trim();
    if (!trimmedName) {
      toast.error("Please enter a substage name");
      return;
    }

    try {
      if (!canCreateStage) {
        toast.error("You don't have permission to add substages");
        return;
      }

      await createSubStageMutation.mutateAsync({
        pipelineStageId: subStageDialog.id,
        name: trimmedName,
      });

      toast.success(`Substage added to ${subStageDialog.stageName}`);
      handleCloseAddSubStage();
    } catch (err: unknown) {
      toast.error("Failed to add substage");
    }
  };

  const handleOpenEditSubStage = React.useCallback(
    (row: any, subStage: SubStage) => {
      setEditingSubStage({ row, subStage });
      setEditSubStageName(subStage.name);
    },
    [],
  );

  const handleCloseEditSubStage = React.useCallback(() => {
    setEditingSubStage(null);
    setEditSubStageName("");
  }, []);

  const handleSaveSubStageEdit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!editingSubStage) return;

    const trimmedName = editSubStageName.trim();
    if (!trimmedName) {
      toast.error("Please enter a substage name");
      return;
    }

    try {
      if (!canUpdateStage) {
        toast.error("You don't have permission to edit substages");
        return;
      }

      await updateSubStageMutation.mutateAsync({
        id: editingSubStage.subStage.id,
        body: {
          name: trimmedName,
          pipelineStageId: editingSubStage.row.id,
        },
      });

      toast.success(`Substage updated in ${editingSubStage.row.stageName}`);
      handleCloseEditSubStage();
    } catch (err: unknown) {
      toast.error("Failed to update substage");
    }
  };

  const handleDeleteSubStage = async () => {
    if (!deleteSubStageState) return;

    try {
      if (!canDeleteStage) {
        toast.error("You don't have permission to delete substages");
        return;
      }

      await deleteSubStageMutation.mutateAsync(deleteSubStageState.subStage.id);
      toast.success(`Substage deleted from ${deleteSubStageState.row.stageName}`);
      setDeleteSubStageState(null);
    } catch (err: unknown) {
      toast.error("Failed to delete substage");
    }
  };

  return (
    <div
      className={cn(
        embedded
          ? "flex flex-col min-h-0 gap-2.5 overflow-hidden"
          : "flex flex-col h-full gap-2.5 md:gap-3.5 lg:gap-4.5 p-3 sm:p-4 md:p-5 lg:p-6 animate-in fade-in duration-500 overflow-hidden bg-gray-50/30",
      )}
    >
      <div className="flex flex-col gap-3 md:gap-4 lg:gap-5 pb-3 md:pb-4 lg:pb-5 border-b border-border/50 shrink-0">
        {/* Top Row: Title and Main Action */}
        <div className="flex items-center justify-between gap-4">
          <div className="flex items-center gap-3 md:gap-5 min-w-0">
            <div className="h-11 w-11 md:h-14 md:w-14 rounded-[18px] md:rounded-[22px] bg-white flex items-center justify-center text-accent shrink-0 shadow-premium border border-border/40">
              <Layers size={22} className="md:size-[28px] stroke-[2.5px]" />
            </div>
            <div className="min-w-0">
              <h1 className="text-[24px] md:text-[36px] font-black text-gray-900 font-['Lexend'] tracking-tight leading-none">
                Stages
              </h1>
              <div className="flex items-center gap-2 mt-2 md:mt-3">
                <span className="text-[11px] font-extrabold text-white bg-accent px-3 py-1 rounded-full uppercase tracking-widest font-['Lexend_Deca'] shadow-lg shadow-accent/20">
                  {total} Rows
                </span>
                <span className="text-[11px] text-gray-400 font-medium hidden xs:flex items-center gap-2 font-['Lexend_Deca'] ml-1">
                  <span className="h-1.5 w-1.5 rounded-full bg-green-500 animate-pulse" />
                  Live Syncing
                </span>
              </div>
            </div>
          </div>

          <div className="hidden sm:flex items-center gap-3">
            {canCreateStage && (
              <Button
                type="button"
                variant="accentPipelinePrimary"
                onClick={() => dispatch(openAddDialog())}
                disabled={!pipelines.length}
              >
                <Plus size={18} className="stroke-[2px]" />
                Add New Stage
              </Button>
            )}
          </div>
        </div>

        {/* Bottom Row: Filters and Search */}
        <div className="flex flex-col lg:flex-row items-stretch lg:items-center gap-4">
          <div className="relative flex-1 group">
            <Search
              size={14}
              className="absolute left-4 top-1/2 -translate-y-1/2 text-gray-400 group-focus-within:text-accent transition-all duration-300 pointer-events-none"
              aria-hidden
            />
            <Input
              type="search"
              className="pl-10 pr-4 h-10 text-[13px] font-bold bg-white border-border/80 rounded-xl w-full font-['Lexend_Deca'] shadow-sm focus:ring-accent/20 focus:border-accent group-hover:border-accent/40 transition-all placeholder:text-gray-400"
              placeholder="Search by stage name, pipeline or ID..."
              value={searchInput}
              onChange={handleSearchChange}
              aria-label="Search stages"
            />
          </div>
          
          <div className="flex items-center gap-3">
            <ReactSelect
              value={pipelineId ?? "all"}
              onValueChange={handlePipelineFilterChange}
              options={[
                { value: "all", label: "All Pipelines" },
                ...pipelines.map((p: { id: string; name: string }) => ({
                  value: p.id,
                  label: p.name,
                })),
              ]}
              placeholder="Filter by Pipeline"
              aria-label="Filter by pipeline"
              triggerClassName="h-10 px-3.5 rounded-xl flex-1 sm:min-w-[200px] text-[13px] font-bold font-['Lexend_Deca'] border-border/80 bg-white shadow-sm hover:border-accent transition-all"
              contentClassName="rounded-2xl border-border/40 shadow-premium"
            />

            <ReactSelect
              value={stageTypeFilter ?? "all"}
              onValueChange={(value) => {
                void setStageTypeFilter(
                  value === "all" ? null : value,
                );
                void setPage(1);
              }}
              options={[
                { value: "all", label: "All types" },
                { value: "Lead", label: "Lead" },
                { value: "Deal", label: "Deal" },
              ]}
              placeholder="Stage type"
              aria-label="Filter by stage type"
              triggerClassName="h-10 px-3.5 rounded-xl flex-1 sm:min-w-[160px] text-[13px] font-bold font-['Lexend_Deca'] border-border/80 bg-white shadow-sm hover:border-accent transition-all"
              contentClassName="rounded-2xl border-border/40 shadow-premium"
            />

            <div className="sm:hidden flex-1">
              {canCreateStage && (
                <Button
                  type="button"
                  variant="accentPipelineBlock"
                  onClick={() => dispatch(openAddDialog())}
                  disabled={!pipelines.length}
                >
                  <Plus size={18} className="mr-2 stroke-[3px]" />
                  New Stage
                </Button>
              )}
            </div>
          </div>
        </div>
      </div>

      <div className="flex-1 min-h-0 flex flex-col rounded-2xl border border-border/60 bg-white/60 backdrop-blur-sm overflow-hidden">
        <div className="px-4 py-3 border-b border-border/60 flex items-center justify-between gap-3 shrink-0 flex-wrap">
          <div className="flex items-center gap-2 text-[12px] text-gray-600">
            <GitBranch size={14} className="text-gray-400 shrink-0" />
            <span>
              Page {page} of {totalPages} · {PAGE_SIZE} per page
            </span>
          </div>
          {isFetching && !isLoading && (
            <div className="flex items-center gap-2 text-[12px] text-gray-500">
              <RefreshCw size={14} className="animate-spin" />
              Refreshing
            </div>
          )}
        </div>

        {isLoading ? (
          <div className="p-6 space-y-4">
            {[1, 2, 3, 4, 5, 6].map((i) => (
              <Skeleton
                key={i}
                className="h-16 w-full rounded-2xl bg-gray-200/50"
              />
            ))}
          </div>
        ) : pipelines.length === 0 ? (
          <div className="flex-1 flex flex-col items-center justify-center gap-2 text-center px-4 py-14">
            <Layers size={32} className="text-gray-300" />
            <p className="text-[14px] font-semibold text-gray-700 font-['Lexend_Deca']">
              No pipelines yet
            </p>
            <p className="text-[12px] text-gray-500">
              Create a pipeline first; stages will appear here.
            </p>
          </div>
        ) : rows.length === 0 ? (
          <div className="flex-1 flex flex-col items-center justify-center gap-3 text-center px-4 py-14">
            <Search size={28} className="text-gray-300" />
            <p className="text-[14px] font-semibold text-gray-700 font-['Lexend_Deca']">
              No stages match your filters
            </p>
            <Button
              type="button"
              variant="outlineToolbarClear"
              onClick={() => {
                setSearchInput("");
                void setQ(null);
                void setPipelineId(null);
                void setStageTypeFilter(null);
                void setPage(1);
              }}
            >
              Clear filters
            </Button>
          </div>
        ) : (
          <>
            <StagesTable
              rows={rows}
              isAdmin={canManageStages}
              onEdit={handleOpenEdit}
              onDelete={setDeleteRowId}
              onAddSubStage={handleOpenAddSubStage}
              getSubStages={getStageSubStages}
              onEditSubStage={handleOpenEditSubStage}
              onDeleteSubStage={(row, subStage) => setDeleteSubStageState({ row, subStage })}
              page={page}
              totalPages={totalPages}
              total={total}
              onPageChange={setPage}
            />
          </>
        )}
      </div>

      <AddStageDialog
        pipelines={pipelines}
        adding={createStageMutation.isPending}
        onSave={handleAddStage}
      />

      <EditStageDialog
        pipelines={pipelines}
        savingStage={updateStageMutation.isPending}
        onSave={handleSaveEdit}
      />

      <DeleteDialog
        open={!!deleteRowId}
        onOpenChange={(open) => !open && setDeleteRowId(null)}
        onConfirm={handleDeleteStage}
        isLoading={deleteStageMutation.isPending}
        title="Delete Stage"
        description="Remove this stage from the pipeline."
      />

      <SubStageDialog
        open={!!subStageDialog}
        mode="add"
        parentStage={subStageDialog}
        value={subStageName}
        loading={createSubStageMutation.isPending}
        onValueChange={setSubStageName}
        onOpenChange={(open) => {
          if (!open) {
            handleCloseAddSubStage();
          }
        }}
        onSubmit={handleCreateSubStage}
      />

      <SubStageDialog
        open={!!editingSubStage}
        mode="edit"
        parentStage={editingSubStage?.row ?? null}
        value={editSubStageName}
        loading={updateSubStageMutation.isPending}
        onValueChange={setEditSubStageName}
        onOpenChange={(open) => {
          if (!open) {
            handleCloseEditSubStage();
          }
        }}
        onSubmit={handleSaveSubStageEdit}
      />

      <DeleteDialog
        open={!!deleteSubStageState}
        onOpenChange={(open) => !open && setDeleteSubStageState(null)}
        onConfirm={handleDeleteSubStage}
        isLoading={deleteSubStageMutation.isPending}
        title="Delete Substage"
        description={`Remove "${deleteSubStageState?.subStage.name ?? "this substage"}"?`}
      />
    </div>
  );
}
