import { useState, useEffect } from "react";
import { FieldValues } from "react-hook-form";
import { motion, Variants } from "framer-motion";
import { Button } from "@/shared/common/ui/button";
import {
  Card,
  CardContent,
  CardHeader,
  CardTitle,
  CardDescription,
} from "@/shared/common/ui/card";
import { Badge } from "@/shared/common/ui/badge";
import { useToast } from "@/shared/common/ui/use-toast";
import { Loader2, Check, ArrowLeft, Shield, Edit } from "lucide-react";
import { FormField, GenericFormProps } from "./shared-field-types";
import { FormFieldRenderer } from "./FormFieldRenderer";
import { cn } from "@/shared/lib/utils";
import { useInfiniteQuery } from "@tanstack/react-query";

const containerVariants: Variants = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: {
      staggerChildren: 0.08,
      duration: 0.6,
    },
  },
};

const sectionVariants: Variants = {
  hidden: {
    opacity: 0,
    y: 20,
    scale: 0.98,
  },
  visible: {
    opacity: 1,
    y: 0,
    scale: 1,
    transition: {
      type: "spring" as const,
      stiffness: 100,
      damping: 15,
      duration: 0.5,
    },
  },
};

const buttonVariants: Variants = {
  hidden: { opacity: 0, x: 20 },
  visible: {
    opacity: 1,
    x: 0,
    transition: {
      type: "spring",
      stiffness: 200,
      damping: 20,
    },
  },
  hover: {
    scale: 1.02,
    transition: {
      type: "spring",
      stiffness: 400,
      damping: 10,
    },
  },
  tap: {
    scale: 0.98,
  },
};

// Section icons mapping
const sectionIcons: Record<string, React.ElementType> = {
  "Basic Information": Shield,
  Organization: Shield,
  "Plan Details": Edit,
  default: Edit,
};

// Section color themes
const sectionThemes: Record<
  string,
  { gradient: string; border: string; bg: string }
> = {
  "Basic Information": {
    gradient: "from-green-500 to-emerald-500",
    border: "border-green-200/50",
    bg: "bg-green-50/30",
  },
  Organization: {
    gradient: "from-purple-500 to-pink-500",
    border: "border-purple-200/50",
    bg: "bg-purple-50/30",
  },
  "Plan Details": {
    gradient: "from-emerald-500 to-teal-500",
    border: "border-emerald-200/50",
    bg: "bg-emerald-50/30",
  },
  default: {
    gradient: "from-gray-500 to-slate-500",
    border: "border-gray-200/50",
    bg: "bg-gray-50/30",
  },
};

// Get grid column class based on field type and context
const getGridClasses = (field: FormField<any>) => {
  // For textarea fields, default to full width
  if (field.type === "textarea") {
    return "col-span-full";
  }

  // Determine column spans with defaults
  const colSpan = field.colSpan || 12;

  // Map to actual Tailwind classes based on your grid system
  const spanMap: Record<number, string> = {
    1: "col-span-1",
    2: "col-span-2",
    3: "col-span-3",
    4: "col-span-4",
    5: "col-span-5",
    6: "col-span-6",
    7: "col-span-7",
    8: "col-span-8",
    9: "col-span-9",
    10: "col-span-10",
    11: "col-span-11",
    12: "col-span-12",
  };

  return spanMap[colSpan] || "col-span-12";
};

