"use client";

import * as React from "react";
import { useQueryState, parseAsString } from "nuqs";
import {
  Layers,
  Search,
  Plus,
  Edit2,
  Trash2,
  GitBranch,
  X,
  AlertCircle,
} from "lucide-react";
import {
  useGetPipelineStageNamesQuery,
  useCreatePipelineStageNameMutation,
  useUpdatePipelineStageNameMutation,
  useDeletePipelineStageNameMutation,
  useBulkDeletePipelineStageNamesMutation,
  PipelineStageName,
} from "@/api/rtk/pipeline-stage-names-api";
import { useGetPipelinesQuery } from "@/api/rtk/pipelines-api";
import {
  useGetRolesQuery,
} from "@/api/rtk/roles-api";
import type { Role } from "@/api/permissions/types";
import {
  useGetRoleStagePermissionsByStageNameQuery,
  useGetRoleStagePermissionsQuery,
  useCreateRoleStagePermissionMutation,
  useUpdateRoleStagePermissionMutation,
  useDeleteRoleStagePermissionMutation,
  RoleStagePermission,
  CreateRoleStagePermissionDto,
  UpdateRoleStagePermissionDto,
} from "@/api/rtk/role-stage-permissions-api";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
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 { ReactSelect } from "@/components/ui/react-select";
import { DeleteDialog } from "@/components/ui/delete-dialog";
import { StageNamesTable } from "@/components/table/stage-names-table";
import { StagePermissionsTable } from "@/components/table/stage-permissions-table";
import { StageNameDialog } from "@/components/dialog/stage-name-dialog";
import { StagePermissionDialog } from "@/components/dialog/stage-permission-dialog";
import { toast } from "sonner";
import { useGetProfileQuery } from "@/api/rtk/auth-api";
import { useAppSelector, useAppDispatch } from "@/store/hooks";
import { useAuthToken } from "@/hooks/use-auth-token"
import {
  selectStageNameDialog,
  openStageNameDialog,
  closeStageNameDialog,
  setStageName,
  setStageNamePipelineId,
} from "@/store/slices/stage-name-dialog-slice";
import { filterForbiddenStageNames } from "@/lib/stage-name-filter";
import { hasPermission, isAdminUser } from "@/lib/permissions";
import { useSession } from "next-auth/react";

