"use client";

import * as React from "react";
import { format } from "date-fns";
import { useQueryState, parseAsString } from "nuqs";
import {
  GitBranch,
  Pencil,
  Plus,
  RefreshCw,
  Trash2,
  Layers,
  Search,
} from "lucide-react";
import {
  useGetProfileQuery,
  useCreatePipelineMutation,
  useDeletePipelineMutation,
  useGetPipelinesQuery,
  useUpdatePipelineMutation,
} from "@/api/rtk";
import type { Pipeline } from "@/api/rtk/pipelines-api";
import { useStagesSync } from "@/hooks/use-stages-sync";
import { useAppDispatch, useAppSelector } from "@/store/hooks";
import { useAuthToken } from "@/hooks/use-auth-token";
import {
  selectPipelineFilters,
  setPipelineFilters,
} from "@/store/slices/pipeline-filters-slice";
import {
  openCreatePipelineForm,
  openEditPipelineForm,
  resetPipelineForm,
  selectPipelineForm,
} from "@/store/slices/pipeline-form-slice";
import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { DeleteDialog } from "@/components/ui/delete-dialog";
import { PipelineTable } from "@/components/table/pipeline-table";
import { StagesViewerDialog } from "@/components/dialog/stages-viewer-dialog";
import { PipelineFormDialog } from "@/components/dialog/pipeline-form-dialog";
import { PipelinePageHeader } from "@/components/pipeline/pipeline-page-header";
import { Badge, badgeVariants } from "@/components/ui/badge";
import { toast } from "sonner";
import type { VariantProps } from "class-variance-authority";
import { hasPermission } from "@/lib/permissions";
import { useSession } from "next-auth/react";
import { cn } from "@/lib/utils";

type PipelinePageProps = {
  embedded?: boolean;
};

function parseStages(stages: any[]): { id: string; name: string }[] {
  if (!Array.isArray(stages)) return [];
  return stages.map((raw, i) => {
    if (typeof raw === "string") {
      const id = raw?.trim().toLowerCase().replace(/\s+/g, "_");
      return { id: id || `stage_${i}`, name: raw };
    }
    const s = raw as { id?: string; name?: string };
    const name = String(s.name ?? s.id ?? `Stage ${i + 1}`);
    const id =
      String(s.id ?? name)
        .trim()
        .toLowerCase()
        .replace(/\s+/g, "_") || `stage_${i}`;
    return { id, name };
  });
}

/** Canonical CRM stage order (Prospecting → … → Customer). */
const STAGE_DISPLAY_ORDER = [
  "prospecting",
  "proposal",
  "proposal_sent",
  "qualified",
  "negotiation",
  "closed_lost",
  "closed_won",
  "customer",
] as const;

function stageOrderIndex(id: string): number {
  const normalized = id.toLowerCase();
  const idx = STAGE_DISPLAY_ORDER.findIndex(
    (k) =>
      normalized === k ||
      normalized.startsWith(`${k}_`) ||
      normalized.includes(k),
  );
  return idx === -1 ? STAGE_DISPLAY_ORDER.length + 1 : idx;
}

function sortStagesForDisplay(stages: { id: string; name: string }[]) {
  return [...stages].sort((a, b) => {
    const da = stageOrderIndex(a.id);
    const db = stageOrderIndex(b.id);
    if (da !== db) return da - db;
    return a.name.localeCompare(b.name);
  });
}

type BadgeVariant = NonNullable<VariantProps<typeof badgeVariants>["variant"]>;

function stageBadgeVariant(stage: { id: string; name: string }): BadgeVariant {
  const id = stage.id.toLowerCase();
  const name = stage.name.toLowerCase();
  if (id === "closed_lost" || name.includes("closed lost"))
    return "destructive";
  if (id === "closed_won" || name.includes("closed won")) return "default";
  if (id === "customer" || name === "customer") return "secondary";
  if (id.includes("proposal") || name.includes("proposal")) return "outline";
  if (id.includes("negotiation") || name.includes("negotiation"))
    return "outline";
  if (id.includes("qualified") || name.includes("qualified")) return "outline";
  if (id.includes("prospect") || name.includes("prospect")) return "outline";
  return "outline";
}

