"use client";

import { OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil";
import RestartAlt from "@mui/icons-material/RestartAlt";
import Search from "@mui/icons-material/Search";
import {
  Box,
  Button,
  Card,
  CardActions,
  CardContent,
  FormControl,
  Grid,
  InputLabel,
  MenuItem,
  Select,
  SelectChangeEvent,
  TextField,
  Typography,
} from "@mui/material";
import { DatePicker, LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import dayjs from "dayjs";
import "dayjs/locale/zh-hk";
import { useCallback, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";

export type StockIssueSearchFieldType = "text" | "select" | "date";

export interface StockIssueSearchField<K extends string> {
  name: K;
  label: string;
  type: StockIssueSearchFieldType;
  options?: string[];
  /** Optional label for select option values (defaults to i18n `t(option)`). */
  getOptionLabel?: (value: string) => string;
  /** When this date is picked, copy the same value to `mirrorTo`. */
  mirrorTo?: K;
}

interface Props<K extends string> {
  fields: StockIssueSearchField<K>[];
  onSearch: (values: Record<K, string>) => void;
  onReset?: () => void;
  extraActions?: React.ReactNode;
  disabled?: boolean;
}

function StockIssueSearchPanel<K extends string>({
  fields,
  onSearch,
  onReset,
  extraActions,
  disabled = false,
}: Props<K>) {
  const { t } = useTranslation("stockIssue");
  const { t: tCommon } = useTranslation("common"); // All

  const emptyValues = useMemo(() => {
    return fields.reduce(
      (acc, field) => {
        acc[field.name] =
          field.type === "select" ? "All" : "";
        return acc;
      },
      {} as Record<K, string>,
    );
  }, [fields]);

  const [values, setValues] = useState<Record<K, string>>(emptyValues);

  const handleTextChange = useCallback(
    (name: K) => (e: React.ChangeEvent<HTMLInputElement>) => {
      setValues((prev) => ({ ...prev, [name]: e.target.value }));
    },
    [],
  );

  const handleSelectChange = useCallback(
    (name: K) => (e: SelectChangeEvent) => {
      setValues((prev) => ({ ...prev, [name]: e.target.value }));
    },
    [],
  );

  const handleDateChange = useCallback(
    (name: K, mirrorTo?: K) => (date: dayjs.Dayjs | null) => {
      const formatted =
        date && dayjs(date).isValid() ? dayjs(date).format("YYYY-MM-DD") : "";
      setValues((prev) => ({
        ...prev,
        [name]: formatted,
        ...(mirrorTo ? { [mirrorTo]: formatted } : {}),
      }));
    },
    [],
  );

  const handleReset = () => {
    setValues(emptyValues);
    onReset?.();
  };

  const handleSearchClick = () => {
    onSearch(values);
  };

  return (
    <Card className="app-search-criteria" elevation={0} sx={{ mb: 2 }}>
      <CardContent sx={{ display: "flex", flexDirection: "column", gap: 1 }}>
        <Typography
          className="app-search-criteria-label"
          variant="overline"
          sx={{ display: "block", mb: 0.5 }}
        >
          {t("Search Criteria")}
        </Typography>
        <Grid container spacing={2} columns={{ xs: 12, sm: 12, md: 12, lg: 12 }}>
          {fields.map((field) => (
            <Grid key={field.name} item xs={12} sm={6} md={4} lg={3}>
              {field.type === "text" && (
                <TextField
                  label={field.label}
                  fullWidth
                  value={values[field.name] ?? ""}
                  onChange={handleTextChange(field.name)}
                  disabled={disabled}
                />
              )}
              {field.type === "select" && (
                <FormControl fullWidth disabled={disabled}>
                  <InputLabel>{field.label}</InputLabel>
                  <Select
                    label={field.label}
                    value={values[field.name] ?? "All"}
                    onChange={handleSelectChange(field.name)}
                  >
                    <MenuItem value="All">{tCommon("All")}</MenuItem>
                    {(field.options ?? []).map((option) => (
                      <MenuItem key={option} value={option}>
                        {field.getOptionLabel?.(option) ?? t(option)}
                      </MenuItem>
                    ))}
                  </Select>
                </FormControl>
              )}
              {field.type === "date" && (
                <LocalizationProvider
                  dateAdapter={AdapterDayjs}
                  adapterLocale="zh-hk"
                >
                  <DatePicker
                    label={field.label}
                    format={OUTPUT_DATE_FORMAT}
                    disabled={disabled}
                    value={
                      values[field.name] && dayjs(values[field.name]).isValid()
                        ? dayjs(values[field.name])
                        : null
                    }
                    onChange={handleDateChange(field.name, field.mirrorTo)}
                    slotProps={{ textField: { fullWidth: true } }}
                  />
                </LocalizationProvider>
              )}
            </Grid>
          ))}
        </Grid>
        <CardActions
          sx={{ justifyContent: "flex-start", gap: 1, pt: 2, flexWrap: "wrap", px: 0 }}
        >
          <Button
            variant="outlined"
            startIcon={<RestartAlt />}
            onClick={handleReset}
            disabled={disabled}
            sx={{ borderColor: "#e2e8f0", color: "#334155" }}
          >
            {t("Reset")}
          </Button>
          <Button
            variant="contained"
            color="primary"
            startIcon={<Search />}
            onClick={handleSearchClick}
            disabled={disabled}
          >
            {t("Search")}
          </Button>
          {extraActions}
        </CardActions>
      </CardContent>
    </Card>
  );
}

export default StockIssueSearchPanel;
