"use client";

import type { Table } from "@tanstack/react-table";
import { Input } from "@workspace/ui/components/input";
import { Combobox } from "@workspace/ui/composed/combobox";
import { useEffect, useState } from "react";

export interface IParams {
  key: string;
  placeholder?: string;
  options?: { label: string; value: string }[];
  type?: "text" | "select" | "date";
}
interface ColumnFilterProps<TData> {
  table: Table<TData>;
  params: IParams[];
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  filters?: any;
}

export function ColumnFilter<TData>({
  table,
  params,
  filters,
}: ColumnFilterProps<TData>) {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const updateFilter = (key: string, value: any) => {
    table.setColumnFilters((prev) => {
      const newFilters = prev.filter((filter) => filter.id !== key);
      if (value) {
        newFilters.push({ id: key, value });
      }
      return newFilters;
    });
  };

  const toDateInput = (d: Date) => {
    const pad = (n: number) => String(n).padStart(2, "0");
    const yyyy = d.getFullYear();
    const MM = pad(d.getMonth() + 1);
    const dd = pad(d.getDate());
    return `${yyyy}-${MM}-${dd}`;
  };

  return (
    <div className="flex gap-2">
      {params.map((param) => {
        if (param.options || param.type === "select") {
          return (
            <Combobox
              className="min-w-32 max-w-48"
              key={param.key}
              onChange={(value) => {
                updateFilter(param.key, value);
              }}
              options={param.options}
              placeholder={param.placeholder || "Choose..."}
              value={filters[param.key] || ""}
            />
          );
        }
        if (param.type === "date") {
          const raw = filters[param.key];
          const inputValue =
            typeof raw === "number"
              ? toDateInput(new Date(raw))
              : typeof raw === "string"
                ? raw
                : "";
          return (
            <Input
              className="block min-w-32"
              key={param.key}
              onChange={(event) => {
                const v = event.target.value;
                updateFilter(param.key, v || "");
              }}
              placeholder={param.placeholder}
              type="date"
              value={inputValue}
            />
          );
        }
        return (
          <DebouncedInput
            externalValue={filters[param.key] || ""}
            key={param.key}
            onSearch={(value) => updateFilter(param.key, value)}
            placeholder={param.placeholder || "Search..."}
          />
        );
      })}
    </div>
  );
}

function DebouncedInput({
  externalValue,
  onSearch,
  placeholder,
}: {
  externalValue: string;
  onSearch: (value: string) => void;
  placeholder: string;
}) {
  const [localValue, setLocalValue] = useState(externalValue);

  // Sync from external (e.g. reset)
  useEffect(() => {
    setLocalValue(externalValue);
  }, [externalValue]);

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setLocalValue(e.target.value);
  };

  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === "Enter") {
      e.preventDefault();
      onSearch(localValue);
    }
  };

  return (
    <Input
      className="min-w-32"
      onChange={handleChange}
      onKeyDown={handleKeyDown}
      placeholder={placeholder}
      value={localValue}
    />
  );
}
