import React, { useCallback, useEffect, useMemo } from "react";
import {
  useForm,
  Controller,
  useWatch,
  Control,
  FieldValues,
} from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { debounce } from "lodash";
import {
  colorSchema,
  urlSchema,
  emailSchema,
  numberRangeSchema,
  stringLengthSchema,
  validateFormField,
  ValidationError,
} from "./validation";
import { useCMSEditor } from "./store";

// Form field interfaces
interface BaseFormFieldProps {
  name: string;
  label: string;
  description?: string;
  required?: boolean;
  disabled?: boolean;
  className?: string;
}

interface TextFieldProps extends BaseFormFieldProps {
  type?: "text" | "email" | "url" | "tel" | "password";
  placeholder?: string;
  maxLength?: number;
  minLength?: number;
}

interface NumberFieldProps extends BaseFormFieldProps {
  min?: number;
  max?: number;
  step?: number;
  placeholder?: string;
}

interface SelectFieldProps extends BaseFormFieldProps {
  options: Array<{ value: string | number; label: string; disabled?: boolean }>;
  placeholder?: string;
}

interface ColorFieldProps extends BaseFormFieldProps {
  allowTransparent?: boolean;
}

interface ToggleFieldProps extends BaseFormFieldProps {
  size?: "small" | "medium" | "large";
}

interface RangeFieldProps extends BaseFormFieldProps {
  min: number;
  max: number;
  step?: number;
  showValue?: boolean;
  formatValue?: (value: number) => string;
}

// Error display component
const FieldError: React.FC<{ error?: string }> = ({ error }) => {
  if (!error) return null;

  return (
    <div className="mt-1 text-sm text-red-600 flex items-center">
      <svg className="w-4 h-4 mr-1" viewBox="0 0 20 20" fill="currentColor">
        <path
          fillRule="evenodd"
          d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z"
          clipRule="evenodd"
        />
      </svg>
      {error}
    </div>
  );
};

// Success indicator
const FieldSuccess: React.FC<{ show: boolean }> = ({ show }) => {
  if (!show) return null;

  return (
    <div className="mt-1 text-sm text-green-600 flex items-center">
      <svg className="w-4 h-4 mr-1" viewBox="0 0 20 20" fill="currentColor">
        <path
          fillRule="evenodd"
          d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
          clipRule="evenodd"
        />
      </svg>
      유효한 값입니다
    </div>
  );
};

// Text input component
export const TextField: React.FC<
  TextFieldProps & { control: Control<FieldValues> }
> = ({
  name,
  label,
  description,
  type = "text",
  placeholder,
  required = false,
  disabled = false,
  maxLength,
  minLength,
  className = "",
  control,
}) => {
  return (
    <div className={`space-y-2 ${className}`}>
      <label htmlFor={name} className="block text-sm font-medium text-gray-700">
        {label}
        {required && <span className="text-red-500 ml-1">*</span>}
      </label>

      {description && <p className="text-sm text-gray-500">{description}</p>}

      <Controller
        name={name}
        control={control}
        render={({ field, fieldState: { error, invalid } }) => (
          <div>
            <input
              {...field}
              id={name}
              type={type}
              placeholder={placeholder}
              disabled={disabled}
              maxLength={maxLength}
              minLength={minLength}
              className={`
                w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm
                focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500
                disabled:bg-gray-50 disabled:text-gray-500
                ${
                  invalid
                    ? "border-red-300 focus:ring-red-500 focus:border-red-500"
                    : ""
                }
                ${!invalid && field.value ? "border-green-300" : ""}
              `}
            />
            <FieldError error={error?.message} />
            <FieldSuccess show={!invalid && !!field.value} />
          </div>
        )}
      />
    </div>
  );
};

// Number input component
export const NumberField: React.FC<
  NumberFieldProps & { control: Control<FieldValues> }