export function GenericForm<T extends FieldValues>({
  form,
  fields,
  onSubmit,
  onCancel,
  isLoading = false,
  isSubmitting: externalIsSubmitting,
  submitButtonText = "Submit",
  cancelButtonText = "Cancel",
  successMessage = "Operation completed successfully",
  errorMessage = "An error occurred",
  customButtons,
  resetOnSuccess = false,
  defaultValue,
  title,
  description,
  showProgress = true,
}: GenericFormProps<T> & {
  title?: string;
  description?: string;
  showProgress?: boolean;
}) {
  const [internalIsSubmitting, setInternalIsSubmitting] = useState(false);
  const [progress, setProgress] = useState(0);
  const isSubmitting = externalIsSubmitting ?? internalIsSubmitting;
  const { toast } = useToast();
  const [shouldClearEditor, setShouldClearEditor] = useState(false);

  // Calculate form completion progress
  const calculateProgress = () => {
    const totalFields = fields.filter((field) => !field.hidden).length;
    const filledFields = fields.filter((field) => {
      if (field.hidden) return false;
      const value = form.getValues(field.name as any);
      return value !== undefined && value !== null && value !== "";
    }).length;

    return Math.round((filledFields / totalFields) * 100);
  };



  // Update progress on form changes
  useEffect(() => {
    const subscription = form.watch(() => {
      setProgress(calculateProgress());
    });
    return () => subscription.unsubscribe();
  }, [form, fields]);

  const handleSubmit = async (values: T) => {
    try {
      setInternalIsSubmitting(true);
      await onSubmit(values);
      if (resetOnSuccess) {
        form.reset();
        setProgress(0);
      }
      setShouldClearEditor(true);
    } catch (error: unknown) {
      console.error("Error submitting form:", error);
    } finally {
      setInternalIsSubmitting(false);
    }
  };

  const renderFormField = (
    field: FormField<T>,
    index: number,
    fieldsInSection: FormField<T>[]
  ) => {
    const gridClass = getGridClasses(field);

    return (
      <motion.div
        key={field.name as string}
        initial={{ opacity: 0, y: 10 }}
        animate={{ opacity: 1, y: 0 }}
        transition={{ delay: index * 0.05 }}
        className={gridClass}>
        <FormFieldRenderer
          field={field}
          form={form}
          isLoading={isLoading}
          isSubmitting={isSubmitting}
          defaultValue={defaultValue}
          shouldClearEditor={shouldClearEditor}
          onScroll={field.onScroll}
        />
      </motion.div>
    );
  };

  // Group fields by section
  const sections = fields.reduce((acc, field) => {
    const section = field.section || "default";
    if (!acc[section]) {
      acc[section] = [];
    }
    acc[section].push(field);
    return acc;
  }, {} as Record<string, FormField<T>[]>);

  const hasMultipleSections = Object.keys(sections).length > 1;

  const SectionIcon = ({ sectionName }: { sectionName: string }) => {
    const IconComponent = sectionIcons[sectionName] || sectionIcons.default;
    return <IconComponent className="h-4 w-4" />;
  };

  const renderActionButtons = (className?: string) => (
    <motion.div
      variants={containerVariants}
      initial="hidden"
      animate="visible"
      className={cn(
        "flex flex-col sm:flex-row justify-between items-center gap-4",
        className
      )}>
      <div className="flex items-center space-x-3 text-sm text-muted-foreground"></div>

      <div className="flex flex-col sm:flex-row gap-3 w-full sm:w-auto">
        {customButtons}

        {onCancel && (
          <motion.div variants={buttonVariants}>
            <Button
              type="button"
              variant="outline"
              onClick={onCancel}
              disabled={isLoading || isSubmitting}
              className="min-w-[120px] border-2 hover:border-gray-300 hover:bg-gray-50/80 transition-all duration-200 group">
              <ArrowLeft className="h-4 w-4 mr-2 group-hover:-translate-x-1 transition-transform" />
              {cancelButtonText}
            </Button>
          </motion.div>
        )}

        <motion.div variants={buttonVariants} whileHover="hover" whileTap="tap">
          <Button
            type="submit"
            disabled={isLoading || isSubmitting}
            className="min-w-[140px] bg-gradient-to-r from-green-600 to-emerald-600 hover:from-green-700 hover:to-emerald-700 text-white shadow-lg shadow-green-500/25 hover:shadow-xl hover:shadow-green-500/30 transition-all duration-300">
            {isSubmitting ? (
              <>
                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                Processing...
              </>
            ) : (
              <>
                <Check className="mr-2 h-4 w-4" />
                {submitButtonText}
              </>
            )}
          </Button>
        </motion.div>
      </div>
    </motion.div>
  );

  return (
    <div className="w-full max-w-7xl mx-auto space-y-8">
      {/* Header Section */}
      {(title || description) && (
        <motion.div
          initial={{ opacity: 0, y: -10 }}
          animate={{ opacity: 1, y: 0 }}
          className="text-center space-y-4">
          {title && (
            <h1 className="text-3xl font-bold bg-gradient-to-r from-gray-900 to-gray-700 bg-clip-text text-transparent">
              {title}
            </h1>
          )}
          {description && (
            <p className="text-lg text-muted-foreground max-w-2xl mx-auto leading-relaxed">
              {description}
            </p>
          )}
        </motion.div>
      )}

      {/* Progress Bar */}
      {showProgress && (
        <motion.div
          initial={{ opacity: 0, scaleX: 0 }}
          animate={{ opacity: 1, scaleX: 1 }}
          className="space-y-2">
          <div className="flex justify-between items-center text-sm text-muted-foreground">
            <span>Form Progress</span>
            <span className="font-semibold text-primary">{progress}%</span>
          </div>
          <div className="h-2 bg-gray-200 rounded-full overflow-hidden">
            <motion.div
              className="h-full bg-gradient-to-r from-green-500 to-emerald-500 rounded-full"
              initial={{ width: "0%" }}
              animate={{ width: `${progress}%` }}
              transition={{ duration: 0.8, ease: "easeOut" }}
            />
          </div>
        </motion.div>
      )}

      <form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-8">
        {/* Loading Overlay */}
        {(isLoading || isSubmitting) && (
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            className="fixed inset-0 bg-background/80 backdrop-blur-lg flex items-center justify-center z-50">
            <motion.div
              initial={{ scale: 0.8, opacity: 0 }}
              animate={{ scale: 1, opacity: 1 }}
              className="bg-white/95 p-8 rounded-3xl shadow-2xl border border-gray-200/50 flex flex-col items-center gap-6 max-w-sm w-full mx-4">
              <motion.div
                animate={{ rotate: 360 }}
                transition={{ duration: 1, repeat: Infinity, ease: "linear" }}
                className="w-16 h-16 bg-gradient-to-r from-green-500 to-emerald-500 rounded-full flex items-center justify-center">
                <Loader2 className="h-8 w-8 text-white" />
              </motion.div>
              <div className="text-center space-y-2">
                <h3 className="font-semibold text-lg text-gray-900">
                  Processing...
                </h3>
                <p className="text-sm text-gray-600">
                  Please wait while we save your changes
                </p>
              </div>
            </motion.div>
          </motion.div>
        )}

        {/* Form Sections */}
        <motion.div
          variants={containerVariants}
          initial="hidden"
          animate="visible"
          className="space-y-8">
          {hasMultipleSections ? (
            Object.entries(sections).map(([sectionName, sectionFields]) => {
              const theme = sectionThemes[sectionName] || sectionThemes.default;
              const visibleFields = sectionFields.filter(
                (field) => !field.hidden
              );

              if (visibleFields.length === 0) return null;

              return (
                <motion.div
                  key={sectionName}
                  variants={sectionVariants}
                  whileHover={{ y: -2 }}
                  className="group">
                  <Card
                    className={`border-0 shadow-lg overflow-hidden backdrop-blur-sm bg-white/70 ${theme.bg} transition-all duration-300 group-hover:shadow-xl`}>
                    {sectionName !== "default" && (
                      <CardHeader
                        className={`pb-4 bg-gradient-to-r ${theme.gradient} text-white`}>
                        <div className="flex items-center justify-between">
                          <div className="flex items-center space-x-3">
                            <div className="w-10 h-10 bg-white/20 rounded-xl flex items-center justify-center backdrop-blur-sm">
                              <SectionIcon sectionName={sectionName} />
                            </div>
                            <div>
                              <CardTitle className="text-xl font-bold text-white">
                                {sectionName}
                              </CardTitle>
                              <CardDescription className="text-white/80">
                                {visibleFields.length} field
                                {visibleFields.length !== 1 ? "s" : ""} to
                                complete
                              </CardDescription>
                            </div>
                          </div>
                          <Badge
                            variant="secondary"
                            className="bg-white/20 text-white border-white/30">
                            {sectionName === "default"
                              ? "General"
                              : sectionName}
                          </Badge>
                        </div>
                      </CardHeader>
                    )}
                    <CardContent className="p-6">
                      <div className="grid grid-cols-12 gap-4">
                        {visibleFields.map((field, index) =>
                          renderFormField(field, index, visibleFields)
                        )}
                      </div>
                    </CardContent>
                  </Card>
                </motion.div>
              );
            })
          ) : (
            <motion.div variants={sectionVariants}>
              <Card className="border-0 shadow-xl bg-white/80 backdrop-blur-sm overflow-hidden ring-1 ring-black/5">
                <CardContent className="p-8">
                  <div className="grid grid-cols-12 gap-4">
                    {fields
                      .filter((field) => !field.hidden)
                      .map((field, index) =>
                        renderFormField(
                          field,
                          index,
                          fields.filter((f) => !f.hidden)
                        )
                      )}
                  </div>
                  {/* Action Buttons Inside Card for Single Section */}
                  {renderActionButtons("pt-8 mt-8 border-t border-gray-100")}
                </CardContent>
              </Card>
            </motion.div>
          )}
        </motion.div>

        {/* Action Buttons Outside for Multiple Sections */}
        {hasMultipleSections &&
          renderActionButtons("pt-8 border-t border-gray-200/50")}
      </form>
    </div>
  );
}
