"use client";

import { useMemo, useState } from "react";

import Badge from "@mui/material/Badge";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import Popover from "@mui/material/Popover";
import Typography from "@mui/material/Typography";
import { alpha, useTheme } from "@mui/material/styles";

import { dashboardAssets } from "@/components/dashboard/dashboard-assets";
import { DashboardAssetIcon } from "@/components/dashboard/dashboard-asset-icon";
import { useAppLanguage } from "@/components/providers/app-language-provider";
import { Dropdown, type DropdownOption } from "@/components/ui/dropdown";
import { filterIcon as FilterIcon } from "@/components/ui/icon";

const FILTER_PANEL_TEXT = {
  en: {
    filter: "Filter",
    apply: "Apply Filter",
    clearAll: "Clear all",
  },
  kh: {
    filter: "តម្រង",
    apply: "អនុវត្តតម្រង",
    clearAll: "សម្អាតទាំងអស់",
  },
};

type FilterPanelText = (typeof FILTER_PANEL_TEXT)["en"];

function getFilterPanelText(language: string | undefined) {
  const lang = language === "kh" || language === "km" ? "kh" : "en";
  return FILTER_PANEL_TEXT[lang];
}

// One filter inside the panel. The screen keeps owning the options and the
// applied value; the panel only edits a copy until the user presses Apply.
export type FilterPanelField = {
  key: string;
  label: string;
  options: DropdownOption[];
  value: string[];
  multiple?: boolean;
  showCheckbox?: boolean;
};

export type FilterPanelValues = Record<string, string[]>;

type FilterPanelProps = {
  fields: FilterPanelField[];
  /** Called with every filter at once when the user presses Apply. */
  onApply: (values: FilterPanelValues) => void;
  /** Overrides the built-in wording. */
  labels?: FilterPanelText;
};

function toDraft(fields: FilterPanelField[]): FilterPanelValues {
  const draft: FilterPanelValues = {};

  for (const field of fields) {
    draft[field.key] = [...field.value];
  }

  return draft;
}

function countUsedFilters(values: FilterPanelValues) {
  return Object.values(values).filter((selected) => selected.length > 0).length;
}