> = ({
  name,
  label,
  description,
  min,
  max,
  step = 1,
  placeholder,
  required = false,
  disabled = false,
  className = "",
  control,
}) => {
  return (
    <div className={`space-y-2 ${className}`}>
      <label htmlFor={name} className="block text-sm font-medium text-gray-700">
        {label}
        {required && <span className="text-red-500 ml-1">*</span>}
      </label>

      {description && <p className="text-sm text-gray-500">{description}</p>}

      <Controller
        name={name}
        control={control}
        render={({ field, fieldState: { error, invalid } }) => (
          <div>
            <input
              {...field}
              id={name}
              type="number"
              min={min}
              max={max}
              step={step}
              placeholder={placeholder}
              disabled={disabled}
              onChange={(e) => field.onChange(parseFloat(e.target.value) || 0)}
              className={`
                w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm
                focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500
                disabled:bg-gray-50 disabled:text-gray-500
                ${
                  invalid
                    ? "border-red-300 focus:ring-red-500 focus:border-red-500"
                    : ""
                }
                ${
                  !invalid && field.value !== undefined
                    ? "border-green-300"
                    : ""
                }
              `}
            />
            <FieldError error={error?.message} />
            <FieldSuccess show={!invalid && field.value !== undefined} />
          </div>
        )}
      />
    </div>
  );
};

// Select dropdown component
export const SelectField: React.FC<
  SelectFieldProps & { control: Control<FieldValues> }
> = ({
  name,
  label,
  description,
  options,
  placeholder,
  required = false,
  disabled = false,
  className = "",
  control,
}) => {
  return (
    <div className={`space-y-2 ${className}`}>
      <label htmlFor={name} className="block text-sm font-medium text-gray-700">
        {label}
        {required && <span className="text-red-500 ml-1">*</span>}
      </label>

      {description && <p className="text-sm text-gray-500">{description}</p>}

      <Controller
        name={name}
        control={control}
        render={({ field, fieldState: { error, invalid } }) => (
          <div>
            <select
              {...field}
              id={name}
              disabled={disabled}
              className={`
                w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm
                focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500
                disabled:bg-gray-50 disabled:text-gray-500
                ${
                  invalid
                    ? "border-red-300 focus:ring-red-500 focus:border-red-500"
                    : ""
                }
                ${!invalid && field.value ? "border-green-300" : ""}
              `}
            >
              {placeholder && <option value="">{placeholder}</option>}
              {options.map((option) => (
                <option
                  key={option.value}
                  value={option.value}
                  disabled={option.disabled}
                >
                  {option.label}
                </option>
              ))}
            </select>
            <FieldError error={error?.message} />
            <FieldSuccess show={!invalid && !!field.value} />
          </div>
        )}
      />
    </div>
  );
};

// Color picker component
export const ColorField: React.FC<ColorFieldProps & { control: any }> = ({
  name,
  label,
  description,
  required = false,
  disabled = false,
  allowTransparent = false,
  className = "",
  control,
}) => {
  return (
    <div className={`space-y-2 ${className}`}>
      <label htmlFor={name} className="block text-sm font-medium text-gray-700">
        {label}
        {required && <span className="text-red-500 ml-1">*</span>}
      </label>

      {description && <p className="text-sm text-gray-500">{description}</p>}

      <Controller
        name={name}
        control={control}
        render={({ field, fieldState: { error, invalid } }) => (
          <div>
            <div className="flex items-center space-x-3">
              <input
                {...field}
                id={name}
                type="color"
                disabled={disabled}
                className={`
                  w-12 h-10 border border-gray-300 rounded cursor-pointer
                  disabled:cursor-not-allowed disabled:opacity-50
                  ${invalid ? "border-red-300" : ""}
                  ${!invalid && field.value ? "border-green-300" : ""}
                `}
              />
              <input
                {...field}
                type="text"
                placeholder="#FF0000"
                disabled={disabled}
                className={`
                  flex-1 px-3 py-2 border border-gray-300 rounded-md shadow-sm
                  focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500
                  disabled:bg-gray-50 disabled:text-gray-500
                  ${
                    invalid
                      ? "border-red-300 focus:ring-red-500 focus:border-red-500"
                      : ""
                  }
                  ${!invalid && field.value ? "border-green-300" : ""}
                `}
              />
              {allowTransparent && (
                <button
                  type="button"
                  onClick={() => field.onChange("transparent")}
                  disabled={disabled}
                  className="px-3 py-2 text-sm border border-gray-300 rounded-md hover:bg-gray-50 disabled:opacity-50"
                >
                  투명
                </button>
              )}
            </div>
            <FieldError error={error?.message} />
            <FieldSuccess show={!invalid && !!field.value} />
          </div>
        )}
      />
    </div>
  );
};