function formatTs(iso: string | undefined): string {
  if (!iso) return "—";
  try {
    return format(new Date(iso), "MMM d, yyyy");
  } catch {
    return "—";
  }
}

function pipelineMatchesQuery(pipeline: Pipeline, q: string): boolean {
  const needle = q.trim().toLowerCase();
  if (!needle) return true;
  if (pipeline.name.toLowerCase().includes(needle)) return true;
  if (pipeline.id.toLowerCase().includes(needle)) return true;
  const stages = sortStagesForDisplay(parseStages(pipeline.stages));
  return stages.some(
    (s) =>
      s.name.toLowerCase().includes(needle) ||
      s.id.toLowerCase().includes(needle),
  );
}

export default function PipelinePage({ embedded = false }: PipelinePageProps) {
  const dispatch = useAppDispatch();
  const { token } = useAuthToken();
  const { data: session } = useSession();
  const pipelineFilters = useAppSelector(selectPipelineFilters);
  const pipelineForm = useAppSelector(selectPipelineForm);
  const { data: profile } = useGetProfileQuery(undefined, { skip: !token });
  const permissionSource =
    (session as { backendUser?: unknown } | null)?.backendUser ?? profile;
  const canCreatePipeline = hasPermission(
    permissionSource,
    "CREATE",
    "PIPELINE",
  );
  const canUpdatePipeline = hasPermission(
    permissionSource,
    "UPDATE",
    "PIPELINE",
  );
  const canDeletePipeline = hasPermission(
    permissionSource,
    "DELETE",
    "PIPELINE",
  );
  const canManagePipelines =
    canCreatePipeline || canUpdatePipeline || canDeletePipeline;

  const {
    data: pipelines = [],
    isLoading,
    isFetching,
  } = useGetPipelinesQuery(undefined, { skip: !token, refetchOnFocus: true });

  const [searchQuery, setSearchQuery] = useQueryState(
    "q",
    parseAsString.withDefault(""),
  );

  const { isLoading: stagesLoading, isFetching: stagesFetching } =
    useStagesSync({ search: pipelineFilters.searchQuery });

  const [createPipeline, { isLoading: creating }] = useCreatePipelineMutation();
  const [updatePipeline, { isLoading: updating }] = useUpdatePipelineMutation();
  const [deletePipeline, { isLoading: deleting }] = useDeletePipelineMutation();

  const [deleteDialogOpen, setDeleteDialogOpen] = React.useState(false);
  const [pipelineToDelete, setPipelineToDelete] =
    React.useState<Pipeline | null>(null);
  const [stagesViewer, setStagesViewer] = React.useState<{
    pipeline: Pipeline;
    stages: { id: string; name: string }[];
  } | null>(null);

  React.useEffect(() => {
    const nextFilters = {
      searchQuery,
    };

    if (pipelineFilters.searchQuery !== nextFilters.searchQuery) {
      dispatch(setPipelineFilters(nextFilters));
    }
  }, [dispatch, pipelineFilters.searchQuery, searchQuery]);

  React.useEffect(() => {
    if (searchQuery !== pipelineFilters.searchQuery) {
      void setSearchQuery(
        pipelineFilters.searchQuery === "" ? null : pipelineFilters.searchQuery,
      );
    }
  }, [pipelineFilters.searchQuery, searchQuery, setSearchQuery]);

  const filteredPipelines = React.useMemo(() => {
    return pipelines.filter((p) =>
      pipelineMatchesQuery(p, pipelineFilters.searchQuery),
    );
  }, [pipelines, pipelineFilters]);

  const openCreate = () => {
    dispatch(openCreatePipelineForm());
  };

  const openEdit = (pipeline: Pipeline) => {
    dispatch(
      openEditPipelineForm({
        id: pipeline.id,
        name: pipeline.name,
        moduleDependencies: pipeline.moduleDependencies,
      }),
    );
  };

  const handleFormSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    const trimmed = pipelineForm.form.name.trim();
    if (!trimmed) {
      toast.error("Pipeline name is required");
      return;
    }
    if (
      !(pipelineForm.mode === "create" ? canCreatePipeline : canUpdatePipeline)
    ) {
      toast.error("You don't have permission to manage pipelines");
      return;
    }
    try {
      if (pipelineForm.mode === "create") {
        await createPipeline({
          name: trimmed,
          moduleDependencies: pipelineForm.form.moduleDependencies,
        }).unwrap();
        toast.success("Pipeline created");
      } else if (pipelineForm.mode === "edit" && pipelineForm.form.id) {
        await updatePipeline({
          id: pipelineForm.form.id,
          body: {
            name: trimmed,
            moduleDependencies: pipelineForm.form.moduleDependencies,
          },
        }).unwrap();
        toast.success("Pipeline updated");
      }
      dispatch(resetPipelineForm());
    } catch (error: unknown) {
      const message =
        (error as { data?: { message?: string } })?.data?.message ??
        (error instanceof Error ? error.message : "Failed to save pipeline");
      toast.error(message);
    }
  };

  const handleDelete = async () => {
    if (!pipelineToDelete) return;
    if (!canDeletePipeline) {
      toast.error("You don't have permission to delete pipelines");
      return;
    }
    try {
      await deletePipeline(pipelineToDelete.id).unwrap();
      toast.success("Pipeline deleted");
      setPipelineToDelete(null);
    } catch (error: unknown) {
      const message =
        (error as { data?: { message?: string } })?.data?.message ??
        (error instanceof Error ? error.message : "Failed to delete pipeline");
      toast.error(message);
      throw error;
    }
  };

  const hasPipelines = pipelines.length > 0;
  const isSearchActive = pipelineFilters.searchQuery.trim().length > 0;

  return (
    <div
      className={cn(
        embedded
          ? "flex flex-col min-h-0 gap-4 overflow-hidden"
          : "flex flex-col h-full gap-4 md:gap-6 p-2 sm:p-4 lg:p-6 animate-in fade-in duration-500 overflow-hidden",
      )}
    >
      <PipelinePageHeader
        filteredCount={filteredPipelines.length}
        isAdmin={canManagePipelines}
        isSearchActive={isSearchActive}
        onCreate={openCreate}
        pipelinesCount={pipelines.length}
      />

      {/* Table Container */}
      <div className="flex-1 min-h-0 flex flex-col rounded-[24px] border border-border/50 bg-white shadow-lg shadow-gray-200/50 overflow-hidden relative">
        <div className="px-5 py-3 border-b border-border/50 flex items-center justify-between gap-4 bg-gray-50/50 shrink-0">
          <div className="flex items-center gap-2.5 text-[12px] md:text-[12.5px] text-gray-500 font-medium">
            <Layers size={15} className="text-gray-400 shrink-0" />
            <span className="hidden sm:inline">
              Pipeline Stages & Configuration
            </span>
            <span className="sm:hidden">Stages Config</span>
          </div>
          {(isFetching || stagesFetching) && !(isLoading || stagesLoading) && (
            <div className="flex items-center gap-2 text-[11px] md:text-[12px] text-accent font-semibold animate-pulse">
              <RefreshCw size={13} className="animate-spin" />
              Syncing
            </div>
          )}
        </div>

        <div className="flex-1 overflow-auto custom-scrollbar">
          {isLoading || stagesLoading ? (
            <div className="p-5 space-y-3">
              {[1, 2, 3, 4, 5].map((i) => (
                <Skeleton
                  key={i}
                  className="h-14 w-full rounded-2xl bg-border/20"
                />
              ))}
            </div>
          ) : !hasPipelines ? (
            <div className="h-full flex flex-col items-center justify-center gap-6 text-center px-6 py-16 md:py-24">
              <div className="h-16 w-16 md:h-20 md:w-20 rounded-full bg-accent/5 flex items-center justify-center">
                <GitBranch size={32} className="text-accent/30 md:size-10" />
              </div>
              <div className="space-y-2">
                <h3 className="text-[16px] md:text-[18px] font-bold text-gray-800 font-['Lexend']">
                  No pipelines found
                </h3>
                <p className="text-[13px] md:text-[14px] text-gray-500 max-w-[340px] leading-relaxed">
                  Start by creating a pipeline to define your sales stages. You
                  can manage your deals in the main <strong>Deals</strong> view.
                </p>
              </div>
              <Button
                size="lg"
                className="rounded-2xl px-6 md:px-8 h-11 md:h-12 text-[13px] md:text-[14px] font-bold bg-accent text-white shadow-premium hover:scale-[1.02] transition-transform w-full sm:w-auto"
                onClick={openCreate}
                disabled={!canCreatePipeline}
              >
                <Plus size={18} className="mr-2 stroke-[3px]" />
                Create First Pipeline
              </Button>
            </div>
          ) : filteredPipelines.length === 0 ? (
            <div className="h-full flex flex-col items-center justify-center gap-5 text-center px-6 py-20">
              <div className="h-16 w-16 rounded-full bg-gray-50 flex items-center justify-center">
                <Search size={32} className="text-gray-300" />
              </div>
              <div className="space-y-1">
                <h3 className="text-[16px] font-bold text-gray-800 font-['Lexend']">
                  No matches for your search
                </h3>
                <p className="text-[13px] text-gray-500 max-w-[300px]">
                  Try adjusting your filters or search terms to find what you're
                  looking for.
                </p>
              </div>
              <Button
                type="button"
                variant="ghost"
                size="sm"
                className="rounded-xl mt-2 text-accent font-bold hover:bg-accent/5"
                onClick={() =>
                  dispatch(
                    setPipelineFilters({
                      searchQuery: "",
                    }),
                  )
                }
              >
                Clear all filters
              </Button>
            </div>
          ) : (
            <PipelineTable
              pipelines={filteredPipelines}
              isAdmin={canManagePipelines}
              onEdit={openEdit}
              onDelete={(pipeline) => {
                const stageCount = Array.isArray(pipeline.stages)
                  ? pipeline.stages.length
                  : 0;
                if (stageCount > 0) {
                  toast.error(
                    `This pipeline has ${stageCount} stage(s). Open Settings → Stages and remove every stage before deleting this pipeline.`,
                  );
                  return;
                }
                setPipelineToDelete(pipeline);
                setDeleteDialogOpen(true);
              }}
              onViewStages={(pipeline, stages) =>
                setStagesViewer({
                  pipeline,
                  stages,
                })
              }
            />
          )}
        </div>
      </div>

      <StagesViewerDialog
        open={!!stagesViewer}
        onOpenChange={(open) => {
          if (!open) setStagesViewer(null);
        }}
        pipeline={stagesViewer?.pipeline ?? null}
        stages={stagesViewer?.stages ?? []}
      />

      <PipelineFormDialog
        creating={creating}
        updating={updating}
        isAdmin={canManagePipelines}
        onSubmit={handleFormSubmit}
      />

      <DeleteDialog
        open={deleteDialogOpen}
        onOpenChange={setDeleteDialogOpen}
        onConfirm={handleDelete}
        title="Delete pipeline"
        description={
          pipelineToDelete?.name
            ? `Permanently delete "${pipelineToDelete.name}"? This may fail if deals still reference it.`
            : "Permanently delete this pipeline?"
        }
        confirmText="Yes, delete pipeline"
        isLoading={deleting}
      />
    </div>
  );
}
