/**
 * Copyright (c) 2023-present Pi Dash Software, Inc. and contributors
 * SPDX-License-Identifier: AGPL-3.0-only
 * See the LICENSE file for details.
 */

import { useCallback, useMemo, useState } from "react";
import { orderBy } from "lodash-es";
import { observer } from "mobx-react";
import { GripVertical, X } from "lucide-react";
// pi dash imports
import { useTranslation } from "@pi-dash/i18n";
import { Checkbox, EModalPosition, EModalWidth, ModalCore, Sortable } from "@pi-dash/ui";
import { cn } from "@pi-dash/utils";
// hooks
import { usePersonalNavigationPreferences, useProjectNavigationPreferences } from "@/hooks/use-navigation-preferences";
// helpers
import { getSidebarNavigationItemIcon } from "@/pi-dash-web/components/workspace/sidebar/helper";
// types
import type { TPersonalNavigationItemKey } from "@/types/navigation-preferences";

type TCustomizeNavigationDialogProps = {
  isOpen: boolean;
  onClose: () => void;
};

const PERSONAL_ITEMS: Array<{ key: TPersonalNavigationItemKey; labelTranslationKey: string }> = [
  { key: "your_work", labelTranslationKey: "Your work" },
  { key: "drafts", labelTranslationKey: "Drafts" },
];

// Block: e, E, +, -, . — extracted to module scope so the handler isn't recreated on every render.
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
  if (["e", "E", "+", "-", "."].includes(e.key)) {
    e.preventDefault();
  }
};

