"use client";

import LabItem, { LabItemPlaceholder } from "@/components/lab-item";
import { useLabs } from "@/components/labs/hook";
import type { LabMetaV2, TiDBEnvironment } from "@/components/labs/hooks-v2";
import { useMe } from "@/components/me-context";
import { Input } from "@/components/ui/input";
import { useLocaleFunction } from "@/hooks/use-localed";
import { isTrustedUser } from "@/lib/users";
import { Search } from "lucide-react";
import { useSearchParams } from "next/navigation";
import { levelIndexFromLabel } from "@/components/labs/lab-level";
import { type ReactNode, useMemo, useState } from "react";

export function LabsLabsList({
  drawerTrigger,
  initialLabs,
}: {
  drawerTrigger?: ReactNode;
  initialLabs?: LabMetaV2[];
}) {
  const usp = useSearchParams();
  const category = usp.get("category");
  const product = usp.get("product") as TiDBEnvironment | null;
  const target = usp.get("target");
  const deliveryType = usp.get("delivery_type");
  const levelMinParam = usp.get("level_min");
  const levelMaxParam = usp.get("level_max");
  const levelMin = levelMinParam != null ? Math.max(0, Math.min(2, parseInt(levelMinParam))) : null;
  const levelMax = levelMaxParam != null ? Math.max(0, Math.min(2, parseInt(levelMaxParam))) : null;

  const { data, isLoading } = useLabs(initialLabs);
  const { data: me } = useMe();

  const trusted = isTrustedUser(me);

  const [searchValue, setSearchValue] = useState("");

  const list = useMemo(() => {
    const conditions: Array<(lab: LabMetaV2) => boolean> = [];

    if (category) {
      conditions.push((lab) =>
        [lab.category_en, lab.category_zh, lab.category_ja]
          .flatMap((categories) => categories)
          .includes(category)
      );
    }

    if (product) {
      conditions.push((lab) => lab.tidb_environments.includes(product));
    }

    if (target) {
      conditions.push((lab) => lab.target_audience.includes(target as never));
    }

    if (deliveryType) {
      conditions.push((lab) => lab.delivery_type === deliveryType);
    }

    if (levelMin != null || levelMax != null) {
      const min = levelMin ?? 0;
      const max = levelMax ?? 2;
      conditions.push((lab) => {
        const idx = levelIndexFromLabel(lab.lab_level);
        if (idx == null) return false; // hide labs without level when filter active
        return idx >= min && idx <= max;
      });
    }

    if (!trusted) {
      conditions.push((lab) => !lab.employee_only);
    }

    if (searchValue.trim()) {
      const k = searchValue.trim().toLocaleLowerCase();
      conditions.push((lab) =>
        [
          lab.lab_code,
          lab.title_ja,
          lab.title_zh,
          lab.title_en,
          lab.description_ja,
          lab.description_zh,
          lab.description_en,
        ]
          .concat(lab.keywords_ja ?? [])
          .concat(lab.keywords_zh ?? [])
          .concat(lab.keywords_en ?? [])
          .some((v) => v?.toLocaleLowerCase().includes(k))
      );
    }

    if (data && conditions) {
      return data.filter((item) =>
        conditions.every((condition) => condition(item))
      );
    }
    return data;
  }, [
    data,
    trusted,
    category,
    product,
    target,
    deliveryType,
    searchValue,
    levelMin,
    levelMax,
  ]);

  return (
    <div>
      <div className="px-4 md:px-8 py-6 pb-0 flex md:block items-center justify-between gap-2 w-full">
        {drawerTrigger}
        <SearchInput
          disabled={!list}
          value={searchValue}
          onChange={setSearchValue}
        />
      </div>
      <div className="grid md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4  gap-8 px-4 md:px-8 py-6 max-w-[1600px]">
        {isLoading && (
          <>
            <LabItemPlaceholder />
            <LabItemPlaceholder />
            <LabItemPlaceholder />
          </>
        )}
        {list?.map((lab) => (
          <LabItem key={lab.lab_code} lab={lab} usage />
        ))}
      </div>
    </div>
  );
}

function SearchInput({
  disabled,
  value,
  onChange,
}: {
  disabled: boolean;
  value: string;
  onChange: (value: string) => void;
}) {
  const t = useLocaleFunction();

  return (
    <div className="relative w-full lg:w-side">
      <Input
        className="peer ps-9"
        disabled={disabled}
        placeholder={t("labs.search")}
        type="search"
        value={value}
        onChange={(event) => onChange(event.target.value)}
      />
      <div className="pointer-events-none absolute inset-y-0 start-0 flex items-center justify-center ps-3 text-muted-foreground/80 peer-disabled:opacity-50">
        <Search size={16} strokeWidth={2} />
      </div>
    </div>
  );
}