// Toggle switch component
export const ToggleField: React.FC<ToggleFieldProps & { control: any }> = ({
  name,
  label,
  description,
  required = false,
  disabled = false,
  size = "medium",
  className = "",
  control,
}) => {
  const sizeClasses = {
    small: "w-8 h-4",
    medium: "w-10 h-5",
    large: "w-12 h-6",
  };

  const thumbSizeClasses = {
    small: "w-3 h-3",
    medium: "w-4 h-4",
    large: "w-5 h-5",
  };

  return (
    <div className={`space-y-2 ${className}`}>
      <Controller
        name={name}
        control={control}
        render={({ field, fieldState: { error } }) => (
          <div>
            <div className="flex items-center justify-between">
              <div>
                <label
                  htmlFor={name}
                  className="block text-sm font-medium text-gray-700"
                >
                  {label}
                  {required && <span className="text-red-500 ml-1">*</span>}
                </label>
                {description && (
                  <p className="text-sm text-gray-500">{description}</p>
                )}
              </div>

              <button
                {...field}
                id={name}
                type="button"
                role="switch"
                aria-checked={field.value}
                disabled={disabled}
                onClick={() => field.onChange(!field.value)}
                className={`
                  relative inline-flex items-center ${
                    sizeClasses[size]
                  } rounded-full
                  transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2
                  focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed
                  ${field.value ? "bg-blue-600" : "bg-gray-300"}
                `}
              >
                <span
                  className={`
                    ${
                      thumbSizeClasses[size]
                    } inline-block bg-white rounded-full shadow
                    transform transition-transform duration-200 ease-in-out
                    ${
                      field.value
                        ? size === "small"
                          ? "translate-x-4"
                          : size === "medium"
                          ? "translate-x-5"
                          : "translate-x-6"
                        : "translate-x-0.5"
                    }
                  `}
                />
              </button>
            </div>
            <FieldError error={error?.message} />
          </div>
        )}
      />
    </div>
  );
};

// Range slider component
export const RangeField: React.FC<RangeFieldProps & { control: any }> = ({
  name,
  label,
  description,
  min,
  max,
  step = 1,
  showValue = true,
  formatValue,
  required = false,
  disabled = false,
  className = "",
  control,
}) => {
  return (
    <div className={`space-y-2 ${className}`}>
      <div className="flex items-center justify-between">
        <label
          htmlFor={name}
          className="block text-sm font-medium text-gray-700"
        >
          {label}
          {required && <span className="text-red-500 ml-1">*</span>}
        </label>
        {showValue && (
          <Controller
            name={name}
            control={control}
            render={({ field }) => (
              <span className="text-sm font-mono text-gray-600">
                {formatValue ? formatValue(field.value) : field.value}
              </span>
            )}
          />
        )}
      </div>

      {description && <p className="text-sm text-gray-500">{description}</p>}

      <Controller
        name={name}
        control={control}
        render={({ field, fieldState: { error, invalid } }) => (
          <div>
            <input
              {...field}
              id={name}
              type="range"
              min={min}
              max={max}
              step={step}
              disabled={disabled}
              onChange={(e) => field.onChange(parseFloat(e.target.value))}
              className={`
                w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer
                disabled:opacity-50 disabled:cursor-not-allowed
                ${invalid ? "accent-red-500" : "accent-blue-500"}
              `}
            />
            <div className="flex justify-between text-xs text-gray-500 mt-1">
              <span>{min}</span>
              <span>{max}</span>
            </div>
            <FieldError error={error?.message} />
          </div>
        )}
      />
    </div>
  );
};