export const CustomizeNavigationDialog = observer(function CustomizeNavigationDialog(
  props: TCustomizeNavigationDialogProps
) {
  const { isOpen, onClose } = props;
  const { t } = useTranslation();

  // store hooks
  const {
    preferences: personalPreferences,
    togglePersonalItem,
    updatePersonalItemOrder,
  } = usePersonalNavigationPreferences();
  const {
    preferences: projectPreferences,
    updateNavigationMode,
    updateShowLimitedProjects,
    updateLimitedProjectsCount,
  } = useProjectNavigationPreferences();

  // local state for limited projects count input
  const [projectCountInput, setProjectCountInput] = useState(projectPreferences.limitedProjectsCount.toString());

  // Filter personal items by feature flags
  const filteredPersonalItems = PERSONAL_ITEMS;

  // Handle reorder of enabled personal items
  const handlePersonalReorder = useCallback(
    (newData: Array<{ key: TPersonalNavigationItemKey; labelTranslationKey: string }>) => {
      const itemsWithOrder = newData.map((item, index) => ({
        key: item.key,
        sortOrder: index,
      }));
      updatePersonalItemOrder(itemsWithOrder);
    },
    [updatePersonalItemOrder]
  );

  // Separate personal items into enabled/disabled
  const personalItems = useMemo(() => {
    const items = filteredPersonalItems.map((item) => {
      const itemState = personalPreferences.items[item.key];
      const isEnabled = typeof itemState === "boolean" ? itemState : (itemState?.enabled ?? true);
      const sortOrder = typeof itemState === "boolean" ? 0 : (itemState?.sort_order ?? 0);

      return {
        ...item,
        isEnabled,
        sortOrder,
      };
    });

    return orderBy(items, ["sortOrder"], ["asc"]);
  }, [personalPreferences, filteredPersonalItems]);

  // Handle project count input change
  const handleProjectCountChange = (value: string) => {
    // Strip any non-digit characters
    const cleanedValue = value.replace(/\D/g, "");
    setProjectCountInput(cleanedValue);

    // Parse and validate the value
    const numValue = parseInt(cleanedValue, 10);

    // If valid number, enforce minimum of 1
    if (!isNaN(numValue)) {
      const validValue = Math.max(1, numValue);
      updateLimitedProjectsCount(validValue);
    }
  };

  return (
    <ModalCore isOpen={isOpen} handleClose={onClose} position={EModalPosition.CENTER} width={EModalWidth.XXL}>
      <div className="flex max-h-[90vh] flex-col rounded-lg bg-surface-1">
        {/* Header */}
        <div className="flex justify-between px-6 pt-4">
          <div>
            <h2 className="text-18 font-semibold text-primary">{t("Customize navigation")}</h2>
            <p className="mt-1 text-13 text-tertiary">
              Toggle which personal items appear in the sidebar and configure how projects are listed. These changes are
              personal to you and won&apos;t affect anyone else on your workspace.
            </p>
          </div>
          <button
            onClick={onClose}
            className="flex size-5 flex-shrink-0 items-center justify-center rounded-sm text-placeholder hover:bg-layer-1"
            aria-label={t("Close")}
          >
            <X className="size-4" />
          </button>
        </div>

        {/* Content */}
        <div className="flex-1 space-y-4 overflow-y-auto px-6 py-4">
          {/* Personal Section */}
          <div className="flex flex-col gap-2">
            <h3 className="text-13 font-semibold text-placeholder">{t("Personal")}</h3>
            <div className="rounded-md border border-subtle bg-surface-2 py-2">
              <Sortable
                data={personalItems}
                onChange={handlePersonalReorder}
                keyExtractor={(item) => item.key}
                id="personal-enabled-items"
                render={(item) => (
                  <div className="flex items-center gap-2 rounded-md px-2 py-1.5 transition-all duration-200 hover:bg-surface-2">
                    <GripVertical className="size-4 cursor-grab text-placeholder transition-colors active:cursor-grabbing" />
                    <Checkbox
                      checked={!!personalPreferences.items[item.key]?.enabled}
                      onChange={(e) => togglePersonalItem(item.key, e.target.checked)}
                    />
                    <div className="flex flex-1 items-center gap-2">
                      {getSidebarNavigationItemIcon(item.key)}
                      <label className="flex-1 cursor-pointer text-13 text-primary">
                        {t(item.labelTranslationKey)}
                      </label>
                    </div>
                  </div>
                )}
              />
            </div>
          </div>

          {/* Projects Section */}
          <div className="flex flex-col gap-2">
            <h3 className="text-13 font-semibold text-placeholder">{t("Projects")}</h3>

            <div className="rounded-md border border-subtle bg-surface-2 px-2 py-2">
              <div className="space-y-3">
                {/* Navigation Mode Radio Buttons */}
                <div className="space-y-2">
                  <label
                    aria-label={t("Accordion sidebar navigation")}
                    className="flex cursor-pointer gap-2 rounded-md px-2 py-1.5 hover:bg-surface-2"
                  >
                    <input
                      type="radio"
                      name="navigation-mode"
                      value="ACCORDION"
                      checked={projectPreferences.navigationMode === "ACCORDION"}
                      onChange={() => updateNavigationMode("ACCORDION")}
                      className="mt-1 size-4 text-accent-primary focus:ring-accent-strong"
                    />
                    <div className="flex-1">
                      <div className="text-13 text-primary">{t("Accordion sidebar navigation")}</div>
                      <div className="text-11 text-secondary">
                        Feature tabs will appear as nested items under project and acts as accordion.
                      </div>
                    </div>
                  </label>

                  <label
                    aria-label={t("Tabbed Navigation")}
                    className="flex cursor-pointer gap-2 rounded-md px-2 py-1.5 hover:bg-surface-2"
                  >
                    <input
                      type="radio"
                      name="navigation-mode"
                      value="TABBED"
                      checked={projectPreferences.navigationMode === "TABBED"}
                      onChange={() => updateNavigationMode("TABBED")}
                      className="mt-1 size-4 text-accent-primary focus:ring-accent-strong"
                    />
                    <div className="flex-1">
                      <div className="text-13 text-primary">{t("Tabbed Navigation")}</div>
                      <div className="text-11 text-secondary">
                        Feature tabs will appear as horizontal tabs inside a project.
                      </div>
                    </div>
                  </label>
                </div>

                {/* Limited Projects Checkbox */}
                <div className="space-y-1">
                  <label className="flex cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 hover:bg-surface-2">
                    <Checkbox
                      checked={projectPreferences.showLimitedProjects}
                      onChange={(e) => updateShowLimitedProjects(e.target.checked)}
                    />
                    <span className="text-13 text-primary">{t("Show limited projects on sidebar")}</span>
                  </label>

                  {projectPreferences.showLimitedProjects && (
                    <div className="pl-8">
                      <div className="flex w-full flex-col gap-1">
                        <div className="flex w-full flex-col gap-2 pb-1.5">
                          <label className="w-full text-11 text-secondary">{t("Enter number of projects")}</label>
                          <input
                            type="number"
                            min="1"
                            step="1"
                            value={projectCountInput}
                            onKeyDown={handleKeyDown}
                            onChange={(e) => handleProjectCountChange(e.target.value)}
                            className={cn(
                              "w-full rounded-md px-2 py-1 text-13",
                              "border bg-surface-2",
                              "text-secondary",
                              parseInt(projectCountInput) >= 1
                                ? "border-strong focus:border-accent-strong focus:ring-1 focus:ring-accent-strong"
                                : "border-danger-strong focus:border-danger-strong focus:ring-1 focus:ring-danger-strong"
                            )}
                          />
                        </div>
                        {parseInt(projectCountInput) < 1 && projectCountInput !== "" && (
                          <span className="pl-0.5 text-11 text-danger-primary">Minimum value is 1</span>
                        )}
                      </div>
                    </div>
                  )}
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </ModalCore>
  );
});
