import { useState, useEffect, useCallback } from "react";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/shared/common/ui/dialog";
import { Button } from "@/shared/common/ui/button";
import { Checkbox } from "@/shared/common/ui/checkbox";
import { Label } from "@/shared/common/ui/label";
import { Input } from "@/shared/common/ui/input";
import {
  Search,
  Loader2,
  ChevronRight,
  ChevronDown,
  Folder,
  FileText,
} from "lucide-react";
import { useToast } from "@/shared/common/ui/use-toast";
import { t } from "i18next";
import { ScrollArea } from "@/shared/common/ui/scroll-area";
import {
  assignServicesToPosition,
  getAssignedServices,
} from "@/performance-management/services/api/serviceAssignmentService";
import { useLocalizedName } from "@/shared/common/localizedName";
import { useServiceCategoryList } from "@/performance-management/hooks/useServiceCategory";
import { useServiceList } from "@/performance-management/hooks/useServiceHook";

interface AssignServiceDialogProps {
  isOpen: boolean;
  onClose: () => void;
  positionId: string;
  positionName: string;
  organizationId: string;
}

interface ServiceCategory {
  id: string;
  name: Record<string, string>;
  description?: Record<string, string>;
}

interface Service {
  id: string;
  name: Record<string, string>;
  description?: Record<string, string>;
  serviceCategoryId?: string;
  parentServiceId?: string;
  childServices?: Service[];
}

