"use client";

import { useState } from "react";
import { useQueryClient } from "@tanstack/react-query";
import { useFeedbackModal } from "@/app/components/providers/feedback-modal-provider";
import { useLoadingModal } from "@/app/components/providers/loading-modal-provider";
import { fetchBranches, type Branch } from "@/lib/api/branches";
import type { Device } from "@/lib/api/devices";
import { getErrorMessage } from "@/lib/api/types";
import { queryKeys } from "@/lib/query/query-keys";
import {
  useCreateDevice,
  useDeleteDevice,
  useDevices,
  useUpdateDevice,
  type DeviceFormData,
} from "@/lib/query/hooks/devices";
import { useClientPagination } from "@/lib/hooks/use-client-pagination";
import { DataPagination } from "../ui/data-pagination";
import { DataTableSection } from "../ui/data-table-section";
import { PageEnter, PageTextEnter } from "../ui/page-enter";
import { IconButton } from "../ui/button";
import { IconAdd } from "../ui/icons";
import { PerangkatFormModal } from "./perangkat-form-modal";
import { PerangkatTable } from "./perangkat-table";

const EMPTY_ITEMS: Device[] = [];
const EMPTY_BRANCHES: Branch[] = [];

type FormModalState =
  | { mode: "create" }
  | { mode: "edit"; item: Device };

