"use client";

import { getWorkingGroupDisplayName } from "@/features/stakeholder/stakeholder-data";
import { useState } from "react";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import {
  Alert,
  Box,
  Button,
  Chip,
  CircularProgress,
  Drawer,
  Stack,
  Typography,
} from "@mui/material";
import RestoreIcon from "@mui/icons-material/Restore";
import { useAppLanguage } from "@/components/providers/app-language-provider";
import {
  DataTable,
  DataTableNumberCell,
  type DataTableColDef,
} from "@/components/ui/data-table";
import { ConfirmDialog } from "@/components/ui/confirm-dialog";
import { RecycleBinFilters } from "./recycle-bin-filters";
import { RecycleBinActions } from "./recycle-bin-actions";
import { ToastNotification } from "@/components/ui/toast-notification";
import { usePermissions } from "@/features/auth/hook/use-permissions";
import { isAdminRole } from "@/features/auth/auth-data";
import { formatNumber } from "@/lib/number-utils";
import { formatActivityTime } from "../activity-logs/activity-log-details-drawer";
import {
  binText,
  fieldLabels,
  valueLabels,
  getRecycleBinRecord,
  listRecycleBinRecords,
  plainValue,
  recordTypes,
  restoreRecycleBinRecord,
  permanentlyDeleteRecycleBinRecord,
  type DeletedRecord,
  type LinkedRecord,
  type RecordFilters,
  type RecordType,
} from "./recycle-bin-data";

const initialFilters: RecordFilters = {
  type: "all",
  search: "",
  from: null,
  to: null,
};

