import { useState, useEffect } from "react";
import TailwindModal from "./TailwindModal";
import { ComponentInfo, HookInfo, PropertyInfo } from "../../proxy/developerKit/componentInfo";
import { getComponentDefinition } from "./data/componentDefinitions";
import { Button } from "../ui";

interface PropertyPanelProps {
  selectedComponent: ComponentInfo | null;
  currentCode: string;
  onPropertiesChange: (
    componentId: string,
    updates: Record<string, any>
  ) => void;
  onHookToggle: (
    componentId: string,
    hookType: string,
    enabled: boolean
  ) => void;
  onMultipleHookToggle: (
    toggles: { componentId: string; hookType: string; enabled: boolean }[]
  ) => void;
  onDeleteComponent: (componentId: string) => void;
}

const PropertyPanel: React.FC<PropertyPanelProps> = ({
  selectedComponent,
  currentCode,
  onPropertiesChange,
  onHookToggle,
  onMultipleHookToggle,
  onDeleteComponent,
}) => {
  const [tailwindModalOpen, setTailwindModalOpen] = useState(false);
  const [currentTailwindProperty, setCurrentTailwindProperty] =
    useState<string>("");
  const [activeHooks, setActiveHooks] = useState<Set<string>>(new Set());
  const [activeTab, setActiveTab] = useState<"props" | "hooks">("props");

  // Local state for pending changes
  const [pendingProperties, setPendingProperties] = useState<
    Record<string, any>
  >({});
  const [pendingEvents, setPendingEvents] = useState<Record<string, string>>(
    {}
  );
  const [pendingHooks, setPendingHooks] = useState<Record<string, boolean>>({});
  const [hasChanges, setHasChanges] = useState(false);
  const [hasHookChanges, setHasHookChanges] = useState(false);

  const componentDefinition = selectedComponent
    ? getComponentDefinition(selectedComponent.name)
    : null;

  // Reset pending changes when component changes
  useEffect(() => {
    setPendingProperties({});
    setPendingEvents({});
    setPendingHooks({});
    setHasChanges(false);
    setHasHookChanges(false);
  }, [selectedComponent?.id]);

  // Check which hooks are currently active in the code
  useEffect(() => {
    if (selectedComponent && currentCode) {
      const hooks = new Set<string>();

      // Check for useState
      if (
        currentCode.includes(
          `const [state_${selectedComponent.id}, setState_${selectedComponent.id}]`
        )
      ) {
        hooks.add("useState");
      }

      // Check for useRef
      if (
        currentCode.includes(`const ref_${selectedComponent.id}`) &&
        currentCode.includes(`ref={ref_${selectedComponent.id}`)
      ) {
        hooks.add("useRef");
      }

      // // Check for useEffect
      // if (
      //   currentCode.includes("useEffect") &&
      //   currentCode.includes(selectedComponent.id)
      // ) {
      //   hooks.add("useEffect");
      // }

      setActiveHooks(hooks);
    }
  }, [selectedComponent, currentCode]);

  // Handle local property changes
  const handleLocalPropertyChange = (propName: string, value: any) => {
    setPendingProperties((prev) => ({
      ...prev,
      [propName]: value,
    }));
    setHasChanges(true);
  };

  // Handle local hook changes
  const handleLocalHookToggle = (hookType: string, enabled: boolean) => {
    setPendingHooks((prev) => ({
      ...prev,
      [hookType]: enabled,
    }));
    setHasHookChanges(true);
  };

  // Handle local event changes
  const handleLocalEventChange = (eventName: string, value: string) => {
    setPendingEvents((prev) => ({
      ...prev,
      [eventName]: value,
    }));
    setHasChanges(true);
  };

  // Apply only property/event changes
  const handleApplyPropChanges = () => {
    if (!selectedComponent) return;

    // Combine all changes into a single update object
    const allUpdates = {
      ...pendingProperties,
      ...pendingEvents,
    };

    // Apply property and event changes together
    if (Object.keys(allUpdates).length > 0) {
      onPropertiesChange(selectedComponent.id, allUpdates);
    }

    // Reset pending changes
    setPendingProperties({});
    setPendingEvents({});
    setHasChanges(false);
  };

  // Apply only hook changes
  const handleApplyHookChanges = () => {
    if (!selectedComponent) return;

    const hookToggles = Object.entries(pendingHooks).map(
      ([hookType, enabled]) => ({
        componentId: selectedComponent.id,
        hookType,
        enabled,
      })
    );
    if (hookToggles.length > 1) {
      onMultipleHookToggle(hookToggles);
    } else if (hookToggles.length === 1) {
      const { componentId, hookType, enabled } = hookToggles[0];
      onHookToggle(componentId, hookType, enabled);
    }

    // Reset pending changes
    setPendingHooks({});
    setHasHookChanges(false);
  };

  // Reset all pending changes
  const handleResetChanges = () => {
    setPendingProperties({});
    setPendingEvents({});
    setPendingHooks({});
    setHasChanges(false);
    setHasHookChanges(false);
  };

  const openTailwindModal = (propertyName: string) => {
    setCurrentTailwindProperty(propertyName);
    setTailwindModalOpen(true);
  };

  const handleTailwindClassSelect = (className: string) => {
    const currentValue =
      pendingProperties[currentTailwindProperty] ||
      selectedComponent?.props[currentTailwindProperty] ||
      "";
    const newValue = currentValue ? `${currentValue} ${className}` : className;
    handleLocalPropertyChange(currentTailwindProperty, newValue);
    // Don't close modal - let user continue selecting
  };

  const renderPropertyControl = (property: PropertyInfo) => {
    // Handle children property specially - get from children, not props
    const currentValue =
      property.name === "children"
        ? typeof selectedComponent?.children === "string"
          ? selectedComponent.children
          : selectedComponent?.props[property.name] || property.value
        : selectedComponent?.props[property.name] || property.value;

    // Use pending value if available, otherwise use current value
    const value =
      pendingProperties[property.name] !== undefined
        ? pendingProperties[property.name]
        : currentValue;
    const isTailwindProperty = ["className", "class", "css"].includes(
      property.name
    );
    const isColorProperty = property.name.toLowerCase().includes("color");

    // Don't show children property if component has nested elements
    if (
      property.name === "children" &&
      Array.isArray(selectedComponent?.children)
    ) {
      return null;
    }

    let arrayError = "";
    let arrayInputValue = "";
    if (property.type === "array") {
      try {
        arrayInputValue = JSON.stringify(value, null, 2);
      } catch (e) {
        arrayInputValue = "";
        arrayError = "Array verisi gösterilemiyor.";
      }
    }
    return (
      <div key={property.name} className="mb-4">
        <label className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-2">
          {property.name}
          {property.description && (
            <span className="text-gray-500 dark:text-gray-400 text-xs ml-1">
              ({property.description})
            </span>
          )}
          {pendingProperties[property.name] !== undefined && (
            <span className="text-orange-500 text-xs ml-1">(değiştirildi)</span>
          )}
        </label>

        <div className="flex gap-2 flex-col">
          {property.type === "boolean" && (
            <label className="flex items-center">
              <input
                type="checkbox"
                checked={Boolean(value)}
                onChange={(e) =>
                  handleLocalPropertyChange(property.name, e.target.checked)
                }
                className="mr-2"
              />
              <span className="text-sm text-gray-600 dark:text-gray-300">{property.name}</span>
            </label>
          )}

          {property.type === "select" && property.options && (
            <select
              value={value || ""}
              onChange={(e) =>
                handleLocalPropertyChange(property.name, e.target.value)
              }
              className="flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-800 dark:text-white dark:placeholder-gray-400"
            >
              <option value="">Select {property.name}</option>
              {property.options.map((option) => (
                <option key={option} value={option}>
                  {option}
                </option>
              ))}
            </select>
          )}

          {property.type === "function" && (
            <>
              <input
                type="text"
                value={value || ""}
                onChange={(e) =>
                  handleLocalPropertyChange(property.name, e.target.value)
                }
                className="flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-800 dark:text-white dark:placeholder-gray-400"
                placeholder={`Enter ${property.name}`}
              />
              {isTailwindProperty && (
                <button
                  onClick={() => openTailwindModal(property.name)}
                  className="px-3 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-700 dark:text-white transition-colors text-sm"
                  title="Select Tailwind Classes"
                >
                  TW
                </button>
              )}
              {isColorProperty && (
                <input
                  type="color"
                  value={value || "#000000"}
                  onChange={(e) =>
                    handleLocalPropertyChange(property.name, e.target.value)
                  }
                  className="w-10 h-10 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-800"
                />
              )}
            </>
          )}

          {property.type === "string" && (
            <>
              <input
                type="text"
                value={value || ""}
                onChange={(e) =>
                  handleLocalPropertyChange(property.name, e.target.value)
                }
                className="flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-800 dark:text-white dark:placeholder-gray-400"
                placeholder={`Enter ${property.name}`}
              />
              {isTailwindProperty && (
                <button
                  onClick={() => openTailwindModal(property.name)}
                  className="px-3 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-700 dark:text-white transition-colors text-sm"
                  title="Select Tailwind Classes"
                >
                  TW
                </button>
              )}
              {isColorProperty && (
                <input
                  type="color"
                  value={value || "#000000"}
                  onChange={(e) =>
                    handleLocalPropertyChange(property.name, e.target.value)
                  }
                  className="w-10 h-10 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-800"
                />
              )}
            </>
          )}

          {property.type === "number" && (
            <input
              type="number"
              value={value || 0}
              onChange={(e) =>
                handleLocalPropertyChange(property.name, Number(e.target.value))
              }
              className="flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-800 dark:text-white dark:placeholder-gray-400"
            />
          )}

          {property.type === "array" && (
            <>
              <textarea
                className="flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md font-mono text-xs focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-800 dark:text-white dark:placeholder-gray-400"
                rows={Math.max(3, arrayInputValue.split('\n').length)}
                value={arrayInputValue}
                onChange={(e) => {
                  try {
                    const parsed = JSON.parse(e.target.value);
                    handleLocalPropertyChange(property.name, parsed);
                    arrayError = "";
                  } catch (err) {
                    arrayError = "Geçersiz JSON formatı";
                  }
                }}
                placeholder="[\n  { ... }\n]"
                spellCheck={false}
              />
              {arrayError && (
                <span className="text-xs text-red-500">{arrayError}</span>
              )}
            </>
          )}
        </div>
      </div>
    );
  };

  const renderHookControl = (hook: HookInfo) => {
    const currentlyActive = activeHooks.has(hook.type);
    const isActive =
      pendingHooks[hook.type] !== undefined
        ? pendingHooks[hook.type]
        : currentlyActive;

    return (
      <div key={hook.name} className="mb-4">
        <label className="flex items-center">
          <input
            type="checkbox"
            checked={isActive}
            onChange={(e) => handleLocalHookToggle(hook.type, e.target.checked)}
            className="mr-2"
          />
          <span className="text-sm font-medium text-gray-700">
            {hook.name} ({hook.type})
          </span>
          {pendingHooks[hook.type] !== undefined && (
            <span className="text-orange-500 text-xs ml-1">(değiştirildi)</span>
          )}
        </label>
      </div>
    );
  };

  if (!selectedComponent) {
    return (
      <div className="h-full bg-gray-50 dark:bg-gray-900 p-4">
        <div className="text-center text-gray-500 dark:text-gray-400 mt-8">
          <div className="text-4xl mb-4">🎯</div>
          <h3 className="text-lg font-medium mb-2 text-gray-700 dark:text-gray-200">No Component Selected</h3>
          <p className="text-sm text-gray-500 dark:text-gray-400">
            Select a component from the editor to edit its properties
          </p>
        </div>
      </div>
    );
  }

  function getDynamicProperties(): PropertyInfo[] {
    if (!selectedComponent) return [];

    const allDefinitionProps = componentDefinition?.properties || [];

    // Sadece tanımdan gelen properties
    const defProps = allDefinitionProps.filter(
      (p: any) => p.category === "properties"
    );

    // allDefinitionNames prop isimlerini belirle
    const allDefinitionNames = new Set(allDefinitionProps.map((p:any) => p.name));

    // Koddan gelen tüm props (id hariç), styling hariç, events hariç
    const codeProps = Object.entries(selectedComponent.props || {})
      .filter(([name]) => name !== "id" && !allDefinitionNames.has(name))
      .map(([name, value]) => {
        let type: PropertyInfo["type"] = "string";
        if (typeof value === "boolean") type = "boolean";
        else if (typeof value === "number") type = "number";
        else if (typeof value === "function") type = "function";
        else if (Array.isArray(value)) type = "array";
        else if (typeof value === "object" && value !== null) type = "object";

        return {
          name,
          type,
          value,
          category: "properties",
        } as PropertyInfo;
      });

    // Merge - öncelik kodda olanlar
    const merged: PropertyInfo[] = [];
    const seen = new Set<string>();

    for (const prop of codeProps) {
      merged.push(prop);
      seen.add(prop.name);
    }

    for (const prop of defProps) {
      if (!seen.has(prop.name)) {
        merged.push(prop);
      }
    }

    return merged;
  }

  const properties = getDynamicProperties();
  const hooks = componentDefinition?.hooks || [];
  const styling =
    componentDefinition?.properties?.filter((p: any) => p.category === "styling") ||
    [];
  const events =
    componentDefinition?.properties?.filter((p: any) => p.category === "events") ||
    [];

  return (
    <div className="w-full text-white flex flex-col h-full">
      {/* Header */}
      <div className="border-b bg-gray-50 dark:bg-gray-900 flex items-center justify-between dark:border-gray-700">
        <div>
          {(hasChanges || hasHookChanges) && (
            <p className="text-sm text-orange-600 mt-1">
              Bekleyen değişiklikler var
            </p>
          )}
          {/* Tabs */}
          <div className="flex gap-2 p-1">
            <button
              className={`px-3 py-1  font-medium border-b-2 transition-colors ${
                activeTab === "props"
                  ? "border-blue-500 text-blue-700 bg-white dark:bg-gray-900 dark:text-blue-400 dark:border-blue-400"
                  : "border-transparent text-gray-500 bg-gray-100 dark:bg-gray-800 dark:text-gray-400 dark:border-transparent"
              }`}
              onClick={() => setActiveTab("props")}
            >
              Properties
            </button>
            <button
              className={`px-3 py-1 font-medium border-b-2 transition-colors ${
                activeTab === "hooks"
                  ? "border-blue-500 text-blue-700 bg-white dark:bg-gray-900 dark:text-blue-400 dark:border-blue-400"
                  : "border-transparent text-gray-500 bg-gray-100 dark:bg-gray-800 dark:text-gray-400 dark:border-transparent"
              }`}
              onClick={() => setActiveTab("hooks")}
            >
              Hooks
            </button>
          </div>
        </div>
        {/* Sil Butonu */}
        <Button
          variant="solid"
          size="sm"
          className="mr-2 px-3 py-1 rounded bg-red-500 text-white hover:bg-red-600 dark:bg-red-700 dark:hover:bg-red-800 dark:text-white transition-colors text-sm"
          onClick={() => {
            if (selectedComponent) {
              if (
                window.confirm(
                  "Seçili komponenti silmek istediğinize emin misiniz?"
                )
              ) {
                onDeleteComponent(selectedComponent.id);
              }
            }
          }}
          title="Komponenti Sil"
        >
          Sil
        </Button>
      </div>

      {/* Footer Action Buttons - her iki tabda da sabit */}
      <div className="p-4 border-t">
        <div className="flex gap-2">
          <Button
            size="sm"
            variant="solid"
            onClick={
              activeTab === "props"
                ? handleApplyPropChanges
                : handleApplyHookChanges
            }
            disabled={activeTab === "props" ? !hasChanges : !hasHookChanges}
            className={`flex-1 rounded-md font-medium transition-colors ${
              (activeTab === "props" ? hasChanges : hasHookChanges)
                ? "bg-green-500 text-white hover:bg-green-600"
                : "bg-gray-300 text-gray-500 cursor-not-allowed"
            }`}
          >
            Uygula
          </Button>
          <Button
            size="sm"
            variant="default"
            onClick={
              activeTab === "props"
                ? handleResetChanges
                : () => {
                    setPendingHooks({});
                    setHasHookChanges(false);
                  }
            }
            disabled={activeTab === "props" ? !hasChanges : !hasHookChanges}
            className={`flex-1 rounded-md font-medium transition-colors ${
              (activeTab === "props" ? hasChanges : hasHookChanges)
                ? "bg-red-500 text-white hover:bg-red-600"
                : "bg-gray-300 text-gray-500 cursor-not-allowed"
            }`}
          >
            İptal
          </Button>
        </div>
      </div>

      {/* Content */}
      {activeTab === "props" && (
        <div className="flex-1 text-black dark:text-gray-200 overflow-y-auto p-4 max-h-[calc(100vh-200px)] bg-white dark:bg-gray-900">
          <h3 className="text-md font-medium text-gray-800 dark:text-gray-100 mb-4">Properties</h3>
          {/* Properties */}
          {properties.length > 0 && (
            <div>{properties.map(renderPropertyControl)}</div>
          )}
          {/* Events */}
          {events.length > 0 && (
            <div>
              <h3 className="text-md font-medium text-gray-800 dark:text-gray-100 mb-4 mt-6">
                Events
              </h3>
              {events.map(renderPropertyControl)}
            </div>
          )}
          {/* Styling */}
          {styling.length > 0 && (
            <div>
              <h3 className="text-md font-medium text-gray-800 dark:text-gray-100 mb-4 mt-6">
                Styling
              </h3>
              {styling.map(renderPropertyControl)}
            </div>
          )}
        </div>
      )}
      {activeTab === "hooks" && (
        <div className="flex-1 overflow-y-auto p-4">
          {/* Sadece useState ve useRef göster */}
          {hooks
            .filter((h: any) => h.type === "useState" || h.type === "useRef")
            .map(renderHookControl)}
        </div>
      )}

      {/* Tailwind Modal */}
      <TailwindModal
        isOpen={tailwindModalOpen}
        onClose={() => setTailwindModalOpen(false)}
        onSelectClass={handleTailwindClassSelect}
        currentValue={
          pendingProperties[currentTailwindProperty] ||
          (selectedComponent &&
            selectedComponent.props[currentTailwindProperty]) ||
          ""
        }
      />
    </div>
  );
};
export default PropertyPanel;
