"use client";

import {
  type FormEvent,
  type MouseEvent,
  useState,
} from "react";

import {
  Box,
} from "@mui/material";

import {
  createTranslation,
  deleteTranslation,
  updateTranslation,
} from "../service/translation-service";

import {
  type TranslationPageGroup,
  useTranslationPageGroups,
} from "../hook/use-translation-page-groups";

import {
  getTranslationUiText,
  useUiLocale,
} from "../translation-ui-i18n";

import TranslationManagementViewDetail from "./translation-management-view-detail";
import TranslationManagementHeader from "./translation-management-header";
import TranslationManagementFilters from "./translation-management-filters";
import TranslationManagementTable from "./translation-management-table";
import TranslationManagementTableRow from "./translation-management-table-row";
import TranslationManagementFormDialog from "./translation-management-form-dialog";
import {
  TranslationManagementLabelMenu,
  TranslationManagementPageMenu,
} from "./translation-management-menus";
import {
  TranslationManagementDeleteLabelDialog,
  TranslationManagementDeletePageDialog,
} from "./translation-management-delete-dialogs";
import TranslationManagementToast from "./translation-management-toast";
import {
  getTranslationManagementPageText,
} from "./translation-management-page-text";

import {
  normalizePage,
  normalizeTranslationKey,
} from "./translation-management-utils";

import type {
  Translation,
  TranslationFormData,
} from "../types/translation-types";

const EMPTY_FORM: TranslationFormData = {
  translationKey: "",
  englishText: "",
  khmerText: "",
  module: "pswg",
  page: "",
  parentId: null,
  isActive: true,
};

