"use client";

import * as React from "react";

import {
  type Header,
} from "@tanstack/react-table";

import {
  DataTableHeaderActions,
  DataTablePagination,
  DataTableShell,
  downloadCsv,
  matchesText,
  useDashboardTable,
} from "@/app/dashboard/_components/data-table";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { TableCell } from "@/components/ui/table";

import { userColumns } from "./columns";
import {
  USER_GROUP_OPTIONS,
  USER_STATUS_OPTIONS,
  emptyUserFilters,
  type UserFilters,
  type UserRow,
} from "./schema";

function filterRows(rows: UserRow[], filters: UserFilters) {
  return rows.filter((row) => {
    if (filters.status !== "all" && row.status !== filters.status) return false;
    if (filters.group !== "all" && row.group !== filters.group) return false;
    if (!matchesText(row.firstName, filters.firstName)) return false;
    if (!matchesText(row.lastName, filters.lastName)) return false;
    if (!matchesText(row.email, filters.email)) return false;
    return true;
  });
}

function exportUsers(rows: UserRow[]) {
  downloadCsv({
    filename: "users-data",
    headers: ["ID", "First Name", "Last Name", "Email", "Group", "Status", "Date Added", "Last Updated"],
    rows,
    toRow: (row) => [
      row.id,
      row.firstName,
      row.lastName,
      row.email,
      row.groupLabel,
      row.statusLabel,
      row.dateAdded,
      row.lastUpdated,
    ],
  });
}

export function UsersTable({ data }: { data: UserRow[] }) {
  const [toolbarStatus, setToolbarStatus] = React.useState("all");
  const [toolbarGroup, setToolbarGroup] = React.useState("all");
  const { filters, setFilters, resetPage, filteredData, table, updateFilter } =
    useDashboardTable<UserRow, UserFilters>({
      data,
      columns: userColumns,
      initialFilters: emptyUserFilters,
      filterRows,
      getRowId: (row) => String(row.id),
    });

  const applyToolbarSearch = () => {
    setFilters((prev) => ({ ...prev, status: toolbarStatus, group: toolbarGroup }));
    resetPage();
  };

  return (
    <div className="space-y-4">
      <div className="flex flex-col gap-3 lg:flex-row lg:items-end lg:justify-between">
        <div className="flex flex-wrap items-end gap-2">
          <div className="space-y-1">
            <Label htmlFor="users-toolbar-group" className="text-xs">
              Group
            </Label>
            <Select value={toolbarGroup} onValueChange={setToolbarGroup}>
              <SelectTrigger id="users-toolbar-group" className="h-9 w-[180px]">
                <SelectValue placeholder="Group" />
              </SelectTrigger>
              <SelectContent>
                <SelectGroup>
                  {USER_GROUP_OPTIONS.map((option) => (
                    <SelectItem key={option.value} value={option.value}>
                      {option.label}
                    </SelectItem>
                  ))}
                </SelectGroup>
              </SelectContent>
            </Select>
          </div>
          <div className="space-y-1">
            <Label htmlFor="users-toolbar-status" className="text-xs">
              Status
            </Label>
            <Select value={toolbarStatus} onValueChange={setToolbarStatus}>
              <SelectTrigger id="users-toolbar-status" className="h-9 w-[180px]">
                <SelectValue placeholder="Status" />
              </SelectTrigger>
              <SelectContent>
                <SelectGroup>
                  {USER_STATUS_OPTIONS.map((option) => (
                    <SelectItem key={option.value} value={option.value}>
                      {option.label}
                    </SelectItem>
                  ))}
                </SelectGroup>
              </SelectContent>
            </Select>
          </div>
          <Button type="button" className="h-9" onClick={applyToolbarSearch}>
            Search
          </Button>
        </div>
      </div>

      <DataTableShell
        table={table}
        columnCount={userColumns.length}
        emptyMessage="No users match your filters."
        renderFilterCell={(header) => renderFilterCell(header, filters, updateFilter)}
      />

      <DataTablePagination
        table={table}
        totalRows={filteredData.length}
        itemNoun="user"
        idPrefix="users"
      />
    </div>
  );
}

function renderFilterCell(
  header: Header<UserRow, unknown>,
  filters: UserFilters,
  updateFilter: <K extends keyof UserFilters>(key: K, value: UserFilters[K]) => void,
) {
  const id = header.id;
  const columnId = header.column.id;

  if (columnId === "options" || columnId === "dateAdded" || columnId === "lastUpdated") {
    return null;
  }

  if (columnId === "firstName") {
    return (
      <TableCell key={id} className="p-2">
        <Input
          value={filters.firstName}
          onChange={(event) => updateFilter("firstName", event.target.value)}
          placeholder="First name"
          className="h-8 bg-background text-xs"
        />
      </TableCell>
    );
  }

  if (columnId === "lastName") {
    return (
      <TableCell key={id} className="p-2">
        <Input
          value={filters.lastName}
          onChange={(event) => updateFilter("lastName", event.target.value)}
          placeholder="Last name"
          className="h-8 bg-background text-xs"
        />
      </TableCell>
    );
  }

  if (columnId === "email") {
    return (
      <TableCell key={id} className="p-2">
        <Input
          value={filters.email}
          onChange={(event) => updateFilter("email", event.target.value)}
          placeholder="Email"
          className="h-8 bg-background text-xs"
        />
      </TableCell>
    );
  }

  if (columnId === "group") {
    return (
      <TableCell key={id} className="p-2">
        <Select value={filters.group} onValueChange={(value) => updateFilter("group", value)}>
          <SelectTrigger className="h-8 bg-background text-xs">
            <SelectValue placeholder="Group" />
          </SelectTrigger>
          <SelectContent>
            {USER_GROUP_OPTIONS.map((option) => (
              <SelectItem key={option.value} value={option.value}>
                {option.label}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      </TableCell>
    );
  }

  if (columnId === "status") {
    return (
      <TableCell key={id} className="p-2">
        <Select value={filters.status} onValueChange={(value) => updateFilter("status", value)}>
          <SelectTrigger className="h-8 bg-background text-xs">
            <SelectValue placeholder="Status" />
          </SelectTrigger>
          <SelectContent>
            {USER_STATUS_OPTIONS.map((option) => (
              <SelectItem key={option.value} value={option.value}>
                {option.label}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      </TableCell>
    );
  }

  return null;
}

export function UsersHeaderActions({ data }: { data: UserRow[] }) {
  return (
    <DataTableHeaderActions
      createHref="/dashboard/admins/users/create"
      onExport={() => exportUsers(data)}
    />
  );
}
