"use client";

import dynamic from "next/dynamic";
import { useEffect, useMemo, useState, type ComponentType } from "react";

import Box from "@mui/material/Box";
import CircularProgress from "@mui/material/CircularProgress";
import Paper from "@mui/material/Paper";
import Typography from "@mui/material/Typography";
import { alpha, useTheme } from "@mui/material/styles";
import type { DataGridProps, GridPaginationModel } from "@mui/x-data-grid";

import {
  MEETING_REQUESTS_PAGE_SIZE,
  MEETING_REQUESTS_TABLE_MIN_WIDTH,
} from "@/features/pswg/meeting-request/components/table/meeting-requests-table-config";
import { getMeetingRequestsTableColumns } from "@/features/pswg/meeting-request/components/table/meeting-requests-table-columns";
import { MeetingRequestsTableFooter } from "@/features/pswg/meeting-request/components/table/meeting-requests-table-footer";
import { useMeetingRequests } from "@/features/pswg/meeting-request/hook/use-meeting-requests";
import type { MeetingRequestRow } from "@/features/pswg/meeting-request/meeting-request-data";
import type { UiLang } from "@/features/pswg/meeting-request/meeting-request-i18n";
import type {
  ApiIssue,
  ApiMeetingRequest,
  ApiStakeholder,
  ApiWorkingGroup,
} from "@/features/pswg/meeting-request/service/meeting-request-service";
import { AlertDialog } from "@/components/ui/alert-dialog";

type MeetingRequestRowWithApi = MeetingRequestRow & {
  title?: string;
  workingGroupId?: number | null;
  governmentAgencyId?: number | null;
  governmentAgencyLogo?: string | null;
  meetingMonthYear?: string;
  meetingRequestLetter?: string | null;
  issueIds?: number[];
  rawIssues?: ApiIssue[];
  issues?: ApiIssue[];
};

const DataGrid = dynamic(
  () => import("@mui/x-data-grid").then((mod) => mod.DataGrid),
  { ssr: false },
) as ComponentType<DataGridProps<MeetingRequestRowWithApi>>;

type MeetingRequestsTableProps = {
  language?: UiLang;
  refreshKey?: number;
  workingGroupFilter?: string[];
  governmentAgencyFilter?: string[];
  statusFilter?: string[];
  meetingDateFilter?: string[];
  onView?: (row: MeetingRequestRow) => void;
  onEdit?: (row: MeetingRequestRow) => void;
  onSendSuccess?: () => void;
};

function hasValidId(item: unknown): item is ApiMeetingRequest {
  if (!item || typeof item !== "object") return false;

  const id = (item as { id?: unknown }).id;

  return typeof id === "number" && Number.isFinite(id);
}

function formatMonthYear(value?: string) {
  if (!value) return "-";

  const date = new Date(value);

  if (Number.isNaN(date.getTime())) {
    return "-";
  }

  return date.toLocaleDateString("en-US", {
    month: "short",
    year: "numeric",
  });
}

