"use client";

import { Avatar, Select, Space, Tag, Typography } from "antd";
import { useEffect, useMemo, useState } from "react";

import { fetchEmployees, type Employee } from "@/lib/api/employees";
import { searchEmployees } from "@/lib/api/department";
import { getPickerReadsBlockedMessage, isPickerReadsBlockedError } from "@/lib/api/errors";
import { useAuth } from "@/lib/hooks/use-auth";

const { Text } = Typography;

export interface EmployeeDropdownProps {
  value?: number | number[];
  onChange?: (value: number | number[] | undefined) => void;
  onEmployeeChange?: (employee: Employee | Employee[] | null) => void;
  mode?: "single" | "multiple";
  placeholder?: string;
  disabled?: boolean;
  allowClear?: boolean;
  filterDepartment?: string;
  id?: string;
  "aria-label"?: string;
  "aria-labelledby"?: string;
  "aria-describedby"?: string;
}

function useDebouncedValue<T>(value: T, delay: number) {
  const [debounced, setDebounced] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => setDebounced(value), delay);
    return () => clearTimeout(timer);
  }, [value, delay]);

  return debounced;
}

export default function EmployeeDropdown({
  value,
  onChange,
  onEmployeeChange,
  mode = "single",
  placeholder = "Select employee",
  disabled = false,
  allowClear = true,
  filterDepartment,
  id,
  "aria-label": ariaLabel,
  "aria-labelledby": ariaLabelledBy,
  "aria-describedby": ariaDescribedBy,
}: EmployeeDropdownProps) {
  const { user } = useAuth();
  const [employees, setEmployees] = useState<Employee[]>([]);
  const [loading, setLoading] = useState(false);
  const [searchValue, setSearchValue] = useState("");
  const [error, setError] = useState<string | null>(null);

  const debouncedSearch = useDebouncedValue(searchValue, 300);

  useEffect(() => {
    let cancelled = false;

    const loadEmployees = async () => {
      setLoading(true);
      setError(null);
      try {
        const data = debouncedSearch ? await searchEmployees(debouncedSearch) : await fetchEmployees();
        if (!cancelled) {
          setEmployees(data ?? []);
        }
      } catch (err) {
        if (!cancelled) {
          setEmployees([]);
          setError(isPickerReadsBlockedError(err) ? getPickerReadsBlockedMessage() : "Failed to load employees");
        }
      } finally {
        if (!cancelled) {
          setLoading(false);
        }
      }
    };

    loadEmployees();
    return () => {
      cancelled = true;
    };
  }, [debouncedSearch]);

  const filteredEmployees = useMemo(() => {
    if (!filterDepartment) {
      return employees;
    }
    return employees.filter((emp) => {
      if (emp.department_id === filterDepartment) {
        return true;
      }
      return false;
    });
  }, [employees, filterDepartment]);

  const options = useMemo(
    () =>
      filteredEmployees.map((emp) => {
        const isCurrentUser = user?.email && emp.email && emp.email.toLowerCase() === user.email.toLowerCase();
        const primaryLabel = emp.name && emp.email ? `${emp.name} · ${emp.email}` : emp.name || emp.email || "";
        return {
          label: primaryLabel,
          value: emp.id,
          data: {
            employee: emp,
            avatarUrl: emp.avatar_url,
            isCurrentUser,
            department: emp.department_name,
          },
        };
      }),
    [filteredEmployees, user?.email],
  );

  const selectMode = mode === "multiple" ? "multiple" : undefined;
  const notFoundContent = loading ? "Loading..." : error ?? "No employees";
  const employeeById = useMemo(
    () => new Map(filteredEmployees.map((emp) => [emp.id, emp])),
    [filteredEmployees],
  );

  const handleChange = (nextValue: number | number[] | undefined) => {
    onChange?.(nextValue);

    if (!onEmployeeChange) {
      return;
    }

    if (Array.isArray(nextValue)) {
      const selectedEmployees = nextValue
        .map((employeeId) => employeeById.get(employeeId))
        .filter((employee): employee is Employee => Boolean(employee));
      onEmployeeChange(selectedEmployees.length > 0 ? selectedEmployees : null);
      return;
    }

    onEmployeeChange(
      typeof nextValue === "number" ? employeeById.get(nextValue) ?? null : null,
    );
  };

  return (
    <Select
      showSearch
      allowClear={allowClear}
      mode={selectMode}
      placeholder={placeholder}
      value={value as number | number[] | undefined}
      onChange={handleChange}
      options={options}
      disabled={disabled}
      loading={loading}
      onSearch={setSearchValue}
      filterOption={false}
      notFoundContent={notFoundContent}
      dropdownStyle={{ minWidth: 360 }}
      dropdownMatchSelectWidth={false}
      id={id}
      aria-label={ariaLabel}
      aria-labelledby={ariaLabelledBy}
      aria-describedby={ariaDescribedBy}
      optionRender={(option) => {
        const data = option.data as
          | { employee?: Employee; avatarUrl?: string; isCurrentUser?: boolean; department?: string }
          | undefined;
        return (
          <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
            <Avatar size="small" src={data?.avatarUrl} />
            <div style={{ display: "flex", flexDirection: "column", maxWidth: 320 }}>
              <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
                <Text ellipsis style={{ maxWidth: 240 }}>
                  {option.label}
                </Text>
                {data?.isCurrentUser ? <Tag color="blue">You</Tag> : null}
              </div>
              {data?.department ? (
                <Text
                  type="secondary"
                  style={{ fontSize: 12, whiteSpace: "normal", wordBreak: "break-word", maxWidth: 320 }}
                >
                  {data.department}
                </Text>
              ) : null}
            </div>
          </div>
        );
      }}
    />
  );
}