export function FilterPanel({ fields, onApply, labels }: FilterPanelProps) {
  const theme = useTheme();
  const { language } = useAppLanguage();
  const text = labels ?? getFilterPanelText(language);
  const isDark = theme.palette.mode === "dark";

  const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
  // What the user is editing. Filled from the applied values each time the
  // panel opens, so closing without applying throws the edits away.
  const [draft, setDraft] = useState<FilterPanelValues>(() => toDraft(fields));

  const appliedCount = useMemo(
    () => countUsedFilters(toDraft(fields)),
    [fields],
  );

  const open = Boolean(anchorEl);

  function handleOpen(event: React.MouseEvent<HTMLElement>) {
    setDraft(toDraft(fields));
    setAnchorEl(event.currentTarget);
  }

  function handleClose() {
    setAnchorEl(null);
  }

  function handleApply() {
    onApply(draft);
    setAnchorEl(null);
  }

  function handleClearAll() {
    const empty: FilterPanelValues = {};

    for (const field of fields) {
      empty[field.key] = [];
    }

    setDraft(empty);
  }

  return (
    <>
      <Badge
        badgeContent={appliedCount}
        color="primary"
        overlap="rectangular"
        sx={{ "& .MuiBadge-badge": { fontSize: 11, fontWeight: 700 } }}
      >
        <Button
          variant="outlined"
          onClick={handleOpen}
          startIcon={<FilterIcon sx={{ fontSize: 16 }} />}
          endIcon={
            <DashboardAssetIcon
              src={dashboardAssets.chevronDownBlue}
              width={7.5}
              height={4.5}
              sx={{
                transform: open ? "rotate(180deg)" : "rotate(0deg)",
                transition: "transform 0.2s ease",
              }}
            />
          }
          sx={{
            height: 40,
            px: 1.5,
            minWidth: "auto",
            flexShrink: 0,
            whiteSpace: "nowrap",
            borderColor: isDark ? alpha("#ffffff", 0.25) : "#1a64a8",
            color: isDark ? "#ffffff" : "#1a64a8",
            bgcolor: isDark ? alpha("#ffffff", 0.04) : "transparent",
            fontSize: 13,
            fontWeight: 500,
            lineHeight: 1,
            textTransform: "none",
            borderRadius: "6px",
            boxShadow: "none",
            "& .MuiButton-startIcon": {
              mr: 1,
            },
            "& .MuiButton-endIcon": {
              ml: 1,
            },
            "&:hover": {
              borderColor: isDark ? alpha("#ffffff", 0.45) : "#15548e",
              bgcolor: isDark
                ? alpha("#ffffff", 0.08)
                : alpha("#1a64a8", 0.04),
              boxShadow: "none",
            },
          }}
        >
          {text.filter}
        </Button>
      </Badge>

      <Popover
        open={open}
        anchorEl={anchorEl}
        onClose={handleClose}
        anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
        transformOrigin={{ vertical: "top", horizontal: "left" }}
        slotProps={{
          paper: {
            sx: {
              mt: 1,
              width: { xs: "calc(100vw - 32px)", sm: 640, lg: 860 },
              maxWidth: "calc(100vw - 32px)",
              borderRadius: "12px",
              // A shade above the fields inside, so each dropdown reads as a
              // control sitting on the panel instead of blending into it.
              backgroundColor: isDark ? "#1e293b" : "#ffffff",
              backgroundImage: "none",
              border: `1px solid ${
                isDark ? alpha("#ffffff", 0.1) : "#e9eaeb"
              }`,
              boxShadow: isDark
                ? "0 12px 32px rgba(0,0,0,0.5)"
                : "0 12px 32px rgba(10,13,18,0.12)",
            },
          },
        }}
      >
        <Box
          sx={{
            px: 2.5,
            py: 2,
            display: "grid",
            gridTemplateColumns: {
              xs: "1fr",
              sm: "repeat(2, minmax(0, 1fr))",
              lg: "repeat(3, minmax(0, 1fr))",
            },
            columnGap: 2,
            rowGap: 1.75,
            maxHeight: "min(60vh, 460px)",
            overflowY: "auto",
          }}
        >
          {fields.map((field) => (
            <Box key={field.key} sx={{ minWidth: 0 }}>
              <Typography
                sx={{
                  mb: 0.75,
                  fontSize: 12,
                  fontWeight: 600,
                  color: theme.palette.text.secondary,
                }}
              >
                {field.label}
              </Typography>

              <Dropdown
                label={field.label}
                options={field.options}
                value={draft[field.key] ?? []}
                multiple={field.multiple ?? true}
                showCheckbox={field.showCheckbox ?? true}
                displayMode="count"
                width="100%"
                onChange={(value) =>
                  setDraft((current) => ({
                    ...current,
                    [field.key]: Array.isArray(value) ? value : [value],
                  }))
                }
              />
            </Box>
          ))}
        </Box>

        <Box
          sx={{
            px: 2.5,
            py: 1.5,
            display: "flex",
            justifyContent: "space-between",
            gap: 1.5,
            borderTop: `1px solid ${isDark ? alpha("#ffffff", 0.1) : "#f0f0f0"}`,
            backgroundColor: isDark
              ? alpha("#ffffff", 0.03)
              : alpha("#000000", 0.015),
          }}
        >
          <Button
            onClick={handleClearAll}
            sx={{
              textTransform: "none",
              fontSize: 13,
              fontWeight: 600,
              color: theme.palette.text.secondary,
            }}
          >
            {text.clearAll}
          </Button>

          <Button
            variant="contained"
            onClick={handleApply}
            sx={{
              textTransform: "none",
              fontSize: 13,
              fontWeight: 700,
              borderRadius: "8px",
              px: 2,
              boxShadow: "none",
            }}
          >
            {text.apply}
          </Button>
        </Box>
      </Popover>
    </>
  );
}