function htmlToPlainText(value?: string | null) {
  if (!value) return "-";

  const plainText = value
    .replace(/<style[\s\S]*?<\/style>/gi, "")
    .replace(/<script[\s\S]*?<\/script>/gi, "")
    .replace(/<br\s*\/?>/gi, " ")
    .replace(/<\/p>/gi, " ")
    .replace(/<\/div>/gi, " ")
    .replace(/<\/li>/gi, " ")
    .replace(/<[^>]+>/g, "")
    .replace(/&nbsp;/gi, " ")
    .replace(/&amp;/gi, "&")
    .replace(/&lt;/gi, "<")
    .replace(/&gt;/gi, ">")
    .replace(/&quot;/gi, '"')
    .replace(/&#39;/gi, "'")
    .replace(/\s+/g, " ")
    .trim();

  return plainText || "-";
}

function resolveWorkingGroupForMeetingRequest(
  item: ApiMeetingRequest,
  workingGroups: ApiWorkingGroup[],
): ApiWorkingGroup | null {
  const agencies =
    item.governmentAgencies
      ?.map((agencyRequest) => agencyRequest.stakeholder)
      .filter((stakeholder): stakeholder is ApiStakeholder =>
        Boolean(stakeholder),
      ) ?? [];

  const directWorkingGroup = agencies.find(
    (agency) =>
      agency.stakeholderTypeId === 2 ||
      agency.stakeholderType?.name?.toLowerCase().includes("working"),
  );

  if (directWorkingGroup) {
    return directWorkingGroup as ApiWorkingGroup;
  }

  for (const agency of agencies) {
    const agencyId = Number(agency.id);
    const agencyRelatedStakeholderId = Number(agency.relatedStakeholderId);

    const found = workingGroups.find((workingGroup) => {
      const workingGroupId = Number(workingGroup.id);
      const workingGroupRelatedStakeholderId = Number(
        workingGroup.relatedStakeholderId,
      );

      return (
        workingGroupRelatedStakeholderId === agencyId ||
        workingGroupId === agencyRelatedStakeholderId
      );
    });

    if (found) return found;
  }

  return null;
}

export function MeetingRequestsTable({
  language = "km",
  refreshKey = 0,
  workingGroupFilter = [],
  governmentAgencyFilter = [],
  statusFilter = [],
  meetingDateFilter = [],
  onView,
  onEdit,
  onSendSuccess,
}: MeetingRequestsTableProps) {
  const theme = useTheme();
  const isDark = theme.palette.mode === "dark";

  const {
    data,
    workingGroups,
    loading,
    loadingWorkingGroups,
    error,
    sendError,
    fetchMeetingRequests,
    fetchWorkingGroups,
    sendMeetingRequest,
    clearSendMeetingRequestError,
  } = useMeetingRequests();

  const [sendConfirmRow, setSendConfirmRow] =
    useState<MeetingRequestRow | null>(null);
  const [sendingConfirm, setSendingConfirm] = useState(false);

  useEffect(() => {
    fetchMeetingRequests();
    fetchWorkingGroups();
  }, [refreshKey, fetchMeetingRequests, fetchWorkingGroups]);

  const rows: MeetingRequestRowWithApi[] = useMemo(() => {
    const mappedRows: MeetingRequestRowWithApi[] = data
      .filter((item) => hasValidId(item))
      .map((item) => {
        const firstAgency = item.governmentAgencies?.[0]?.stakeholder;
        const workingGroup = resolveWorkingGroupForMeetingRequest(
          item,
          workingGroups,
        );
        const rowIssues = item.issues || [];

        return {
          id: item.id,
          title: item.title || "",

          workingGroup: workingGroup?.name || "-",
          workingGroupId: workingGroup?.id ?? null,

          meetingDescription: htmlToPlainText(item.description),
          description: item.description || "",
          issuesCount: rowIssues.length,
          issueIds: rowIssues.map((issue) => issue.id),
          rawIssues: rowIssues,
          issues: rowIssues,

          meetingStatus: item.status || "Drafted",
          meetingDate: item.createdAt || "-",
          meetingMonthYear: formatMonthYear(item.createdAt),

          governmentAgency: firstAgency?.name || "-",
          governmentAgencyId: firstAgency?.id ?? null,
          governmentAgencyLogo: firstAgency?.logo || null,

          meetingRequest: item.meetingRequestLetter || "",
          meetingRequestLetter: item.meetingRequestLetter || "",
          canManage: item.canManage === true,
        };
      });

    let filteredRows = mappedRows;

    if (workingGroupFilter.length > 0) {
      filteredRows = filteredRows.filter((row) => {
        if (row.workingGroupId) {
          return workingGroupFilter.includes(String(row.workingGroupId));
        }

        return workingGroupFilter.includes(row.workingGroup);
      });
    }

    if (governmentAgencyFilter.length > 0) {
      filteredRows = filteredRows.filter((row) => {
        if (row.governmentAgencyId) {
          return governmentAgencyFilter.includes(
            String(row.governmentAgencyId),
          );
        }

        return governmentAgencyFilter.includes(row.governmentAgency);
      });
    }

    if (statusFilter.length > 0) {
      filteredRows = filteredRows.filter((row) =>
        statusFilter.includes(row.meetingStatus),
      );
    }

    if (meetingDateFilter.length > 0) {
      filteredRows = filteredRows.filter((row) =>
        meetingDateFilter.includes(row.meetingMonthYear || "-"),
      );
    }

    return filteredRows;
  }, [
    data,
    workingGroups,
    workingGroupFilter,
    governmentAgencyFilter,
    statusFilter,
    meetingDateFilter,
  ]);

  const columns = useMemo(
    () =>
      getMeetingRequestsTableColumns(language, {
        onView,
        onEdit,
        onSend: (row) => {
          clearSendMeetingRequestError();
          setSendConfirmRow(row);
        },
      }),
    [language, onView, onEdit, clearSendMeetingRequestError],
  );

  async function handleConfirmSend() {
    if (!sendConfirmRow || sendingConfirm) return;

    const id = Number(sendConfirmRow.id);
    if (!Number.isFinite(id)) {
      setSendConfirmRow(null);
      return;
    }

    try {
      setSendingConfirm(true);
      const result = await sendMeetingRequest(id);

      if (result) {
        setSendConfirmRow(null);
        onSendSuccess?.();
      }
    } finally {
      setSendingConfirm(false);
    }
  }

  const [paginationModel, setPaginationModel] = useState<GridPaginationModel>({
    page: 0,
    pageSize: MEETING_REQUESTS_PAGE_SIZE,
  });

  const pageCount = Math.max(
    1,
    Math.ceil(rows.length / paginationModel.pageSize),
  );

  const dataGridSx = useMemo(
    () => ({
      border: "none",
      color: isDark ? alpha("#ffffff", 0.86) : theme.palette.text.primary,
      backgroundColor: isDark ? "#101828" : "#ffffff",

      "& .MuiDataGrid-columnHeaders": {
        backgroundColor: isDark ? alpha("#ffffff", 0.06) : "#ddedfb",
      },

      "& .MuiDataGrid-columnHeader": {
        px: 2,
        backgroundColor: isDark ? alpha("#ffffff", 0.06) : "#ddedfb",
      },

      "& .MuiDataGrid-columnHeaderTitle": {
        fontSize: 12,
        fontWeight: 500,
        color: isDark ? alpha("#ffffff", 0.72) : "#717680",
        lineHeight: 1.25,
        overflow: "visible",
        whiteSpace: "normal",
      },

      "& .MuiDataGrid-cell": {
        px: 2,
        py: 0,
        display: "flex",
        alignItems: "center",
        overflow: "hidden",
        backgroundColor: isDark ? "#101828" : "#ffffff",
        color: isDark ? alpha("#ffffff", 0.86) : theme.palette.text.primary,
      },

      "& .MuiDataGrid-row": {
        backgroundColor: isDark ? "#101828" : "#ffffff",
      },

      "& .MuiDataGrid-row:hover": {
        backgroundColor: isDark ? alpha("#ffffff", 0.04) : "#f9fafb",
      },

      "& .MuiDataGrid-withBorderColor": {
        borderColor: isDark ? alpha("#ffffff", 0.08) : "#f5f5f5",
      },

      "& .MuiDataGrid-cell:focus, & .MuiDataGrid-cell:focus-within": {
        outline: "none",
      },

      "& .MuiDataGrid-columnHeader:focus, & .MuiDataGrid-columnHeader:focus-within":
        {
          outline: "none",
        },

      "& .MuiDataGrid-main": {
        overflow: "hidden",
      },

      "& .MuiDataGrid-virtualScroller": {
        overflowX: "auto !important",
        overflowY: "auto !important",
        backgroundColor: isDark ? "#101828" : "#ffffff",
      },

      "& .MuiDataGrid-columnHeadersInner, & .MuiDataGrid-virtualScrollerContent":
        {
          minWidth: MEETING_REQUESTS_TABLE_MIN_WIDTH,
        },

      "& .MuiDataGrid-columnHeader[data-field='meetingRequest'] .MuiDataGrid-columnHeaderTitleContainer":
        {
          justifyContent: "center",
        },

      "& .MuiDataGrid-cell[data-field='meetingRequest']": {
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
      },
    }),
    [isDark, theme.palette.text.primary],
  );

  return (
    <Paper
      elevation={0}
      sx={{
        flex: 1,
        minHeight: 428,
        display: "flex",
        flexDirection: "column",
        borderRadius: "12px",
        border: `1px solid ${isDark ? alpha("#ffffff", 0.1) : "#f5f5f5"}`,
        overflow: "hidden",
        backgroundColor: isDark ? "#101828" : "#ffffff",
      }}
    >
      <Box sx={{ flex: 1, minHeight: 360, width: "100%" }}>
        {loading || loadingWorkingGroups ? (
          <Box sx={{ height: "100%", display: "grid", placeItems: "center" }}>
            <CircularProgress size={28} />
          </Box>
        ) : error ? (
          <Box
            sx={{
              height: "100%",
              display: "grid",
              placeItems: "center",
              px: 2,
            }}
          >
            <Typography sx={{ color: "#d92d20", fontSize: 14 }}>
              {error}
            </Typography>
          </Box>
        ) : (
          <DataGrid
            rows={rows}
            columns={columns}
            getRowId={(row) => row.id}
            pagination
            hideFooter
            disableRowSelectionOnClick
            disableColumnSelector
            disableDensitySelector
            paginationModel={paginationModel}
            onPaginationModelChange={setPaginationModel}
            pageSizeOptions={[MEETING_REQUESTS_PAGE_SIZE]}
            showCellVerticalBorder
            showColumnVerticalBorder
            rowHeight={74}
            columnHeaderHeight={56}
            sx={dataGridSx}
          />
        )}
      </Box>

      <MeetingRequestsTableFooter
        language={language}
        page={paginationModel.page}
        pageCount={pageCount}
        onPrevious={() =>
          setPaginationModel((current) => ({
            ...current,
            page: Math.max(0, current.page - 1),
          }))
        }
        onNext={() =>
          setPaginationModel((current) => ({
            ...current,
            page: Math.min(pageCount - 1, current.page + 1),
          }))
        }
        onSelectPage={(pageIndex) =>
          setPaginationModel((current) => ({
            ...current,
            page: pageIndex,
          }))
        }
      />

      <AlertDialog
        open={Boolean(sendConfirmRow)}
        title="Send Request"
        description={
          <>
            Do you want to send this meeting request?
            {sendError ? (
              <Box component="span" sx={{ display: "block", mt: 1.5, color: "#d92d20" }}>
                {sendError}
              </Box>
            ) : null}
          </>
        }
        confirmLabel="Confirm"
        cancelLabel="Cancel"
        loading={sendingConfirm}
        onConfirm={() => void handleConfirmSend()}
        onCancel={() => {
          if (!sendingConfirm) {
            setSendConfirmRow(null);
            clearSendMeetingRequestError();
          }
        }}
      />
    </Paper>
  );
}
