"use client";

import { useMemo } from "react";

import { Checkbox } from "@/components/ui/checkbox";
import { cn } from "@/lib/utils";

import {
  MODULE_GROUPS,
  PARENT_TO_SALE,
  type ModuleGroup,
  type ModuleUsageMap,
} from "../constants";

type AvailableModule = ModuleGroup & { partialOwners: string[] };

type Props = {
  id?: string;
  value: string[];
  onChange: (value: string[]) => void;
  className?: string;
  /** Fully claimed (empty-refine) modules — blocked. */
  moduleFullClaims?: ModuleUsageMap;
  /** Partially claimed (type-refine) modules — still selectable. */
  modulePartialClaims?: ModuleUsageMap;
};

function uniqueCodes(codes: string[]): string[] {
  return [...new Set(codes)];
}

function uniqueNames(names: string[]): string[] {
  return names.filter((name, index, all) => all.indexOf(name) === index);
}

export function ModuleMultiSelect({
  id,
  value,
  onChange,
  className,
  moduleFullClaims = {},
  modulePartialClaims = {},
}: Props) {
  const isFullyTaken = (code: string) => (moduleFullClaims[code]?.length ?? 0) > 0;

  const toggle = (parentCode: string, checked: boolean) => {
    const saleCode = PARENT_TO_SALE[parentCode];

    if (checked) {
      if (isFullyTaken(parentCode) || (saleCode && isFullyTaken(saleCode))) return;
      const next = [...value, parentCode];
      if (saleCode) next.push(saleCode);
      onChange(uniqueCodes(next));
      return;
    }

    onChange(value.filter((item) => item !== parentCode && item !== saleCode));
  };

  const { available, fullyTaken } = useMemo(() => {
    const availableItems: AvailableModule[] = [];
    const takenItems: Array<{ parent: ModuleGroup["parent"]; usedBy: string[] }> = [];

    for (const group of MODULE_GROUPS) {
      const { parent, sale } = group;
      const checked = value.includes(parent.value);
      const fullOwners = uniqueNames([
        ...(moduleFullClaims[parent.value] ?? []),
        ...(sale ? (moduleFullClaims[sale.value] ?? []) : []),
      ]);
      const partialOwners = uniqueNames([
        ...(modulePartialClaims[parent.value] ?? []),
        ...(sale ? (modulePartialClaims[sale.value] ?? []) : []),
      ]);

      if (!checked && fullOwners.length > 0) {
        takenItems.push({ parent, usedBy: fullOwners });
      } else {
        availableItems.push({ ...group, partialOwners });
      }
    }

    return { available: availableItems, fullyTaken: takenItems };
  }, [moduleFullClaims, modulePartialClaims, value]);

  return (
    <div id={id} className={cn("space-y-3", className)}>
      <div className="overflow-hidden rounded-lg border bg-card">
        <div className="bg-muted/40 px-2.5 py-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">
          Available ({available.length})
        </div>
        <div className="grid max-h-48 overflow-y-auto sm:grid-cols-2 lg:grid-cols-3">
          {available.map(({ parent, partialOwners }) => {
            const checked = value.includes(parent.value);
            const fieldId = `${id ?? "modules"}-${parent.value}`;

            return (
              <label
                key={parent.value}
                htmlFor={fieldId}
                className={cn(
                  "flex cursor-pointer items-start gap-2 border-b border-border/40 px-2.5 py-1.5 text-sm",
                  checked ? "bg-primary/5" : "hover:bg-muted/40",
                )}
              >
                <Checkbox
                  id={fieldId}
                  checked={checked}
                  className="mt-0.5"
                  onCheckedChange={(next) => toggle(parent.value, next === true)}
                />
                <span className="min-w-0 leading-snug">
                  <span className="block">{parent.label}</span>
                  {partialOwners.length > 0 ? (
                    <span className="mt-0.5 block text-[11px] text-sky-700 dark:text-sky-400">
                      Types split with {partialOwners.join(", ")}
                    </span>
                  ) : null}
                </span>
              </label>
            );
          })}
          {available.length === 0 ? (
            <p className="col-span-full px-3 py-3 text-muted-foreground text-sm">
              All modules are fully claimed by other macros.
            </p>
          ) : null}
        </div>
      </div>

      {fullyTaken.length > 0 ? (
        <details className="group overflow-hidden rounded-lg border bg-muted/10">
          <summary className="cursor-pointer list-none px-3 py-2 text-muted-foreground text-xs [&::-webkit-details-marker]:hidden">
            <span className="inline-flex items-center gap-2">
              <span className="font-semibold uppercase tracking-wide">
                Fully claimed ({fullyTaken.length})
              </span>
              <span className="text-[11px] opacity-70 group-open:hidden">Show</span>
              <span className="hidden text-[11px] opacity-70 group-open:inline">Hide</span>
            </span>
          </summary>
          <div className="grid max-h-36 overflow-y-auto border-t sm:grid-cols-2 lg:grid-cols-3">
            {fullyTaken.map(({ parent, usedBy }) => (
              <div
                key={parent.value}
                className="flex items-start gap-2 border-b border-border/40 px-3 py-2 text-sm opacity-70"
              >
                <Checkbox checked={false} disabled className="mt-0.5" />
                <span className="min-w-0 leading-snug">
                  <span className="block text-muted-foreground">{parent.label}</span>
                  <span className="mt-0.5 block text-[11px] text-amber-700/90 dark:text-amber-400/90">
                    {usedBy.join(", ")}
                  </span>
                </span>
              </div>
            ))}
          </div>
        </details>
      ) : null}
    </div>
  );
}