export default function StageNamesPage() {
  const { token } = useAuthToken();
  const { data: session } = useSession();
  const dispatch = useAppDispatch();
  const dialogState = useAppSelector(selectStageNameDialog);
  const { data: profile } = useGetProfileQuery(undefined, { skip: !token });
  const permissionSource = (session as { backendUser?: unknown } | null)?.backendUser ?? profile;
  const isAdmin = isAdminUser(permissionSource);
  const currentUserRoleId = profile?.roleId;
  const canCreateStageNames = hasPermission(permissionSource, ["CREATE", "UPDATE"], "PIPELINE");
  const canUpdateStageNames = hasPermission(permissionSource, "UPDATE", "PIPELINE");
  const canDeleteStageNames = hasPermission(permissionSource, "DELETE", "PIPELINE");

  const canEditStageNames = canUpdateStageNames;

  // Check if user can manage permissions for this stage
  const canManageStagePermissions = (stageNameId: string) => {
    if (isAdmin || canUpdateStageNames) return true;

    // Check if user has explicit permission to edit this stage
    const userPermission = permissions.find(p =>
      p.roleId === profile?.roleId &&
      p.stageNameId === stageNameId
    );

    return userPermission?.canEdit || false;
  };

  const [search, setSearch] = React.useState("");
  const [pipelineId, setPipelineId] = useQueryState("pipelineId", parseAsString);

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

  const [page, setPage] = React.useState(1);
  const [pageSize, setPageSize] = React.useState(10);

  const { data: paginatedData, isLoading } = useGetPipelineStageNamesQuery(
    { 
      pipelineId: pipelineId ?? undefined,
      page,
      limit: pageSize,
      search: search.trim() || undefined,
    },
    { skip: !token },
  );

  const stageNames: PipelineStageName[] = paginatedData?.data ?? [];
  const total = paginatedData?.total ?? 0;
  const totalPages = paginatedData?.totalPages ?? 0;
  const visibleApiStageNames = React.useMemo(
    () => filterForbiddenStageNames(stageNames),
    [stageNames],
  );

  const [createStageName, { isLoading: isCreating }] = useCreatePipelineStageNameMutation();
  const [updateStageName, { isLoading: isUpdating }] = useUpdatePipelineStageNameMutation();
  const [deleteStageName, { isLoading: isDeleting }] = useDeletePipelineStageNameMutation();

  const [deleteId, setDeleteId] = React.useState<string | null>(null);
  const [selectedStageNameId, setSelectedStageNameId] = React.useState<string | null>(null);
  const [permissionDialogOpen, setPermissionDialogOpen] = React.useState(false);
  const [editingPermission, setEditingPermission] = React.useState<RoleStagePermission | undefined>(undefined);
  const [permissionDeleteId, setPermissionDeleteId] = React.useState<string | null>(null);
  
  const [selectedIds, setSelectedIds] = React.useState<string[]>([]);
  const [isBulkDeleting, setIsBulkDeleting] = React.useState(false);

  // Roles and permissions
  const { data: roles = [] } = useGetRolesQuery(undefined, { skip: !token });
  const { data: permissions = [], isLoading: permissionsLoading } = useGetRoleStagePermissionsByStageNameQuery(
    selectedStageNameId!,
    { skip: !token || !selectedStageNameId }
  );
  const { data: myRoleStagePermissions = [] } = useGetRoleStagePermissionsQuery(
    currentUserRoleId ? { roleId: currentUserRoleId } : undefined,
    { skip: !token || !currentUserRoleId || isAdmin },
  );

  const [createPermission, { isLoading: isCreatingPermission }] = useCreateRoleStagePermissionMutation();
  const [updatePermission, { isLoading: isUpdatingPermission }] = useUpdateRoleStagePermissionMutation();
  const [deletePermission, { isLoading: isDeletingPermission }] = useDeleteRoleStagePermissionMutation();
  const [bulkDeleteStageNames] = useBulkDeletePipelineStageNamesMutation();

  const toggleSelect = (id: string, checked: boolean) => {
    setSelectedIds(prev => 
      checked ? [...prev, id] : prev.filter(i => i !== id)
    );
  };

  const toggleSelectAll = (checked: boolean) => {
    setSelectedIds(checked ? filteredData.map(d => d.id) : []);
  };

  const handleBulkDelete = async () => {
    if (selectedIds.length === 0) return;
    
    if (!confirm(`Are you sure you want to delete ${selectedIds.length} stage names?`)) return;

    setIsBulkDeleting(true);
    try {
      await bulkDeleteStageNames(selectedIds).unwrap();
      toast.success(`${selectedIds.length} stage names deleted`);
      setSelectedIds([]);
    } catch (err: unknown) {
      const message = (err as { data?: { message?: string } })?.data?.message ?? "Bulk delete failed";
      toast.error(message);
    } finally {
      setIsBulkDeleting(false);
    }
  };

  const visibleStageNames = React.useMemo(() => {
    if (isAdmin) return visibleApiStageNames;
    const allowedStageNameIds = new Set(
      myRoleStagePermissions
        .filter((p) => p.canView)
        .map((p) => p.stageNameId),
    );
    return visibleApiStageNames.filter((stage) => allowedStageNameIds.has(stage.id));
  }, [isAdmin, myRoleStagePermissions, visibleApiStageNames]);

  const filteredData = visibleStageNames;

  React.useEffect(() => {
    setPage(1);
  }, [search, pipelineId]);

  const handleOpenCreate = () => {
    dispatch(
      openStageNameDialog({
        editingId: null,
        name: "",
        editPipelineId: pipelineId ?? "any",
      })
    );
  };

  const handleOpenEdit = (item: PipelineStageName) => {
    // Check if user has permission to edit this stage
    if (!canEditStageNames && !canManageStagePermissions(item.id)) {
      toast.error("You don't have permission to edit this stage name");
      return;
    }

    dispatch(
      openStageNameDialog({
        editingId: item.id,
        name: item.name,
        editPipelineId: item.pipelineId ?? "any",
      })
    );
  };

  const handleSave = async (e: React.FormEvent) => {
    e.preventDefault();
    const trimmedName = dialogState.name.trim();
    if (!trimmedName) {
      toast.error("Name is required");
      return;
    }

    // Additional permission check for updates
    if (dialogState.editingId) {
      if (!canEditStageNames && !canManageStagePermissions(dialogState.editingId)) {
        toast.error("You don't have permission to update this stage name");
        return;
      }
    }

    try {
      if (dialogState.editingId) {
        await updateStageName({
          id: dialogState.editingId,
          name: trimmedName,
          pipelineId: dialogState.editPipelineId === "any" ? undefined : dialogState.editPipelineId,
        }).unwrap();
        toast.success("Stage name updated");
      } else {
        // Only admins can create new stage names
        if (!canCreateStageNames) {
          toast.error("You don't have permission to create stage names");
          return;
        }

        await createStageName({
          name: trimmedName,
          pipelineId: dialogState.editPipelineId === "any" ? undefined : dialogState.editPipelineId,
        }).unwrap();
        toast.success("Stage name created");
      }
      dispatch(closeStageNameDialog());
    } catch (err: unknown) {
      const message =
        (err as { data?: { message?: string } })?.data?.message ??
        (err instanceof Error ? err.message : "Failed to save stage name");
      toast.error(message);
    }
  };

  const handleDelete = async () => {
    if (!deleteId) return;
    if (!canDeleteStageNames) {
      toast.error("You don't have permission to delete stage names");
      return;
    }
    try {
      await deleteStageName(deleteId).unwrap();
      toast.success("Pipeline stage name deleted");
      setDeleteId(null);
    } catch (err: unknown) {
      const message =
        (err as { data?: { message?: string } })?.data?.message ??
        (err instanceof Error ? err.message : "Failed to delete item");
      toast.error(message);
      throw err;
    }
  };

  // Permission handlers
  const handleOpenPermissionDialog = (stageNameId: string, permission?: RoleStagePermission) => {
    // Check if user can manage permissions for this stage
    if (!isAdmin && !canManageStagePermissions(stageNameId)) {
      toast.error("You don't have permission to manage permissions for this stage");
      return;
    }

    setSelectedStageNameId(stageNameId);
    setEditingPermission(permission);
    setPermissionDialogOpen(true);
  };

  const handleClosePermissionDialog = () => {
    setPermissionDialogOpen(false);
    setEditingPermission(undefined);
    setSelectedStageNameId(null);
  };

  const handleSavePermission = async (data: {
    roleId: string;
    canView: boolean;
    canEdit: boolean;
    canDelete: boolean;
  }) => {
    if (!selectedStageNameId) return;

    try {
      if (editingPermission) {
        await updatePermission({
          id: editingPermission.id,
          body: {
            canView: data.canView,
            canEdit: data.canEdit,
            canDelete: data.canDelete,
          },
        }).unwrap();
        toast.success("Permission updated");
      } else {
        await createPermission({
          roleId: data.roleId,
          stageNameId: selectedStageNameId,
          canView: data.canView,
          canEdit: data.canEdit,
          canDelete: data.canDelete,
        }).unwrap();
        toast.success("Permission created");
      }
      handleClosePermissionDialog();
    } catch (err: unknown) {
      const message =
        (err as { data?: { message?: string } })?.data?.message ??
        (err instanceof Error ? err.message : "Failed to save permission");
      toast.error(message);
    }
  };

  const handleDeletePermission = async () => {
    if (!permissionDeleteId) return;
    try {
      await deletePermission(permissionDeleteId).unwrap();
      toast.success("Permission deleted");
      setPermissionDeleteId(null);
    } catch (err: unknown) {
      const message =
        (err as { data?: { message?: string } })?.data?.message ??
        (err instanceof Error ? err.message : "Failed to delete permission");
      toast.error(message);
      throw err;
    }
  };

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

  return (
    <div className="flex flex-col h-full gap-4.5 p-1 sm:p-2 md:p-3 animate-in fade-in duration-500 overflow-hidden">
      <div className="flex max-w-full flex-col lg:flex-row lg:flex-wrap lg:items-start justify-between gap-4 border-b border-border/40 pb-5 shrink-0">
        <div className="flex items-center gap-3 min-w-0">
          <div className="h-10 w-10 rounded-xl bg-accent/10 flex items-center justify-center text-accent shrink-0">
            <Layers size={20} />
          </div>
          <div className="min-w-0">
            <h1 className="text-[18px] md:text-[25px] font-extrabold text-text font-['Lexend'] tracking-tight leading-none">
              Stage Names
            </h1>
            <p className="text-[12px] text-gray-500 mt-2 font-['Lexend_Deca'] tracking-wider">
              Manage reusable names for your pipeline stages.
            </p>
          </div>
        </div>
        <div className="flex flex-col sm:flex-row items-stretch sm:items-center gap-2 w-full lg:w-auto">
          <div className="relative flex-1 min-w-[160px] sm:max-w-[240px]">
            <Search
              size={14}
              className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 pointer-events-none"
              aria-hidden
            />
            <Input
              type="search"
              className="pl-9 pr-3 h-9 text-[13px] bg-white border-border/60 rounded-xl w-full font-['Lexend_Deca']"
              placeholder="Search stage names…"
              value={search}
              onChange={(e) => setSearch(e.target.value)}
            />
          </div>
          <div className="w-full sm:w-[min(100%,200px)] min-w-0">
            <ReactSelect
              value={pipelineId ?? "all"}
              onValueChange={handlePipelineFilterChange}
              options={[
                { value: "all", label: "All pipelines" },
                ...pipelines.map((p) => ({ value: p.id, label: p.name })),
              ]}
              placeholder="Pipeline"
              aria-label="Filter by pipeline"
              triggerClassName="h-9 rounded-xl text-[12px] font-bold font-['Lexend_Deca'] border-border/60 bg-white"
              contentClassName="rounded-xl"
            />
          </div>
          {canCreateStageNames && (
            <Button
              type="button"
              variant="accentStageNameNew"
              onClick={handleOpenCreate}
            >
              <Plus size={15} className="sm:mr-1.5" />
              <span className="hidden sm:inline">New Name</span>
            </Button>
          )}
        </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">
        {isLoading ? (
          <div className="p-4 space-y-3">
            {[1, 2, 3, 4, 5].map((i) => (
              <Skeleton
                key={i}
                className="h-11 w-full rounded-lg bg-border/30"
              />
            ))}
          </div>
        ) : filteredData.length === 0 ? (
          <div className="flex-1 flex flex-col items-center justify-center gap-3 text-center px-4 py-14">
            <Layers size={28} className="text-gray-300" />
            <p className="text-[14px] font-semibold text-gray-700 font-['Lexend_Deca']">
              No stage names found
            </p>
            {search && (
              <Button
                type="button"
                variant="outlineToolbarClear"
                onClick={() => setSearch("")}
              >
                Clear search
              </Button>
            )}
          </div>
        ) : (
          <div className="flex-1 min-h-0 flex gap-4">
            <div className="flex-1 min-h-0 flex flex-col">
              <div className="flex-1 min-w-0 overflow-hidden">
                <StageNamesTable
                  data={filteredData}
                  pipelines={pipelines}
                  isAdmin={isAdmin || canEditStageNames || canDeleteStageNames}
                  canEditStageNames={canEditStageNames}
                  canManageStagePermissions={canManageStagePermissions}
                  onEdit={handleOpenEdit}
                  onDelete={setDeleteId}
                  onManagePermissions={(stageNameId) =>
                    setSelectedStageNameId(stageNameId)
                  }
                  selectedStageNameId={selectedStageNameId}
                  selectedIds={selectedIds}
                  onSelect={toggleSelect}
                  onSelectAll={toggleSelectAll}
                />
              </div>

              {/* Pagination Controls */}
              <div className="px-4 py-3 border-t border-border/60 flex items-center justify-between bg-white/40 sticky bottom-0">
                <div className="text-[12px] text-gray-500 font-['Lexend_Deca']">
                  Showing{" "}
                  <span className="font-bold text-gray-700">
                    {Math.min((page - 1) * pageSize + 1, total)}
                  </span>{" "}
                  to{" "}
                  <span className="font-bold text-gray-700">
                    {Math.min(page * pageSize, total)}
                  </span>{" "}
                  of <span className="font-bold text-gray-700">{total}</span>{" "}
                  stage names
                </div>
                <div className="flex items-center gap-2">
                  <Button
                    variant="outline"
                    size="pagination"
                    onClick={() => setPage((p) => Math.max(1, p - 1))}
                    disabled={page <= 1}
                  >
                    Previous
                  </Button>
                  <div className="flex items-center gap-1">
                    {Array.from({ length: Math.min(5, totalPages) }, (_, i) => {
                      let pageNum = page;
                      if (totalPages <= 5) pageNum = i + 1;
                      else if (page <= 3) pageNum = i + 1;
                      else if (page >= totalPages - 2)
                        pageNum = totalPages - 4 + i;
                      else pageNum = page - 2 + i;

                      return (
                        <Button
                          key={pageNum}
                          variant={page === pageNum ? "paginationPageCurrent" : "outline"}
                          size="page"
                          onClick={() => setPage(pageNum)}
                        >
                          {pageNum}
                        </Button>
                      );
                    })}
                  </div>
                  <Button
                    variant="outline"
                    size="pagination"
                    onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
                    disabled={page >= totalPages}
                  >
                    Next
                  </Button>
                </div>
              </div>
            </div>
            {selectedStageNameId && (
              <div className="w-[400px] min-w-0 border-l border-border/60">
                <StagePermissionsTable
                  data={permissions}
                  isAdmin={isAdmin || canUpdateStageNames}
                  onEdit={(permission) =>
                    handleOpenPermissionDialog(selectedStageNameId, permission)
                  }
                  onDelete={setPermissionDeleteId}
                  onCreateNew={() =>
                    handleOpenPermissionDialog(selectedStageNameId)
                  }
                />
              </div>
            )}
          </div>
        )}
      </div>

      <StageNameDialog
        pipelines={pipelines}
        isCreating={isCreating}
        isUpdating={isUpdating}
        onSave={handleSave}
      />

      <DeleteDialog
        open={!!deleteId}
        onOpenChange={(open) => !open && setDeleteId(null)}
        onConfirm={handleDelete}
        isLoading={isDeleting}
        title="Delete Stage Name"
        description="Are you sure you want to delete this stage name? This action cannot be undone."
      />

      <StagePermissionDialog
        open={permissionDialogOpen}
        onOpenChange={handleClosePermissionDialog}
        roles={roles}
        editingPermission={editingPermission ? {
          id: editingPermission.id,
          roleId: editingPermission.roleId,
          canView: editingPermission.canView,
          canEdit: editingPermission.canEdit,
          canDelete: editingPermission.canDelete,
        } : undefined}
        onSave={handleSavePermission}
        isSaving={isCreatingPermission || isUpdatingPermission}
        title={editingPermission ? "Edit Role Permission" : "Add Role Permission"}
        description={editingPermission
          ? "Update the permissions for this role."
          : "Select a role and set their permissions for this stage name."
        }
      />

      <DeleteDialog
        open={!!permissionDeleteId}
        onOpenChange={(open) => !open && setPermissionDeleteId(null)}
        onConfirm={handleDeletePermission}
        isLoading={isDeletingPermission}
        title="Delete Role Permission"
        description="Are you sure you want to remove this role's permission? This action cannot be undone."
      />

      {selectedIds.length > 0 && isAdmin && (
        <div className="fixed bottom-6 left-1/2 -translate-x-1/2 z-50 animate-in fade-in slide-in-from-bottom-4 duration-300 w-full max-w-fit px-4">
          <div className="bg-white dark:bg-gray-900 border border-border shadow-2xl rounded-2xl px-4 py-3 flex items-center gap-6">
            <div className="flex items-center gap-3 border-r border-border pr-6">
               <div className="size-9 rounded-xl bg-red-100 flex items-center justify-center text-red-600">
                 <Trash2 size={20} />
               </div>
               <div className="flex flex-col">
                  <span className="text-[13px] font-bold text-gray-900 dark:text-gray-100">
                    {selectedIds.length} Selected
                  </span>
                  <span className="text-[11px] text-gray-400 font-medium">
                    Bulk actions
                  </span>
               </div>
            </div>

            <div className="flex items-center gap-2">
              <Button
                variant="destructiveBulkBar"
                onClick={handleBulkDelete}
                disabled={isBulkDeleting}
              >
                <Trash2 size={14} />
                Delete Selected
              </Button>
              <Button
                variant="ghostBulkClear"
                onClick={() => setSelectedIds([])}
                disabled={isBulkDeleting}
              >
                <X size={14} className="mr-2" />
                Clear
              </Button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