export const AssignServiceDialog = ({
  isOpen,
  onClose,
  positionId,
  positionName,
  organizationId,
}: AssignServiceDialogProps) => {
  const { toast } = useToast();
  const localizedName = useLocalizedName();
  const [selectedServiceIds, setSelectedServiceIds] = useState<string[]>([]);
  const [searchQuery, setSearchQuery] = useState("");
  const [isSaving, setIsSaving] = useState(false);
  const [expandedCategories, setExpandedCategories] = useState<Set<string>>(
    new Set()
  );
  const [expandedServices, setExpandedServices] = useState<Set<string>>(
    new Set()
  );
  const [alreadyAssignedServiceIds, setAlreadyAssignedServiceIds] = useState<
    string[]
  >([]);

  // Fetch service categories
  const { data: serviceCategoriesResponse, isLoading: categoriesLoading } =
    useServiceCategoryList(organizationId);

  // Fetch all services (without category filter for search)
  const { data: allServicesResponse } = useServiceList(organizationId);

  // Helper function to safely render text that might be localized
  const renderText = (
    text: Record<string, string> | string | undefined
  ): string => {
    if (!text) return "";
    if (typeof text === "string") return text;
    if (typeof text === "object") {
      const textObj = text as Record<string, string>;
      if (textObj.en || textObj.am) {
        return localizedName({ am: textObj.am || "", en: textObj.en || "" });
      }
    }
    return String(text);
  };

  // Extract service categories
  let serviceCategories: ServiceCategory[] = [];
  if (serviceCategoriesResponse?.data) {
    if (Array.isArray(serviceCategoriesResponse.data)) {
      serviceCategories = serviceCategoriesResponse.data;
    } else if (serviceCategoriesResponse.data.data) {
      serviceCategories = Array.isArray(serviceCategoriesResponse.data.data)
        ? serviceCategoriesResponse.data.data
        : [];
    } else if (serviceCategoriesResponse.data.items) {
      serviceCategories = Array.isArray(serviceCategoriesResponse.data.items)
        ? serviceCategoriesResponse.data.items
        : [];
    }
  }

  // Extract all services
  let allServices: Service[] = [];
  if (allServicesResponse?.data) {
    if (Array.isArray(allServicesResponse.data)) {
      allServices = allServicesResponse.data;
    } else if (allServicesResponse.data.data) {
      allServices = Array.isArray(allServicesResponse.data.data)
        ? allServicesResponse.data.data
        : [];
    } else if (allServicesResponse.data.items) {
      allServices = Array.isArray(allServicesResponse.data.items)
        ? allServicesResponse.data.items
        : [];
    }
  }

  // Build parent-child relationships
  const servicesWithChildren = allServices.map((service) => {
    const childServices = allServices.filter(
      (s) => s.parentServiceId === service.id
    );
    return {
      ...service,
      childServices: childServices.length > 0 ? childServices : undefined,
    };
  });

  // Fetch assigned service when dialog opens
  const fetchAssignedService = useCallback(async () => {
    try {
      const response = await getAssignedServices(positionId);
      let assignedServices = response.data?.data || response.data || [];

      if (!Array.isArray(assignedServices)) {
        assignedServices = assignedServices.items || [];
      }

      if (Array.isArray(assignedServices) && assignedServices.length > 0) {
        const serviceIds = assignedServices
          .map(
            (service: { id?: string; serviceId?: string; firstId?: string }) =>
              service.id || service.serviceId || service.firstId
          )
          .filter((id: string | undefined): id is string => !!id);

        setSelectedServiceIds(serviceIds);
        setAlreadyAssignedServiceIds(serviceIds);

        // Auto-expand categories containing the selected services
        serviceIds.forEach((serviceId: string) => {
          const service = allServices.find((s) => s.id === serviceId);
          if (service?.serviceCategoryId) {
            setExpandedCategories((prev) =>
              new Set(prev).add(service.serviceCategoryId!)
            );
          }
          // Auto-expand parent services if this is a child service
          if (service?.parentServiceId) {
            setExpandedServices((prev) =>
              new Set(prev).add(service.parentServiceId!)
            );
          }
        });
      } else {
        setSelectedServiceIds([]);
        setAlreadyAssignedServiceIds([]);
      }
    } catch (error) {
      console.error("Failed to fetch assigned service:", error);
      setSelectedServiceIds([]);
      setAlreadyAssignedServiceIds([]);
    }
  }, [positionId, allServices]);

  useEffect(() => {
    if (isOpen && positionId) {
      fetchAssignedService();
    }
  }, [isOpen, positionId, fetchAssignedService]);

  const handleToggleService = (serviceId: string) => {
    // Check if service is already assigned
    if (alreadyAssignedServiceIds.includes(serviceId)) {
      toast({
        title: "Warning",
        description: "Service already assigned to this position",
        variant: "destructive",
      });
      return;
    }

    setSelectedServiceIds((prev) => {
      if (prev.includes(serviceId)) {
        return prev.filter((id) => id !== serviceId);
      } else {
        return [...prev, serviceId];
      }
    });
  };

  const handleSave = async () => {
    // Filter out already assigned services
    const newServiceIds = selectedServiceIds.filter(
      (id) => !alreadyAssignedServiceIds.includes(id)
    );

    if (newServiceIds.length === 0) {
      toast({
        title: "Warning",
        description: "Please select at least one new service to assign",
        variant: "destructive",
      });
      return;
    }

    setIsSaving(true);
    try {
      await assignServicesToPosition(positionId, newServiceIds);

      toast({
        title: "Success",
        description: `${newServiceIds.length} service(s) assigned to ${positionName} successfully`,
        variant: "default",
      });

      onClose();
    } catch (error: unknown) {
      console.error("Failed to assign service:", error);
      const errorMessage =
        (
          error as {
            response?: { data?: { message?: string } };
            message?: string;
          }
        ).response?.data?.message ||
        (error as { message?: string }).message ||
        "Failed to assign service";
      toast({
        title: "Error",
        description: errorMessage,
        variant: "destructive",
      });
    } finally {
      setIsSaving(false);
    }
  };

  const handleClearSelection = () => {
    setSelectedServiceIds([]);
  };

  const toggleCategory = (categoryId: string) => {
    setExpandedCategories((prev) => {
      const newSet = new Set(prev);
      if (newSet.has(categoryId)) {
        newSet.delete(categoryId);
      } else {
        newSet.add(categoryId);
      }
      return newSet;
    });
  };

  const toggleService = (serviceId: string) => {
    setExpandedServices((prev) => {
      const newSet = new Set(prev);
      if (newSet.has(serviceId)) {
        newSet.delete(serviceId);
      } else {
        newSet.add(serviceId);
      }
      return newSet;
    });
  };

  // Group services by category (only parent services)
  const parentServicesByCategory = servicesWithChildren
    .filter((service) => !service.parentServiceId)
    .reduce((acc, service) => {
      const categoryId = service.serviceCategoryId || "uncategorized";
      if (!acc[categoryId]) {
        acc[categoryId] = [];
      }
      acc[categoryId].push(service);
      return acc;
    }, {} as Record<string, Service[]>);

  // Filter categories and services based on search
  const filteredData = searchQuery
    ? {
        categories: serviceCategories.filter((cat) =>
          renderText(cat.name).toLowerCase().includes(searchQuery.toLowerCase())
        ),
        services: servicesWithChildren.filter((service) => {
          const searchLower = searchQuery.toLowerCase();
          const serviceName = renderText(service.name).toLowerCase();
          const serviceDesc = renderText(service.description).toLowerCase();
          return (
            serviceName.includes(searchLower) ||
            serviceDesc.includes(searchLower)
          );
        }),
      }
    : { categories: serviceCategories, services: servicesWithChildren };

  // Auto-expand categories when searching
  useEffect(() => {
    if (searchQuery && filteredData.services.length > 0) {
      const categoriesToExpand = new Set<string>();
      const servicesToExpand = new Set<string>();
      filteredData.services.forEach((service) => {
        if (service.serviceCategoryId) {
          categoriesToExpand.add(service.serviceCategoryId);
        }
        // If it's a child service, expand its parent
        if (service.parentServiceId) {
          servicesToExpand.add(service.parentServiceId);
        }
      });
      setExpandedCategories(categoriesToExpand);
      setExpandedServices(servicesToExpand);
    }
  }, [searchQuery, filteredData.services]);

  const renderService = (service: Service, isChild: boolean = false) => {
    const isExpanded = expandedServices.has(service.id);
    const hasChildren =
      service.childServices && service.childServices.length > 0;
    const isAlreadyAssigned = alreadyAssignedServiceIds.includes(service.id);

    return (
      <div key={service.id} className="space-y-1">
        <div
          className={`flex items-start gap-3 p-3 rounded-lg border transition-colors ${
            isChild ? "ml-6" : ""
          } ${
            selectedServiceIds.includes(service.id)
              ? "border-purple-500 bg-purple-50"
              : isAlreadyAssigned
              ? "border-gray-300 bg-gray-50 opacity-60"
              : "border-gray-200 hover:bg-gray-50"
          } ${hasChildren ? "cursor-pointer" : ""}`}
        >
          {hasChildren && (
            <div
              onClick={() => toggleService(service.id)}
              className="cursor-pointer pt-1"
            >
              {isExpanded ? (
                <ChevronDown className="h-4 w-4 text-gray-500" />
              ) : (
                <ChevronRight className="h-4 w-4 text-gray-500" />
              )}
            </div>
          )}
          <Checkbox
            checked={selectedServiceIds.includes(service.id)}
            onCheckedChange={() => handleToggleService(service.id)}
            id={`service-${service.id}`}
            className="mt-1"
            disabled={isAlreadyAssigned}
          />
          <FileText className="h-4 w-4 text-blue-500 mt-1" />
          <div
            className="flex-1"
            onClick={() =>
              !isAlreadyAssigned && handleToggleService(service.id)
            }
          >
            <Label
              htmlFor={`service-${service.id}`}
              className={`cursor-pointer block ${
                isAlreadyAssigned ? "cursor-not-allowed" : ""
              }`}
            >
              <div className="font-medium text-gray-900">
                {renderText(service.name)}
                {isAlreadyAssigned && (
                  <span className="ml-2 text-xs text-gray-500">
                    (Already Assigned)
                  </span>
                )}
              </div>
              {service.description && (
                <div className="text-sm text-gray-600 mt-1 line-clamp-2">
                  {renderText(service.description)}
                </div>
              )}
            </Label>
          </div>
        </div>

        {/* Render child services */}
        {hasChildren && isExpanded && (
          <div className="ml-6 space-y-2 mt-1">
            {service.childServices!.map((childService) =>
              renderService(childService, true)
            )}
          </div>
        )}
      </div>
    );
  };

  return (
    <Dialog open={isOpen} onOpenChange={onClose}>
      <DialogContent className="max-w-2xl h-[80vh] flex flex-col">
        <DialogHeader>
          <DialogTitle>{t("assignServices", "Assign Services")}</DialogTitle>
          <DialogDescription>
            {t(
              "assignServicesDescription",
              `Select one or more services to assign to position: ${positionName}`
            )}
          </DialogDescription>
        </DialogHeader>

        <div className="flex-1 flex flex-col min-h-0 gap-4">
          {/* Search */}
          <div className="relative shrink-0">
            <Search className="absolute left-2 top-2.5 h-4 w-4 text-gray-500" />
            <Input
              placeholder={t(
                "searchServices",
                "Search services or categories..."
              )}
              className="pl-8"
              value={searchQuery}
              onChange={(e) => setSearchQuery(e.target.value)}
            />
          </div>

          {/* Tree View */}
          <ScrollArea className="flex-1 border rounded-md p-2 min-h-0">
            <div className="max-h-[400px]">
              {categoriesLoading ? (
                <div className="flex items-center justify-center py-8">
                  <Loader2 className="h-8 w-8 animate-spin text-purple-600" />
                </div>
              ) : filteredData.categories.length === 0 &&
                filteredData.services.length === 0 ? (
                <div className="text-center py-8 text-gray-500">
                  {t("noServicesFound", "No services found")}
                </div>
              ) : (
                <div>
                  <div className="space-y-1 pr-3">
                    {filteredData.categories.map((category) => {
                      const categoryServices = searchQuery
                        ? filteredData.services.filter(
                            (s) =>
                              s.serviceCategoryId === category.id &&
                              !s.parentServiceId
                          )
                        : parentServicesByCategory[category.id] || [];

                      const isExpanded = expandedCategories.has(category.id);

                      if (searchQuery && categoryServices.length === 0) {
                        return null;
                      }

                      return (
                        <div key={category.id} className="space-y-1">
                          {/* Category Header */}
                          <div
                            className="flex items-center gap-2 p-2 rounded-md hover:bg-gray-100 cursor-pointer"
                            onClick={() => toggleCategory(category.id)}
                          >
                            {isExpanded ? (
                              <ChevronDown className="h-4 w-4 text-gray-500" />
                            ) : (
                              <ChevronRight className="h-4 w-4 text-gray-500" />
                            )}
                            <Folder className="h-4 w-4 text-purple-500" />
                            <span className="font-medium text-gray-900">
                              {renderText(category.name)}
                            </span>
                            <span className="text-xs text-gray-500 ml-auto">
                              ({categoryServices.length})
                            </span>
                          </div>

                          {/* Services under this category */}
                          {isExpanded && categoryServices.length > 0 && (
                            <div className="ml-6 space-y-2 mt-1">
                              {categoryServices.map((service) =>
                                renderService(service)
                              )}
                            </div>
                          )}
                        </div>
                      );
                    })}

                    {/* Uncategorized services */}
                    {parentServicesByCategory["uncategorized"] &&
                      parentServicesByCategory["uncategorized"].length > 0 && (
                        <div className="space-y-1">
                          <div
                            className="flex items-center gap-2 p-2 rounded-md hover:bg-gray-100 cursor-pointer"
                            onClick={() => toggleCategory("uncategorized")}
                          >
                            {expandedCategories.has("uncategorized") ? (
                              <ChevronDown className="h-4 w-4 text-gray-500" />
                            ) : (
                              <ChevronRight className="h-4 w-4 text-gray-500" />
                            )}
                            <Folder className="h-4 w-4 text-gray-400" />
                            <span className="font-medium text-gray-700">
                              Uncategorized
                            </span>
                            <span className="text-xs text-gray-500 ml-auto">
                              (
                              {parentServicesByCategory["uncategorized"].length}
                              )
                            </span>
                          </div>

                          {expandedCategories.has("uncategorized") && (
                            <div className="ml-6 space-y-2 mt-1">
                              {parentServicesByCategory["uncategorized"].map(
                                (service) => renderService(service)
                              )}
                            </div>
                          )}
                        </div>
                      )}
                  </div>
                </div>
              )}
            </div>
          </ScrollArea>

          {/* Selected service info */}
          <div className="flex items-center justify-between text-sm shrink-0">
            <div className="text-gray-600">
              {selectedServiceIds.length > 0
                ? t(
                    "servicesSelected",
                    `${selectedServiceIds.length} service(s) selected`
                  )
                : t("noServiceSelected", "No services selected")}
            </div>
            {selectedServiceIds.length > 0 && (
              <Button
                variant="ghost"
                size="sm"
                onClick={handleClearSelection}
                className="text-red-600 hover:text-red-700 hover:bg-red-50"
              >
                {t("clearSelection", "Clear Selection")}
              </Button>
            )}
          </div>
        </div>

        <DialogFooter className="shrink-0">
          <Button variant="outline" onClick={onClose} disabled={isSaving}>
            {t("common.cancel", "Cancel")}
          </Button>
          <Button
            onClick={handleSave}
            disabled={isSaving || selectedServiceIds.length === 0}
            className="bg-purple-600 hover:bg-purple-700"
          >
            {isSaving ? (
              <>
                <Loader2 className="h-4 w-4 mr-2 animate-spin" />
                {t("saving", "Saving...")}
              </>
            ) : (
              t("assignServices", "Assign Services")
            )}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
};