export default function TranslationManagementPage() {
  const locale = useUiLocale();
  const text =
    getTranslationUiText(
      locale,
    );

  const appFontFamily =
    locale === "km"
      ? '"Kantumruy Pro", "Noto Sans Khmer", "Khmer OS System", Arial, sans-serif'
      : "inherit";

  const pageText =
    getTranslationManagementPageText(
      locale,
    );

  const {
    items: pageGroups,
    allItems:
      allPageGroups,
    meta,
    search,
    moduleFilter,
    loading,
    error,
    setPage,
    setSearch,
    setModuleFilter,
    setError,
    loadPageLabels,
    reload,
    resetFilters,
  } =
    useTranslationPageGroups();

  const getSubPageItems = (
    parentId: number,
  ): Array<{
    group: TranslationPageGroup;
    depth: number;
  }> => {
    const result: Array<{
      group: TranslationPageGroup;
      depth: number;
    }> = [];

    const visited =
      new Set<number>();

    const walk = (
      currentParentId: number,
      depth: number,
    ) => {
      const children =
        allPageGroups.filter(
          (item) =>
            item.parentId ===
            currentParentId,
        );

      for (const child of children) {
        if (
          visited.has(child.id)
        ) {
          continue;
        }

        visited.add(child.id);

        result.push({
          group: child,
          depth,
        });

        walk(
          child.id,
          depth + 1,
        );
      }
    };

    walk(parentId, 1);

    return result;
  };

  const [
    expandedRows,
    setExpandedRows,
  ] = useState<Record<number, boolean>>({});

  const setRowExpanded = (
    id: number,
    open: boolean,
  ) => {
    setExpandedRows(
      (current) => ({
        ...current,
        [id]: open,
      }),
    );
  };

  const getRowNumber = (
    rootIndex: number,
  ): number => {
    let number =
      (meta.page - 1) *
        meta.limit +
      1;

    for (
      let index = 0;
      index < rootIndex;
      index += 1
    ) {
      const previous =
        pageGroups[index];

      if (!previous) {
        continue;
      }

      // Count the previous root row itself.
      number += 1;

      // When expanded, count every visible Sub Page row.
      if (
        expandedRows[
          previous.id
        ]
      ) {
        number +=
          getSubPageItems(
            previous.id,
          ).length;
      }
    }

    return number;
  };

  const [
    formDialogOpen,
    setFormDialogOpen,
  ] = useState(false);

  const [
    pageLocked,
    setPageLocked,
  ] = useState(false);

  const [
    selectedLabel,
    setSelectedLabel,
  ] =
    useState<Translation | null>(
      null,
    );

  const [form, setForm] =
    useState<TranslationFormData>(
      {
        ...EMPTY_FORM,
      },
    );


  const [saving, setSaving] =
    useState(false);

  const [
    dialogError,
    setDialogError,
  ] = useState("");

  const [
    toastMessage,
    setToastMessage,
  ] = useState("");

  const [
    viewGroup,
    setViewGroup,
  ] =
    useState<TranslationPageGroup | null>(
      null,
    );

  const [
    pageLabels,
    setPageLabels,
  ] = useState<Translation[]>(
    [],
  );

  const [
    labelSearch,
    setLabelSearch,
  ] = useState("");

  const [
    loadingLabels,
    setLoadingLabels,
  ] = useState(false);

  const [
    labelsError,
    setLabelsError,
  ] = useState("");

  const [
    pageMenuAnchor,
    setPageMenuAnchor,
  ] =
    useState<HTMLElement | null>(
      null,
    );

  const [
    pageMenuGroup,
    setPageMenuGroup,
  ] =
    useState<TranslationPageGroup | null>(
      null,
    );

  const [
    labelMenuAnchor,
    setLabelMenuAnchor,
  ] =
    useState<HTMLElement | null>(
      null,
    );

  const [
    labelMenuItem,
    setLabelMenuItem,
  ] =
    useState<Translation | null>(
      null,
    );

  const [
    deleteTarget,
    setDeleteTarget,
  ] =
    useState<Translation | null>(
      null,
    );

  const [deleting, setDeleting] =
    useState(false);

  const [
    deletePageTarget,
    setDeletePageTarget,
  ] =
    useState<TranslationPageGroup | null>(
      null,
    );

  const [
    deletingPage,
    setDeletingPage,
  ] = useState(false);

  const loadLabelsForGroup = async (
    group: TranslationPageGroup,
  ) => {
    const labels = await loadPageLabels(
      group.module,
      group.page,
    );

    if (!group.translationKey) {
      return labels;
    }

    return labels.filter(
      (item) =>
        item.translationKey === group.translationKey,
    );
  };

  const refreshPageLabels =
    async (
      group:
        TranslationPageGroup,
    ) => {
      setLoadingLabels(true);
      setLabelsError("");

      try {
        const labels =
          await loadLabelsForGroup(
            group,
          );

        setPageLabels(labels);
      } catch (err) {
        setLabelsError(
          err instanceof Error
            ? err.message
            : "Unable to load labels.",
        );
      } finally {
        setLoadingLabels(false);
      }
    };

  const openViewLabels =
    async (
      group:
        TranslationPageGroup,
    ) => {
      setViewGroup(group);
      setLabelSearch("");
      setPageLabels([]);
      await refreshPageLabels(
        group,
      );
    };

  const openCreateNewPage = () => {
    setSelectedLabel(null);
    setPageLocked(false);
    setForm({
      ...EMPTY_FORM,
      parentId: null,
    });
    setDialogError("");
    setFormDialogOpen(true);
  };

  const openAddLabel = (
    group:
      TranslationPageGroup,
  ) => {
    setSelectedLabel(null);
    setPageLocked(true);
    setForm({
      ...EMPTY_FORM,
      module: group.module,
      page: group.page,
      parentId: group.parentId,
    });
    setDialogError("");
    setFormDialogOpen(true);
  };

  const openCreateSubPage = (
    group: TranslationPageGroup,
  ) => {
    setSelectedLabel(null);
    setPageLocked(false);
    setForm({
      ...EMPTY_FORM,
      module: group.module,
      page: "",
      parentId: group.id,
    });
    setDialogError("");
    setFormDialogOpen(true);
  };

  const openEditLabel = (
    item: Translation,
  ) => {
    if (
      !item.module ||
      !item.page
    ) {
      return;
    }

    setSelectedLabel(item);
    setPageLocked(true);
    setForm({
      translationKey:
        item.translationKey,
      englishText:
        item.englishText,
      khmerText:
        item.khmerText,
      module:
        item.module,
      page:
        item.page,
      parentId:
        item.parentId,
      isActive:
        item.isActive,
    });
    setDialogError("");
    setFormDialogOpen(true);
  };

  const closeFormDialog = () => {
    if (saving) {
      return;
    }

    setFormDialogOpen(false);
    setSelectedLabel(null);
    setPageLocked(false);
    setDialogError("");
    setForm({
      ...EMPTY_FORM,
      parentId: null,
    });
  };

  const handleSubmit =
    async (
      event:
        FormEvent<HTMLFormElement>,
    ) => {
      event.preventDefault();
      setDialogError("");

      const isCreatingPage =
        !pageLocked &&
        !selectedLabel;

      const translationKey =
        isCreatingPage
          ? "title"
          : normalizeTranslationKey(
              form.translationKey,
            );

      const page =
        normalizePage(
          form.page,
        );

      const englishText =
        form.englishText.trim();

      const khmerText =
        form.khmerText.trim();

      if (!page) {
        setDialogError(
          pageText.pageRequired,
        );
        return;
      }

      if (
        !isCreatingPage &&
        !translationKey
      ) {
        setDialogError(
          pageText.keyRequired,
        );
        return;
      }

      if (!englishText) {
        setDialogError(
          pageText.englishRequired,
        );
        return;
      }

      if (!khmerText) {
        setDialogError(
          pageText.khmerRequired,
        );
        return;
      }

      const payload:
        TranslationFormData = {
        ...form,
        page,
        translationKey,
        englishText,
        khmerText,
      };

      setSaving(true);

      try {
        if (selectedLabel) {
          await updateTranslation(
            selectedLabel.id,
            payload,
          );

          setToastMessage(
            pageText.updated,
          );
        } else {
          await createTranslation(
            payload,
          );

          setToastMessage(
            pageText.created,
          );
        }

        setFormDialogOpen(false);
        setSelectedLabel(null);
        setPageLocked(false);
        setForm({
          ...EMPTY_FORM,
        });

        await reload();

        if (
          viewGroup &&
          viewGroup.module ===
            payload.module &&
          viewGroup.page ===
            payload.page
        ) {
          await refreshPageLabels(
            viewGroup,
          );
        }
      } catch (err) {
        setDialogError(
          err instanceof Error
            ? err.message
            : "Unable to save label.",
        );
      } finally {
        setSaving(false);
      }
    };

  const openPageMenu = (
    event: MouseEvent<HTMLElement>,
    group: TranslationPageGroup,
  ) => {
    event.stopPropagation();
    setPageMenuAnchor(
      event.currentTarget,
    );
    setPageMenuGroup(group);
  };

  const closePageMenu = () => {
    setPageMenuAnchor(null);
    setPageMenuGroup(null);
  };

  const viewPageFromMenu = () => {
    if (!pageMenuGroup) {
      return;
    }

    const group =
      pageMenuGroup;

    closePageMenu();

    void openViewLabels(
      group,
    );
  };

  const addLabelFromPageMenu = () => {
    if (!pageMenuGroup) {
      return;
    }

    const group =
      pageMenuGroup;

    closePageMenu();
    openAddLabel(group);
  };

  const createSubPageFromMenu = () => {
    if (!pageMenuGroup) {
      return;
    }

    const group = pageMenuGroup;
    closePageMenu();
    openCreateSubPage(group);
  };

  const editPageFromMenu = async () => {
    if (!pageMenuGroup) {
      return;
    }

    const group =
      pageMenuGroup;

    closePageMenu();

    try {
      const labels =
        await loadLabelsForGroup(
          group,
        );

      // The Page table displays title/subtitle as its
      // English/Khmer text. Edit the same representative
      // record so the Page row updates consistently.
      const target =
        labels.find(
          (item) =>
            item.translationKey ===
            "title",
        ) ??
        labels.find(
          (item) =>
            item.translationKey ===
            "subtitle",
        ) ??
        labels[0];

      if (!target) {
        setError(
          locale === "km"
            ? "មិនមាន Label សម្រាប់កែប្រែទេ។"
            : "No label is available to edit.",
        );
        return;
      }

      openEditLabel(target);
    } catch (err) {
      setError(
        err instanceof Error
          ? err.message
          : locale === "km"
            ? "មិនអាចបើក Page សម្រាប់កែប្រែបានទេ។"
            : "Unable to open page for editing.",
      );
    }
  };

  const deletePageFromMenu = () => {
    if (!pageMenuGroup) {
      return;
    }

    const group =
      pageMenuGroup;

    closePageMenu();
    setDeletePageTarget(
      group,
    );
  };

  const handleDeletePage =
    async () => {
      if (!deletePageTarget) {
        return;
      }

      setDeletingPage(true);
      setError("");

      try {
        const labels =
          await loadLabelsForGroup(
            deletePageTarget,
          );

        // A Translation "Page" is represented by all translation
        // records that share the same module + page.
        // Delete every label using the existing DELETE /translations/:id API.
        for (const label of labels) {
          await deleteTranslation(
            label.id,
          );
        }

        setToastMessage(
          pageText.pageDeleted,
        );

        if (
          viewGroup &&
          viewGroup.module ===
            deletePageTarget.module &&
          viewGroup.page ===
            deletePageTarget.page
        ) {
          setViewGroup(null);
          setPageLabels([]);
          setLabelSearch("");
        }

        setDeletePageTarget(
          null,
        );

        await reload();
      } catch (err) {
        setError(
          err instanceof Error
            ? err.message
            : locale === "km"
              ? "មិនអាចលុប Page បានទេ។"
              : "Unable to delete page.",
        );
      } finally {
        setDeletingPage(false);
      }
    };

  const openLabelMenu = (
    event:
      MouseEvent<HTMLElement>,
    item: Translation,
  ) => {
    event.stopPropagation();
    setLabelMenuAnchor(
      event.currentTarget,
    );
    setLabelMenuItem(item);
  };

  const closeLabelMenu = () => {
    setLabelMenuAnchor(null);
    setLabelMenuItem(null);
  };

  const editFromMenu = () => {
    if (!labelMenuItem) {
      return;
    }

    const item =
      labelMenuItem;

    closeLabelMenu();
    openEditLabel(item);
  };

  const deleteFromMenu = () => {
    if (!labelMenuItem) {
      return;
    }

    const item =
      labelMenuItem;

    closeLabelMenu();
    setDeleteTarget(item);
  };

  const handleDelete =
    async () => {
      if (!deleteTarget) {
        return;
      }

      setDeleting(true);
      setError("");

      try {
        await deleteTranslation(
          deleteTarget.id,
        );

        setToastMessage(
          pageText.deleted,
        );

        setDeleteTarget(null);
        await reload();

        if (viewGroup) {
          await refreshPageLabels(
            viewGroup,
          );
        }
      } catch (err) {
        setError(
          err instanceof Error
            ? err.message
            : "Unable to delete label.",
        );
      } finally {
        setDeleting(false);
      }
    };

  return (
    <Box
      lang={locale === "km" ? "km" : "en"}
      sx={{
        minHeight: "100vh",
        bgcolor: "background.default",
        color: "text.primary",
        p: {
          xs: 2,
          md: 4,
        },
        fontFamily: appFontFamily,
        "& .MuiButton-root": {
          fontFamily: appFontFamily,
        },
        "& .MuiTableCell-root": {
          fontFamily: appFontFamily,
        },
        "& .MuiInputBase-root": {
          fontFamily: appFontFamily,
        },
        "& .MuiInputLabel-root": {
          fontFamily: appFontFamily,
        },
      }}
    >
      <Box
        sx={{
          width: "100%",
          maxWidth: 1600,
          mx: "auto",
        }}
      >
        {viewGroup ? (
          <TranslationManagementViewDetail
            locale={locale}
            appFontFamily={appFontFamily}
            group={viewGroup}
            labels={pageLabels}
            loading={loadingLabels}
            error={labelsError}
            search={labelSearch}
            text={{
              back: pageText.back,
              title: pageText.detailTitle,
              subtitle:
                pageText.detailSubtitle,
              module: text.module,
              page: pageText.page,
              addNewLabel:
                pageText.addNewLabel,
              searchPlaceholder:
                pageText.searchLabel,
              no: text.no,
              translationKey:
                pageText.translationKey,
              englishText:
                pageText.englishText,
              khmerText:
                pageText.khmerText,
              status: pageText.status,
              active: text.active,
              inactive: text.inactive,
              createdAt:
                pageText.createdAt,
              updatedAt:
                pageText.updatedAt,
              actions: pageText.actions,
              noLabels:
                pageText.noLabels,
            }}
            onSearchChange={setLabelSearch}
            onBack={() => {
              setViewGroup(null);
              setLabelSearch("");
              setPageLabels([]);
            }}
            onAddNewLabel={openAddLabel}
            onOpenActionMenu={
              openLabelMenu
            }
          />
        ) : (
          <>
            <TranslationManagementHeader
              title={text.pageTitle}
              subtitle={text.pageSubtitle}
              resetLabel={text.reset}
              createLabel={
                text.addTranslation
              }
              error={error}
              onReset={resetFilters}
              onCreatePage={
                openCreateNewPage
              }
            />

            <TranslationManagementFilters
              moduleFilter={moduleFilter}
              search={search}
              allModulesLabel={
                text.allModules
              }
              searchPlaceholder={
                pageText.searchPage
              }
              onModuleChange={(value) => {
                setModuleFilter(value);
                setPage(1);
              }}
              onSearchChange={(value) => {
                setSearch(value);
                setPage(1);
              }}
            />

            <TranslationManagementTable
              loading={loading}
              empty={
                pageGroups.length === 0
              }
              hierarchyMode={false}
              meta={meta}
              onPageChange={setPage}
              labels={{
                no: text.no,
                module: text.module,
                page: pageText.page,
                englishText:
                  pageText.englishText,
                khmerText:
                  pageText.khmerText,
                status: pageText.status,
                createdAt:
                  pageText.createdAt,
                updatedAt:
                  pageText.updatedAt,
                actions: pageText.actions,
                noPages: pageText.noPages,
                previous: text.previous,
                next: text.next,
              }}
              rows={pageGroups.map(
                (group, index) => (
                  <TranslationManagementTableRow
                    key={`${group.id}-${group.page}`}
                    group={group}
                    rowNumber={
                      getRowNumber(
                        index,
                      )
                    }
                    subPages={
                      getSubPageItems(
                        group.id,
                      )
                    }
                    open={
                      Boolean(
                        expandedRows[
                          group.id
                        ],
                      )
                    }
                    onOpenChange={(
                      nextOpen,
                    ) => {
                      setRowExpanded(
                        group.id,
                        nextOpen,
                      );
                    }}
                    locale={locale}
                    activeLabel={
                      text.active
                    }
                    inactiveLabel={
                      text.inactive
                    }
                    onSelectSubPage={(
                      child,
                    ) => {
                      void openViewLabels(
                        child,
                      );
                    }}
                    onOpenPageMenu={
                      openPageMenu
                    }
                  />
                ),
              )}
            />
          </>
        )}
      </Box>

      <TranslationManagementPageMenu
        anchorEl={pageMenuAnchor}
        appFontFamily={appFontFamily}
        labels={{
          viewDetail:
            pageText.viewLabels,
          addNewLabel:
            pageText.addNewLabel,
          createSubPage:
            pageText.createSubPage,
          edit: pageText.editPage,
          deletePage:
            pageText.deletePage,
        }}
        onClose={closePageMenu}
        onViewDetail={viewPageFromMenu}
        onAddNewLabel={
          addLabelFromPageMenu
        }
        onCreateSubPage={
          createSubPageFromMenu
        }
        onEdit={() => {
          void editPageFromMenu();
        }}
        onDeletePage={
          deletePageFromMenu
        }
      />

      <TranslationManagementLabelMenu
        anchorEl={labelMenuAnchor}
        editLabel={pageText.editLabel}
        deleteLabel={
          pageText.deleteLabel
        }
        onClose={closeLabelMenu}
        onEdit={editFromMenu}
        onDelete={deleteFromMenu}
      />

      <TranslationManagementFormDialog
        open={formDialogOpen}
        saving={saving}
        appFontFamily={appFontFamily}
        locale={locale}
        selectedLabel={selectedLabel}
        pageLocked={pageLocked}
        pageText={pageText}
        text={text}
        dialogError={dialogError}
        form={form}
        setForm={setForm}
        onClose={closeFormDialog}
        onSubmit={handleSubmit}
      />

      <TranslationManagementDeletePageDialog
        target={deletePageTarget}
        deleting={deletingPage}
        locale={locale}
        appFontFamily={appFontFamily}
        pageText={pageText}
        cancelLabel={text.cancel}
        setTarget={setDeletePageTarget}
        onDelete={() => {
          void handleDeletePage();
        }}
      />

      <TranslationManagementDeleteLabelDialog
        target={deleteTarget}
        deleting={deleting}
        pageText={pageText}
        cancelLabel={text.cancel}
        setTarget={setDeleteTarget}
        onDelete={() => {
          void handleDelete();
        }}
      />

      <TranslationManagementToast
        message={toastMessage}
        appFontFamily={appFontFamily}
        onClose={() =>
          setToastMessage("")
        }
      />
    </Box>
  );
}