export function PerangkatView() {
  const queryClient = useQueryClient();
  const { showLoading, hideLoading } = useLoadingModal();
  const { showDeleteConfirm, showSaveSuccess } = useFeedbackModal();
  const devicesQuery = useDevices();
  const createDeviceMutation = useCreateDevice();
  const updateDeviceMutation = useUpdateDevice();
  const deleteDeviceMutation = useDeleteDevice();

  const items = devicesQuery.data ?? EMPTY_ITEMS;
  const {
    setPage,
    paginatedItems,
    startIndex,
    clampPageAfterDelete,
    paginationProps,
  } = useClientPagination(items);
  const [formModal, setFormModal] = useState<FormModalState | null>(null);
  const [modalBranches, setModalBranches] = useState<Branch[]>(EMPTY_BRANCHES);
  const [isOpeningFormModal, setIsOpeningFormModal] = useState(false);
  const [mutationError, setMutationError] = useState<string | null>(null);

  const cachedBranches =
    queryClient.getQueryData<Branch[]>(queryKeys.branches.all) ?? EMPTY_BRANCHES;
  const fallbackBranchName =
    cachedBranches.length === 1 ? cachedBranches[0].name : undefined;

  const isSubmitting =
    createDeviceMutation.isPending ||
    updateDeviceMutation.isPending ||
    deleteDeviceMutation.isPending;

  const error =
    mutationError ??
    (devicesQuery.error
      ? getErrorMessage(devicesQuery.error, "Gagal memuat data perangkat.")
      : null);

  async function openFormModal(intent: FormModalState) {
    setMutationError(null);
    setIsOpeningFormModal(true);
    showLoading({
      message: "Memuat data cabang...",
      ariaLabel: "Memuat cabang",
    });

    try {
      const branches = await queryClient.fetchQuery({
        queryKey: queryKeys.branches.all,
        queryFn: fetchBranches,
      });
      setModalBranches(branches);
      setFormModal(intent);
    } catch (err) {
      setMutationError(getErrorMessage(err, "Gagal memuat data cabang."));
    } finally {
      hideLoading();
      setIsOpeningFormModal(false);
    }
  }

  function closeFormModal() {
    setFormModal(null);
    setModalBranches(EMPTY_BRANCHES);
    setMutationError(null);
  }

  async function runWithLoading<T>(
    message: string,
    action: () => Promise<T>,
  ): Promise<T> {
    showLoading({
      message,
      ariaLabel: "Memproses perangkat",
    });

    try {
      return await action();
    } finally {
      hideLoading();
    }
  }

  async function handleCreate(data: DeviceFormData) {
    setMutationError(null);

    try {
      await runWithLoading("Jangan tutup, proses sedang berlangsung", () =>
        createDeviceMutation.mutateAsync(data),
      );
      closeFormModal();
      setPage(1);
      showSaveSuccess({
        description: "Data perangkat telah tersimpan dengan aman.",
        onPrimary: () => void openFormModal({ mode: "create" }),
      });
    } catch (err) {
      setMutationError(getErrorMessage(err, "Gagal menyimpan perangkat."));
    }
  }

  async function handleUpdate(data: DeviceFormData) {
    if (!formModal || formModal.mode !== "edit") return;

    setMutationError(null);

    try {
      await runWithLoading("Jangan tutup, proses sedang berlangsung", () =>
        updateDeviceMutation.mutateAsync({
          id: formModal.item.id,
          payload: data,
        }),
      );
      closeFormModal();
      showSaveSuccess({
        description: "Data perangkat telah tersimpan dengan aman.",
        onPrimary: () => void openFormModal({ mode: "create" }),
      });
    } catch (err) {
      setMutationError(getErrorMessage(err, "Gagal memperbarui perangkat."));
    }
  }

  async function handleDelete(id: number) {
    setMutationError(null);

    try {
      await runWithLoading("Jangan tutup, proses sedang berlangsung", () =>
        deleteDeviceMutation.mutateAsync(id),
      );
      clampPageAfterDelete(items.length - 1);
    } catch (err) {
      setMutationError(getErrorMessage(err, "Gagal menghapus perangkat."));
      throw err;
    }
  }

  function handleDeleteRequest(item: Device) {
    showDeleteConfirm({
      onConfirm: () => handleDelete(item.id),
    });
  }

  function handleFormSubmit(data: DeviceFormData) {
    if (formModal?.mode === "edit") {
      void handleUpdate(data);
      return;
    }

    void handleCreate(data);
  }

  return (
    <PageEnter className="flex min-h-0 flex-1 flex-col">
      <div className="flex min-h-0 flex-1 flex-col overflow-hidden rounded-[10px] border border-neutral-40 bg-neutral-10">
        <div className="relative flex shrink-0 items-center gap-2 px-5 pt-5">
          <div className="absolute top-5 left-0 h-5 w-1 rounded-r-sm bg-primary-500" />
          <PageTextEnter
            as="h1"
            delay={0.08}
            className="text-l-medium flex-1 text-neutral-100"
          >
            Manajemen Perangkat
          </PageTextEnter>
          <PageEnter delay={0.12}>
            <IconButton
              icon={<IconAdd />}
              onClick={() => void openFormModal({ mode: "create" })}
              disabled={isOpeningFormModal}
            >
              Tambah Perangkat
            </IconButton>
          </PageEnter>
        </div>

        <div className="flex min-h-0 flex-1 flex-col gap-4 overflow-hidden p-5">
          <p className="text-m-regular text-neutral-80">
            Daftarkan tablet atau HP POS di sini. Gunakan{" "}
            <span className="font-mono text-neutral-100">kode perangkat</span>{" "}
            untuk aktivasi di aplikasi mobile.
          </p>

          {error && (
            <PageEnter delay={0.1}>
              <p className="text-m-regular rounded-lg border border-danger-200 bg-danger-50 px-4 py-3 text-danger-700">
                {error}
              </p>
            </PageEnter>
          )}

          {devicesQuery.isPending ? (
            <p className="text-m-regular text-neutral-80">Memuat data...</p>
          ) : (
            <PageEnter delay={0.2} className="flex min-h-0 flex-1 flex-col">
              <DataTableSection pagination={<DataPagination {...paginationProps} />}>
                <PerangkatTable
                  items={paginatedItems}
                  startIndex={startIndex}
                  fallbackBranchName={fallbackBranchName}
                  onEdit={(item) => void openFormModal({ mode: "edit", item })}
                  onDelete={handleDeleteRequest}
                />
              </DataTableSection>
            </PageEnter>
          )}
        </div>
      </div>

      {formModal && (
        <PerangkatFormModal
          key={
            formModal.mode === "edit"
              ? `edit-${formModal.item.id}`
              : "create"
          }
          open
          mode={formModal.mode}
          branches={modalBranches}
          initialData={formModal.mode === "edit" ? formModal.item : null}
          isSubmitting={isSubmitting}
          onClose={closeFormModal}
          onSubmit={handleFormSubmit}
        />
      )}
    </PageEnter>
  );
}