// Optimistic form wrapper
interface OptimisticFormProps {
  sectionId: string;
  schema: z.ZodSchema;
  defaultValues: any;
  onSubmit: (data: any) => Promise<void>;
  children: (props: {
    control: any;
    formState: any;
    handleSubmit: any;
  }) => React.ReactNode;
  className?: string;
}

export const OptimisticForm: React.FC<OptimisticFormProps> = ({
  sectionId,
  schema,
  defaultValues,
  onSubmit,
  children,
  className = "",
}) => {
  const {
    updateSection,
    startOptimisticUpdate,
    finishOptimisticUpdate,
    rollbackOptimisticUpdate,
  } = useCMSEditor();

  const form = useForm({
    resolver: zodResolver(schema),
    defaultValues,
    mode: "onChange",
  });

  const { control, handleSubmit, formState, watch, getValues } = form;

  // Watch for changes and apply optimistic updates
  const watchedValues = useWatch({ control });

  const debouncedOptimisticUpdate = useMemo(
    () =>
      debounce((values: any) => {
        startOptimisticUpdate(sectionId);
        updateSection(sectionId, values);
      }, 300),
    [sectionId, startOptimisticUpdate, updateSection]
  );

  useEffect(() => {
    if (formState.isValid && !formState.isSubmitting) {
      debouncedOptimisticUpdate(watchedValues);
    }

    return () => {
      debouncedOptimisticUpdate.cancel();
    };
  }, [
    watchedValues,
    formState.isValid,
    formState.isSubmitting,
    debouncedOptimisticUpdate,
  ]);

  const handleFormSubmit = useCallback(
    async (data: any) => {
      try {
        startOptimisticUpdate(sectionId);
        await onSubmit(data);
        finishOptimisticUpdate(sectionId, true);
      } catch (error) {
        console.error("Form submission failed:", error);
        rollbackOptimisticUpdate(sectionId);
        finishOptimisticUpdate(sectionId, false);
      }
    },
    [
      sectionId,
      onSubmit,
      startOptimisticUpdate,
      finishOptimisticUpdate,
      rollbackOptimisticUpdate,
    ]
  );

  return (
    <form onSubmit={handleSubmit(handleFormSubmit)} className={className}>
      {children({
        control,
        formState,
        handleSubmit: handleSubmit(handleFormSubmit),
      })}
    </form>
  );
};

// Real-time validation indicator
export const ValidationIndicator: React.FC<{
  sectionId: string;
  className?: string;
}> = ({ sectionId, className = "" }) => {
  const { validationErrors, pendingUpdates } = useCMSEditor();
  const errors = validationErrors[sectionId] || [];
  const isPending = pendingUpdates.has(sectionId);

  if (isPending) {
    return (
      <div className={`flex items-center text-blue-600 ${className}`}>
        <svg className="animate-spin w-4 h-4 mr-1" viewBox="0 0 24 24">
          <circle
            cx="12"
            cy="12"
            r="10"
            stroke="currentColor"
            strokeWidth="4"
            fill="none"
            opacity="0.25"
          />
          <path
            fill="currentColor"
            d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
          />
        </svg>
        <span className="text-sm">저장 중...</span>
      </div>
    );
  }

  if (errors.length > 0) {
    return (
      <div className={`flex items-center text-red-600 ${className}`}>
        <svg className="w-4 h-4 mr-1" viewBox="0 0 20 20" fill="currentColor">
          <path
            fillRule="evenodd"
            d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z"
            clipRule="evenodd"
          />
        </svg>
        <span className="text-sm">{errors.length}개 오류</span>
      </div>
    );
  }

  return (
    <div className={`flex items-center text-green-600 ${className}`}>
      <svg className="w-4 h-4 mr-1" viewBox="0 0 20 20" fill="currentColor">
        <path
          fillRule="evenodd"
          d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
          clipRule="evenodd"
        />
      </svg>
      <span className="text-sm">저장됨</span>
    </div>
  );
};