export default function RecycleBinPage() {
  const { language } = useAppLanguage();
  const text = binText[language === "en" ? "en" : "kh"];
  const labelIndex = language === "en" ? 0 : 1;
  const access = usePermissions();
  const isAdmin = isAdminRole(access.role);
  const queryClient = useQueryClient();
  const [filters, setFilters] = useState(initialFilters);
  const [page, setPage] = useState(0);
  const [selected, setSelected] = useState<DeletedRecord | null>(null);
  const [restoring, setRestoring] = useState<DeletedRecord | null>(null);
  const [deleting, setDeleting] = useState<DeletedRecord | null>(null);
  const [pending, setPending] = useState(false);
  const [toast, setToast] = useState<{
    message: string;
    variant: "success" | "error";
  } | null>(null);
  const invalidDates = Boolean(
    filters.from && filters.to && filters.from > filters.to,
  );
  const records = useQuery({
    queryKey: ["recycle-bin", filters, page],
    queryFn: ({ signal }) => listRecycleBinRecords(filters, page, signal),
    enabled: isAdmin && !invalidDates,
    retry: false,
  });
  const detail = useQuery({
    queryKey: ["recycle-bin-detail", selected?.type, selected?.id],
    queryFn: ({ signal }) => getRecycleBinRecord(selected!, signal),
    enabled: isAdmin && Boolean(selected),
    retry: false,
  });

  function changeFilters(next: Partial<RecordFilters>) {
    setFilters((current) => ({ ...current, ...next }));
    setPage(0);
  }
  function typeLabel(type: string) {
    return (
      recordTypes[type as RecordType]?.[labelIndex] ??
      fieldLabels[type]?.[labelIndex] ??
      (type === "meeting-summary-statuses"
        ? labelIndex
          ? "ស្ថានភាពសេចក្តីសង្ខេបកិច្ចប្រជុំ"
          : "Meeting summary statuses"
        : type)
    );
  }
  function recordTitle(row: DeletedRecord) {
    if (row.type === "stakeholders" && row.details.stakeholder_type_id === 2) {
      return getWorkingGroupDisplayName({
        name: row.title,
        khName: typeof row.details.kh_name === "string" ? row.details.kh_name : null,
      }, language);
    }
    if (
      language !== "en" &&
      typeof row.details.kh_name === "string" &&
      row.details.kh_name
    )
      return row.details.kh_name;
    return plainValue(row.title);
  }
  function linkedRows(rows: LinkedRecord[]) {
    return rows.map((row, index) => (
      <Stack
        key={`${row.type}-${row.id}-${index}`}
        direction="row"
        spacing={1}
        sx={{ alignItems: "center" }}
      >
        <Typography sx={{ flex: 1, overflowWrap: "anywhere" }}>
          {typeLabel(row.type)} · {row.type === "stakeholders" ? getWorkingGroupDisplayName({ name: row.title, khName: row.khName }, language) : plainValue(row.title)} (#
          {formatNumber(row.id, language)})
        </Typography>
        <Chip
          size="small"
          label={row.deleted ? text.deletedLabel : text.active}
          color={row.deleted ? "warning" : "default"}
        />
      </Stack>
    ));
  }
  async function restore() {
    if (!restoring || pending) return;
    setPending(true);
    try {
      await restoreRecycleBinRecord(restoring, language);
      setRestoring(null);
      setSelected(null);
      setPage(0);
      // Restoration can affect lists, options, assignments and dashboard counts.
      await queryClient.invalidateQueries();
      setToast({ message: text.success, variant: "success" });
    } catch (error) {
      setToast({
        message: error instanceof Error ? error.message : text.failed,
        variant: "error",
      });
    } finally {
      setPending(false);
    }
  }

  async function permanentlyDelete() {
    if (!deleting || pending) return;
    setPending(true);
    try {
      await permanentlyDeleteRecycleBinRecord(deleting, language);
      setDeleting(null);
      setSelected(null);
      setPage(0);
      await queryClient.invalidateQueries();
      setToast({ message: text.permanentDeleteSuccess, variant: "success" });
    } catch (error) {
      setToast({
        message:
          error instanceof Error ? error.message : text.permanentDeleteFailed,
        variant: "error",
      });
    } finally {
      setPending(false);
    }
  }

  const columns = (
    [
      {
        field: "id",
        headerName: text.id,
        width: 120,
        renderCell: ({ row }) => <DataTableNumberCell value={row.id} />,
      },
      {
        field: "title",
        headerName: text.name,
        minWidth: 260,
        flex: 1,
        valueGetter: (_value, row) => recordTitle(row),
        renderCell: ({ row }) => (
          <Typography
            component="span"
            noWrap
            sx={{
              display: "block",
              width: "100%",
              fontSize: "inherit",
              lineHeight: 1.7,
            }}
          >
            {recordTitle(row)}
          </Typography>
        ),
      },
      {
        field: "type",
        headerName: text.type,
        width: 190,
        valueGetter: (_value, row) => typeLabel(row.type),
      },
      {
        field: "deletedAt",
        headerName: text.deleted,
        width: 240,
        valueFormatter: (value: string) => formatActivityTime(value, language),
      },
      {
        field: "deletedBy",
        headerName: text.deletedBy,
        width: 180,
        valueGetter: (_value, row) => row.deletedBy?.name || text.unknown,
      },
      {
        field: "actions",
        headerName: text.actions,
        width: 100,
        align: "center",
        headerAlign: "center",
        renderCell: ({ row }) => (
          <RecycleBinActions
            actionsLabel={text.actions}
            viewLabel={text.view}
            restoreLabel={text.restore}
            deleteLabel={text.permanentlyDelete}
            onView={() => setSelected(row)}
            onRestore={() => setRestoring(row)}
            onDelete={() => setDeleting(row)}
          />
        ),
      },
    ] satisfies DataTableColDef<DeletedRecord>[]
  ).map((column) => ({
    ...column,
    sortable: false,
    filterable: false,
    disableColumnMenu: true,
  }));

  if (access.isLoading) return <CircularProgress aria-label={text.loading} />;
  if (access.error) return <Alert severity="error">{text.error}</Alert>;
  if (!isAdmin) return <Alert severity="warning">{text.denied}</Alert>;

  return (
    <Stack spacing={3} sx={{ p: { xs: 2, md: 3 } }}>
      <Typography variant="h5" component="h1" sx={{ fontWeight: 600 }}>
        {text.title}
      </Typography>
      <Stack
        direction="row"
        spacing={2}
        useFlexGap
        sx={{ alignItems: "end", flexWrap: "wrap" }}
      >
        <RecycleBinFilters filters={filters} onChange={changeFilters} />
      </Stack>
      {invalidDates ? (
        <Alert severity="warning">{text.invalidDates}</Alert>
      ) : records.isError ? (
        <Alert
          severity="error"
          action={
            <Button onClick={() => void records.refetch()}>{text.retry}</Button>
          }
        >
          {text.error}
        </Alert>
      ) : (
        <DataTable
          rows={records.data?.data ?? []}
          columns={columns}
          getRowId={(row) => `${row.type}-${row.id}`}
          loading={records.isFetching}
          emptyMessage={text.empty}
          pageSize={25}
          paginationMode="server"
          rowCount={records.data?.meta.total ?? 0}
          paginationModel={{ page, pageSize: 25 }}
          onPaginationModelChange={(model) => setPage(model.page)}
          onRowClick={({ row }) => setSelected(row)}
        />
      )}

      <Drawer
        anchor="right"
        open={Boolean(selected)}
        onClose={() => setSelected(null)}
        slotProps={{ paper: { sx: { width: { xs: "100%", sm: 620 }, p: 3 } } }}
      >
        <Stack spacing={2}>
          <Stack direction="row" sx={{ justifyContent: "space-between" }}>
            <Typography variant="h6">{text.view}</Typography>
            <Button onClick={() => setSelected(null)}>{text.close}</Button>
          </Stack>
          {detail.isLoading && <CircularProgress aria-label={text.loading} />}
          {detail.isError && (
            <Alert
              severity="error"
              action={
                <Button onClick={() => void detail.refetch()}>
                  {text.retry}
                </Button>
              }
            >
              {text.error}
            </Alert>
          )}
          {detail.data && (
            <>
              <Typography sx={{ fontWeight: 600 }}>
                {recordTitle(detail.data)}
              </Typography>
              <Typography>
                {text.id}: {formatNumber(detail.data.id, language)}
              </Typography>
              <Typography>
                {text.deleted}:{" "}
                {formatActivityTime(detail.data.deletedAt, language)}
              </Typography>
              <Typography>
                {text.deletedBy}: {detail.data.deletedBy?.name || text.unknown}
              </Typography>
              <Typography>
                {text.created}:{" "}
                {formatActivityTime(detail.data.createdAt, language)}
              </Typography>
              {Object.entries(detail.data.details)
                .filter(([key]) => !key.endsWith("_id"))
                .map(([key, value]) => (
                  <Box key={key}>
                    <Typography color="text.secondary" variant="body2">
                      {fieldLabels[key]?.[labelIndex] ?? key}
                    </Typography>
                    <Typography
                      sx={{ overflowWrap: "anywhere", whiteSpace: "pre-wrap" }}
                    >
                      {typeof value === "boolean"
                        ? value
                          ? text.yes
                          : text.no
                        : typeof value === "number" || key === "number_issue"
                          ? formatNumber(plainValue(value), language)
                          : [
                                "meeting_date",
                                "deadline",
                                "submitted_to_cdc_at",
                              ].includes(key) && typeof value === "string"
                            ? formatActivityTime(value, language)
                            : typeof value === "string" &&
                                ["status", "semester"].includes(key)
                              ? (valueLabels[value]?.[labelIndex] ??
                                plainValue(value))
                              : plainValue(value)}
                    </Typography>
                  </Box>
                ))}
              {!!detail.data.parents.length && (
                <>
                  <Typography variant="h6">{text.linked}</Typography>
                  {linkedRows(detail.data.parents)}
                </>
              )}
              {!!detail.data.assignments.length && (
                <>
                  <Typography variant="h6">{text.assignments}</Typography>
                  {linkedRows(detail.data.assignments)}
                </>
              )}
              {detail.data.relatedCounts?.map((group) => (
                <Typography key={group.type}>
                  {typeLabel(group.type)}: {formatNumber(group.total, language)}{" "}
                  ({text.deletedLabel}: {formatNumber(group.deleted, language)})
                </Typography>
              ))}
              {detail.data.parents.some((row) => row.deleted) && (
                <Alert severity="warning">{text.parentWarning}</Alert>
              )}
              <Button
                variant="contained"
                startIcon={<RestoreIcon />}
                disabled={detail.data.parents.some((row) => row.deleted)}
                onClick={() => setRestoring(detail.data!)}
              >
                {text.restore}
              </Button>
            </>
          )}
        </Stack>
      </Drawer>
      <ConfirmDialog
        open={Boolean(restoring)}
        title={text.confirm}
        tone="primary"
        confirmLabel={text.restore}
        cancelLabel={text.cancel}
        confirmIcon={<RestoreIcon />}
        loading={pending}
        onConfirm={() => void restore()}
        onCancel={() => setRestoring(null)}
        description={
          <Stack spacing={2}>
            <Typography sx={{ fontWeight: 600 }}>
              {restoring ? recordTitle(restoring) : ""}
            </Typography>
            <Typography>{text.description}</Typography>
            {restoring &&
              ["roles", "permissions", "users"].includes(restoring.type) && (
                <Alert severity="warning">{text.access}</Alert>
              )}
            {restoring?.type === "users" && (
              <Alert severity="info">{text.user}</Alert>
            )}
          </Stack>
        }
      />
      <ConfirmDialog
        open={Boolean(deleting)}
        title={text.permanentDeleteConfirm}
        tone="danger"
        confirmLabel={text.permanentlyDelete}
        cancelLabel={text.cancel}
        loading={pending}
        onConfirm={() => void permanentlyDelete()}
        onCancel={() => setDeleting(null)}
        description={
          <Stack spacing={2}>
            <Typography sx={{ fontWeight: 600 }}>
              {deleting ? recordTitle(deleting) : ""}
            </Typography>
            {deleting && (
              <Typography>
                {typeLabel(deleting.type)} · {text.id}:{" "}
                {formatNumber(deleting.id, language)}
              </Typography>
            )}
            <Typography>
              {deleting?.type === "issues"
                ? text.issuePermanentDeleteDescription
                : deleting?.type === "progress-reports"
                ? text.reportPermanentDeleteDescription
                : text.permanentDeleteDescription}
            </Typography>
            {deleting && ["users", "roles", "permissions"].includes(deleting.type) && (
              <Alert severity="warning">{text.permanentDeleteAccess}</Alert>
            )}
          </Stack>
        }
      />
      <ToastNotification
        open={Boolean(toast)}
        message={toast?.message ?? ""}
        variant={toast?.variant ?? "success"}
        onClose={() => setToast(null)}
        closeLabel={text.close}
      />
    </Stack>
  );
}
