'use client';

import React, { useEffect, useState, useMemo, useCallback } from 'react';
import {
  Dialog,
  DialogTrigger,
  DialogContent,
  DialogTitle,
  DialogDescription,
  DialogClose,
} from '@/components/ui/dialog';
import CommonImage from '@/components/common/CommonImage';
import { Text } from '@/components/ui/text';
import { useForm } from 'react-hook-form';
import { Button } from '@/components/ui/button';
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from '@/components/ui/form';
import { useDispatch, useSelector } from 'react-redux';
import { AppDispatch, RootState, store } from '@/store/store';
import {
  setFilterArguments,
  setIsFilterApplied,
  setIsFilterLoaded,
  triggerFormReset,
} from '@/store/slices/filtersSlice';
import { transformSelectOptions } from '@/utils/transformers';
import { FormFieldRenderer } from '../forms/elements/FormFieldRenderer';
import { FormElement } from '@/types/form-types';
import { FilterSearchInput } from './FilterSearchInput';
import { CommonFilterProps, MixRecord } from '@/types';
import { prepareFormDropdown } from './input-values';
import { formatDate } from '@/utils/decorators';

const CommonFilters = ({
  bucket,
  handlePaginatedRecords,
}: CommonFilterProps) => {
  const dispatch = useDispatch<AppDispatch>();
  const filters = useSelector((state: RootState) => state.filters);
  const [isDialogOpen, setIsDialogOpen] = useState(false);

  interface DropdownOption {
    id: string | number;
    label: string;
    [key: string]: string | number;
  }

  const [dropdownOptionsMap, setDropdownOptionsMap] = useState<
    Record<string, DropdownOption[]>
  >({});

  // Track if dropdowns have been loaded for the current dialog session
  const [dropdownsLoaded, setDropdownsLoaded] = useState(false);

  // ---------- Form Types ----------
  type FieldType<T extends FormElement> = T['element'] extends
    | 'select'
    | 'multi-select'
    ? T['is_multi_select'] extends true
      ? (number | string)[]
      : number | string
    : string;

  type GenerateFormValues<T extends Record<string, FormElement>> = {
    [K in keyof T]: FieldType<T[K]>;
  };

  function generateDefaultValues<T extends Record<string, FormElement>>(
    config: T,
  ) {
    const values = Object.fromEntries(
      Object.entries(config).map(([key, field]) => {
        if (field.element === 'select')
          return [key, field.is_multi_select ? [] : ''];
        return [key, ''];
      }),
    ) as GenerateFormValues<T>;

    return { ...values, search_title: '' };
  }

  // ---------- Memoized Filter Fields ----------
  const bucketFilterFormElements = useMemo(() => {
    const rawFields = bucket.filters?.fields;
    const validFields: Record<string, FormElement> = {};
    if (rawFields && typeof rawFields === 'object') {
      Object.entries(rawFields).forEach(([key, value]) => {
        if (
          value &&
          typeof value === 'object' &&
          'id' in value &&
          'title' in value &&
          'element' in value
        ) {
          validFields[key] = value as FormElement;
        }
      });
    }
    return validFields;
  }, [bucket.filters?.fields]);

  type FilterValues = GenerateFormValues<typeof bucketFilterFormElements>;
  const filterDefaultValues = generateDefaultValues(bucketFilterFormElements);

  const form = useForm<FilterValues>({
    defaultValues: filterDefaultValues,
  });

  interface DateRange {
    from?: Date | string;
    to?: Date | string;
  }

  interface FilterArguments {
    created_on?: DateRange;
    updated_on?: DateRange;
    search_title?: string;
  }

  const normalizeDates = (range?: DateRange): DateRange | undefined => {
    if (!range) return undefined;
    return {
      from:
        range.from instanceof Date
          ? formatDate(range.from.toString(), 'YYYY-MM-DD HH:mm:ss')
          : range.from,
      to:
        range.to instanceof Date
          ? formatDate(range.to.toString(), 'YYYY-MM-DD HH:mm:ss')
          : range.to,
    };
  };

  // ---------- Apply Filters ----------
  const applyFilters = async (data: FilterArguments) => {
    const normalizedData = {
      ...data,
      created_on: data.created_on
        ? normalizeDates(data.created_on)
        : bucket?.default_params?.created_on
          ? normalizeDates(bucket.default_params.created_on as DateRange)
          : null,
      updated_on: data.updated_on
        ? normalizeDates(data.updated_on)
        : bucket?.default_params?.updated_on
          ? normalizeDates(bucket.default_params.updated_on as DateRange)
          : null,
    };

    const filterArgs = bucket?.default_params
      ? { ...bucket.default_params, ...normalizedData }
      : normalizedData;

    dispatch(setFilterArguments(filterArgs));
    dispatch(setIsFilterApplied(true));

    handlePaginatedRecords(1, {
      ...(filterArgs || {}),
      per_page: store.getState().tableSettings.record_per_page,
    });

    setIsDialogOpen(false);
  };

  const handleFilters = async () => {
    setIsDialogOpen(true);
    const storedFilters = store.getState().filters;
    if (storedFilters.is_loaded) return;
    dispatch(setFilterArguments(bucket?.default_params || null));
    dispatch(setIsFilterLoaded(true));
  };

  // ---------- Load Dropdowns ----------
  const loadAllDropdowns = useCallback(async () => {
    // Reset dropdownsLoaded flag when starting to load
    setDropdownsLoaded(false);

    const dropdownPromises = [];

    for (const el of Object.values(bucketFilterFormElements)) {
      if (el.options_id) {
        dropdownPromises.push(
          prepareFormDropdown(
            el.options_id,
            bucket?.default_params as MixRecord,
          )
            .then((data) => {
              if (Array.isArray(data) && data.length > 0) {
                return {
                  key: el.id,
                  options: transformSelectOptions(
                    data as MixRecord[],
                  ) as DropdownOption[],
                };
              }
              return null;
            })
            .catch((err) => {
              console.error(`Failed to load dropdown for ${el.id}`, err);
              return null;
            }),
        );
      }
    }

    try {
      const results = await Promise.all(dropdownPromises);

      const newOptionsMap: Record<string, DropdownOption[]> = {};
      results.forEach((result) => {
        if (result) {
          newOptionsMap[result.key] = result.options;
        }
      });

      setDropdownOptionsMap(newOptionsMap);
      setDropdownsLoaded(true);
    } catch (err) {
      console.error('Failed to load dropdowns', err);
      setDropdownsLoaded(true); // Still set to true to prevent endless loading
    }
  }, [bucketFilterFormElements, bucket?.default_params]);

  // Load dropdowns when dialog opens
  useEffect(() => {
    if (isDialogOpen && !dropdownsLoaded) {
      loadAllDropdowns();
    }
  }, [isDialogOpen, dropdownsLoaded, loadAllDropdowns]);

  // Reset dropdownsLoaded when dialog closes
  useEffect(() => {
    if (!isDialogOpen) {
      setDropdownsLoaded(false);
    }
  }, [isDialogOpen]);

  // ---------- Reset Form ----------
  const shouldResetForm = useSelector(
    (state: RootState) => state.filters.shouldResetForm,
  );
  useEffect(() => {
    if (shouldResetForm) {
      form.reset(filterDefaultValues);
      dispatch(triggerFormReset(false));
    }
  }, [shouldResetForm, form, dispatch, filterDefaultValues]);

  // ---------- Type Guard ----------
  function isFormElement(value: unknown): value is FormElement {
    return (
      typeof value === 'object' &&
      value !== null &&
      'id' in value &&
      'title' in value &&
      'element' in value
    );
  }

  return (
    <Dialog open={isDialogOpen}>
      <DialogTrigger
        asChild
        onClick={() => {
          handleFilters();
        }}
      >
        <Text
          className="filter-icn wo-fts-filter-bts flex items-start"
          title="Filters"
        >
          <CommonImage
            src="/main/filter-icn.webp"
            width={20}
            height={20}
            alt="Filters"
            classname="setting-icon"
          />
        </Text>
      </DialogTrigger>
      <DialogContent className="modal-common-widget w-full max-w-7xl p-0 m-0 filter-modal-widget table-modal-settings state-widget">
        <DialogTitle className="p-5 modal-header">
          Filters → {bucket.heading}
        </DialogTitle>
        <DialogDescription>{''}</DialogDescription>
        <DialogClose asChild>
          <button
            onClick={() => setIsDialogOpen(false)}
            className="dialog-close absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none z-[9]"
            aria-label="Close"
          >
            <CommonImage
              src="/main/cross-arrow.webp"
              width={15}
              height={15}
              alt="Close"
              classname="dialog-close-img"
            />
          </button>
        </DialogClose>

        <Form {...form}>
          <form
            onSubmit={form.handleSubmit(applyFilters)}
            className="space-y-6"
          >
            <Text className="main-scroll-widget">
              {bucket.filters?.search_bar &&
                isFormElement(bucket.filters.search_bar) && (
                  <FilterSearchInput
                    element={bucket.filters.search_bar}
                    name={bucket.filters.search_bar.id} // required
                    control={form.control}
                  />
                )}

              <Text className="flex flex-wrap p-2 form-mid mt-0">
                {Object.entries(bucketFilterFormElements).map(
                  ([key, element]) => (
                    <FormField
                      key={key}
                      control={form.control}
                      name={element.id}
                      render={({ field }) => {
                        const formElement =
                          element.element === 'multi-select'
                            ? {
                                ...element,
                                element: 'select' as const,
                                is_multi_select: true,
                              }
                            : {
                                ...element,
                                element: element.element as
                                  | 'input'
                                  | 'select'
                                  | 'date',
                              };

                        // Determine defaultValues type for FormFieldRenderer
                        const rawValue = filters?.arguments?.[formElement.id];
                        const defaultValues = Array.isArray(rawValue)
                          ? rawValue
                          : rawValue && typeof rawValue === 'object'
                            ? (rawValue as Record<string, unknown>)
                            : undefined;

                        return (
                          <FormItem className="w-1/4 p-2">
                            <FormLabel className="no-error-styles font-bold">
                              {element.title}
                            </FormLabel>
                            <FormControl>
                              <FormFieldRenderer
                                form={form}
                                element={formElement}
                                field={field}
                                dropdownOptions={dropdownOptionsMap[element.id]}
                                defaultValues={defaultValues}
                              />
                            </FormControl>
                            <FormMessage />
                          </FormItem>
                        );
                      }}
                    />
                  ),
                )}
              </Text>
            </Text>

            <Text className="modal-footer flex justify-end items-end gap-2 m-0 pr-4 p-2">
              <Button
                type="button"
                className={`m-0 refresh-btn bg-transparent shadow ${store.getState().filters.is_applied ? 'refresh-icon-active' : 'primary-button-refresh'}`}
                onClick={() => {
                  form.reset();
                  dispatch(setFilterArguments(null));
                  dispatch(setIsFilterApplied(false));
                  handlePaginatedRecords(1, {});
                  setIsDialogOpen(false);
                  // Reset dropdowns when clearing filters
                  setDropdownsLoaded(false);
                }}
              >
                <CommonImage
                  src="/main/refresh-icn.webp"
                  width={15}
                  height={15}
                  alt="refresh"
                  classname="refresh-icon"
                />
              </Button>

              <Button
                type="submit"
                className="m-0 filter-search-btn tracking-wider w-40 primary-button"
                disabled={!dropdownsLoaded} // Optionally disable button while loading
              >
                {dropdownsLoaded ? 'Search' : 'Loading...'}
              </Button>
            </Text>
          </form>
        </Form>
      </DialogContent>
    </Dialog>
  );
};

export default CommonFilters;
