"use client";

import sumBy from "lodash/sumBy";
import { useState, useCallback, useEffect } from "react";

import Tab from "@mui/material/Tab";
import Tabs from "@mui/material/Tabs";
import Card from "@mui/material/Card";
import Table from "@mui/material/Table";
import Stack from "@mui/material/Stack";
import Button from "@mui/material/Button";
import Divider from "@mui/material/Divider";
import Tooltip from "@mui/material/Tooltip";
import Container from "@mui/material/Container";
import TableBody from "@mui/material/TableBody";
import IconButton from "@mui/material/IconButton";
import { alpha, useTheme } from "@mui/material/styles";
import TableContainer from "@mui/material/TableContainer";
import LocalizationProvider from "@/shared/locales/localization-provider";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { paths } from "@/routes/paths";
import { useRouter } from "@/hooks";
import RouterLink from "@/routes/router-link";

import { useBoolean } from "@/hooks";

import { isAfter, isBetween } from "@/utils/format-time";

import {
  TASK_SORT_OPTIONS,
  TASK_TYPE_OPTIONS,
  _managers,
} from "@/shared/_mock";

import Label from "@/shared/components/label";
import Iconify from "@/shared/components/iconify";
import Scrollbar from "@/shared/components/scrollbar";
import { useSnackbar } from "@/components/snackbar";
import { ConfirmDialog } from "@/shared/components/custom-dialog";
import { useSettingsContext } from "@/shared/components/settings";
import CustomBreadcrumbs from "@/components/custom-breadcrumbs";
import {
  useTable,
  emptyRows,
  TableNoData,
  getComparator,
  TableHeadCustom,
  TableSelectedAction,
  TablePaginationCustom,
  TableEmptyRows,
} from "@/shared/components/table";

import {
  ITaskItem,
  ITaskTableFilterValue,
  ITaskTableFilters,
  IManager,
} from "@/contexts/types/tasks";
import TaskTableRow from "./task-table-row";
import TaskSearch from "./task-search";
import TaskSort from "./task-sort";
import TaskFilters from "./task-filters";
import { orderBy } from "lodash";
import {
  archiveListTask,
  archiveTask,
  deleteListTask,
  deleteTask,
  recoverListTask,
  recoverTask,
} from "@/shared/api/task";
import TaskFiltersResult from "./task-filters-result";
import { axiosInstance, endpoints } from "@/utils/axios";
// ----------------------------------------------------------------------

const TABLE_HEAD = [
  { id: "name", label: "Name" },
  { id: "startDate", label: "Create" },
  { id: "endDate", label: "Due" },
  { id: "priority", label: "Priority" }, 
  { id: "type", label: "Type" },
  { id: "managerId", label: "Manager", align: "center" },
  { id: "collaborators", label: "Collaborators", align: "center" },
  { id: "status", label: "Status" },
  { id: "" },
];

const defaultFilters: ITaskTableFilters = {
  name: "",
  manager: [],
  column: {
    id: 0,
    name: "all",
    orderIndex: 0,
    tasks: []
  },
  type: [],
  startDate: null,
  endDate: null,
};

// ----------------------------------------------------------------------

export default function AllTasksView() {
  const { enqueueSnackbar } = useSnackbar();
  const theme = useTheme();
  const settings = useSettingsContext();
  const openFilters = useBoolean();
  const router = useRouter();
  const table = useTable({ defaultOrderBy: "startDate" });
  const confirm = useBoolean();
  const confirmArchive = useBoolean();
  const [tableData, setTableData] = useState<ITaskItem[]>([]);
  const [filters, setFilters] = useState(defaultFilters);
  const dateError = isAfter(filters.startDate, filters.endDate);
  const [sortBy, setSortBy] = useState("latest");
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [search, setSearch] = useState<{ query: string; results: ITaskItem[] }>(
    {
      query: "",
      results: [],
    }
  );
  const [managers, setManagers] = useState<IManager[]>([]);
  const agencyId = Number(localStorage.getItem("selectedAgency"));

  useEffect(() => {
    const fetchTasks = async () => {
      setLoading(true);
      try {
        const response = await axiosInstance.get(
          `${process.env.NEXT_PUBLIC_GATEWAY_API}/api/projects/api/tasks/${agencyId}/CURRENT`
        );
        setTableData(response.data);
      } catch (err) {
        console.error(err);
        setError("Failed to fetch tasks.");
      } finally {
        setLoading(false);
      }
    };

    fetchTasks();
  }, [agencyId]);

  useEffect(() => {
    const fetchManagers = async () => {
      try {
        const response = await axiosInstance.get(
          `${process.env.NEXT_PUBLIC_GATEWAY_API}/api/user/accountsagency?agencyId=${agencyId}`
        );

        const accountsList = response.data.map((account: any) => ({
          id: account.id,
          name: `${account.user.firstName} ${account.user.lastName}`,
          avatarUrl: account.user.picture || '/assets/images/avatars/avatar_default.jpg',
          email: account.user.email
        }));

        setManagers(accountsList);
      } catch (error) {
        console.error('Error fetching accounts:', error);
        enqueueSnackbar('Failed to fetch accounts', { variant: 'error' });
      }
    };

    fetchManagers();
  }, [agencyId]);

  //----------------integration----------------

  //-------------------------------------------
  const onUpdateTask = (updatedTask: ITaskItem) => {
    setTableData((prevTasks) =>
      prevTasks.map((task) => (task.id === updatedTask.id ? updatedTask : task))
    );
  };
  //-------------------------------------------

  const dataFiltered = applyFilter({
    inputData: tableData,
    comparator: getComparator(table.order, table.orderBy),
    filters,
    sortBy,
    dateError,
  });

  const dataInPage = dataFiltered.slice(
    table.page * table.rowsPerPage,
    table.page * table.rowsPerPage + table.rowsPerPage
  );

  const denseHeight = table.dense ? 56 : 56 + 20;

  const canReset =
    !!filters.name ||
    filters.column.name !== "all" ||
    !!filters.type.length ||
    !!filters.manager.length ||
    (!!filters.startDate && !!filters.endDate);

  const notFound = (!dataFiltered.length && canReset) || !dataFiltered.length;
  const getTaskLength = (status: string) =>
    Array.isArray(tableData)
      ? tableData.filter((item) => item.status === status).length
      : 0;

  const TABS = [
    { value: "all", label: "All", color: "default", count: tableData.length },
    {
      value: "TO DO",
      label: "To Do",
      color: "error",
      count: getTaskLength("TO DO"),
    },
    {
      value: "IN PROGRESS",
      label: "In Progress",
      color: "warning",
      count: getTaskLength("IN PROGRESS"),
    },
    {
      value: "DONE",
      label: "Done",
      color: "success",
      count: getTaskLength("DONE"),
    },
  ] as const;

  const handleFilters = useCallback(
    (name: string, value: ITaskTableFilterValue) => {
      table.onResetPage();
      setFilters((prevState) => ({
        ...prevState,
        [name]: value,
      }));
    },
    [table]
  );

  const handleResetFilters = useCallback(() => {
    setFilters(defaultFilters);
  }, []);
  //----------------------------------------------------------------------------------
  const handleSortBy = useCallback((newValue: string) => {
    setSortBy(newValue);
  }, []);

  const handleSearch = useCallback(
    (inputValue: string) => {
      setSearch((prevState) => ({
        ...prevState,
        query: inputValue,
      }));

      if (inputValue) {
        const results = tableData.filter(
          (task: any) =>
            task.name.toLowerCase().indexOf(search.query.toLowerCase()) !== -1
        );

        setSearch((prevState) => ({
          ...prevState,
          results,
        }));
      }
    },
    [search.query]
  );
  //-----------------------------Delete--------------------------------------------------

  const handleDeleteRow = useCallback(
    async (id: number) => {
      try {
        const response = await deleteTask(id);

        if (response.code === 200) {
          const updatedTableData = tableData.filter((row) => row.id !== id);
          setTableData(updatedTableData);

          confirm.onFalse();
          enqueueSnackbar("task deleted successfully", { variant: "success" });
        } else {
          enqueueSnackbar("Failed to delete task", { variant: "error" });
        }
      } catch (error) {
        console.error("An error occurred:", error);
        enqueueSnackbar("An error occurred. Please try again later.", {
          variant: "error",
        });
      }
    },
    [tableData, table, enqueueSnackbar]
  );

  const handleDeleteRows = useCallback(async () => {
    try {
      const response = await deleteListTask(
        table.selected.map((id) => Number(id))
      );
      const deleteRows = tableData.filter(
        (row) => !table.selected.includes(row.id.toString())
      );

      setTableData(deleteRows);

      table.onUpdatePageDeleteRows({
        totalRowsInPage: dataInPage.length,
        totalRowsFiltered: dataFiltered.length,
      });
      enqueueSnackbar("tasks deleted successfully", { variant: "success" });
    } catch (error) {
      enqueueSnackbar("delete tasks Error", { variant: "error" });
    }
  }, [
    dataFiltered.length,
    dataInPage.length,
    enqueueSnackbar,
    table,
    tableData,
  ]);
  //------------------Archive-------------------------

  const handleArchiveRow = useCallback(
    async (id: number) => {
      try {
        const response = await archiveTask(id);
        const updatedTableData = tableData.filter((row) => row.id !== id);
        setTableData(updatedTableData);

        if (response.code === 200) {
          enqueueSnackbar("Task archived successfully", { variant: "success" });
        } else {
          enqueueSnackbar("Failed to archive task", { variant: "error" });
        }
      } catch (error) {
        console.error("An error occurred:", error);
        enqueueSnackbar("An error occurred. Please try again later.", {
          variant: "error",
        });
      }
    },
    [tableData, table, enqueueSnackbar]
  );

  const handleArchiveRows = useCallback(async () => {
    try {
      const response = await archiveListTask(
        table.selected.map((id) => Number(id))
      );
      const archiveRows = tableData.filter(
        (row) => !table.selected.includes(row.id.toString())
      );

      setTableData(archiveRows);

      table.onUpdatePageDeleteRows({
        totalRowsInPage: dataInPage.length,
        totalRowsFiltered: dataFiltered.length,
      });
      enqueueSnackbar("Tasks archived successfully", { variant: "success" });
    } catch (error) {
      enqueueSnackbar("archive tasks Error", { variant: "error" });
    }
  }, [
    dataFiltered.length,
    dataInPage.length,
    enqueueSnackbar,
    table,
    tableData,
  ]);

  //---------------------------------------------------------

  const handleFilterStatus = useCallback(
    (event: React.SyntheticEvent, newValue: string) => {
      handleFilters("column", {
        id: 0,
        name: newValue,
        orderIndex: 0,
        tasks: []
      });
    },
    [handleFilters]
  );

  //----------------view details--------------

  const renderFilters = (
    <Stack
      spacing={3}
      justifyContent="space-between"
      alignItems={{ xs: "flex-end", sm: "center" }}
      direction={{ xs: "column", sm: "row" }}
    >
      <TaskSearch
        query={search.query}
        results={search.results}
        onSearch={handleSearch}
        hrefItem={(id: string) => paths.dashboard.tasks.details(id)}
      />

      <Stack direction="row" spacing={1} flexShrink={0}>
        <TaskFilters
          open={openFilters.value}
          onOpen={openFilters.onTrue}
          onClose={openFilters.onFalse}
          filters={filters}
          onFilters={handleFilters}
          canReset={canReset}
          onResetFilters={handleResetFilters}
          managerOptions={managers}
          typeOptions={TASK_TYPE_OPTIONS.map((option) => option.label)}
          dateError={dateError}
        />

        <TaskSort
          sort={sortBy}
          onSort={handleSortBy}
          sortOptions={TASK_SORT_OPTIONS}
        />
      </Stack>
      <Button
        component={RouterLink}
        href={paths.dashboard.tasks.add_task}
        variant="contained"
        startIcon={<Iconify icon="mingcute:add-line" />}
        sx={{
          backgroundColor: '#144dd5',
          '&:hover': {
            backgroundColor: '#144dd5',
          },
          width: '19.2%',
          height: '100%',
          textTransform: 'none',
        }}
      >
        New Task
      </Button>
    </Stack>
  );

  const renderResults = (
    <TaskFiltersResult
      filters={filters}
      onResetFilters={handleResetFilters}
      canReset={canReset}
      onFilters={handleFilters}
      results={dataFiltered.length}
    />
  );

  return (
    <>
      <LocalizationProvider>
        <Stack
          spacing={2.5}
          sx={{
            mb: { xs: 3, md: 5 },
          }}
        >
          {renderFilters}
          {canReset && renderResults}
        </Stack>

        <Card>
          <Tabs
            value={filters.column.name}
            onChange={handleFilterStatus}
            sx={{
              px: 2.5,
              boxShadow: `inset 0 -2px 0 0 ${alpha(
                theme.palette.grey[500],
                0.08
              )}`,
            }}
          >
            {TABS.map((tab) => (
              <Tab
                key={tab.value}
                value={tab.value}
                label={tab.label}
                iconPosition="end"
                icon={
                  <Label
                    variant={
                      ((tab.value === "all" ||
                        tab.value === filters.column.name) &&
                        "filled") ||
                      "soft"
                    }
                    color={tab.color}
                  >
                    {tab.count}
                  </Label>
                }
              />
            ))}
          </Tabs>

          <TableContainer sx={{ position: "relative", overflow: "unset" }}>
            <TableSelectedAction
              dense={table.dense}
              numSelected={table.selected.length}
              rowCount={dataFiltered.length}
              onSelectAllRows={(checked) => {
                table.onSelectAllRows(
                  checked,
                  dataFiltered.map((row) => row.id.toString())
                );
              }}
              action={
                <Stack direction="row">
                  <Tooltip title="Archive">
                    <IconButton
                      color="primary"
                      onClick={() => {
                        confirmArchive.onTrue();
                      }}
                    >
                      <Iconify icon="clarity:archive-solid" />
                    </IconButton>
                  </Tooltip>

                  <Tooltip title="Delete">
                    <IconButton color="primary" onClick={confirm.onTrue}>
                      <Iconify icon="solar:trash-bin-trash-bold" />
                    </IconButton>
                  </Tooltip>
                </Stack>
              }
            />

            <Scrollbar>
              <Table
                size={table.dense ? "small" : "medium"}
                sx={{ minWidth: 800 }}
              >
                <TableHeadCustom
                  order={table.order}
                  orderBy={table.orderBy}
                  headLabel={TABLE_HEAD}
                  rowCount={dataFiltered.length}
                  numSelected={table.selected.length}
                  onSort={table.onSort}
                  onSelectAllRows={(checked) =>
                    table.onSelectAllRows(
                      checked,
                      dataFiltered.map((row) => row.id.toString())
                    )
                  }
                />

                <TableBody>
                  {dataFiltered
                    .slice(
                      table.page * table.rowsPerPage,
                      table.page * table.rowsPerPage + table.rowsPerPage
                    )
                    .map((row) => {
                      return (
                        <TaskTableRow
                          key={row.id}
                          row={row}
                          selected={table.selected.includes(row.id.toString())}
                          onSelectRow={() => table.onSelectRow(row.id.toString())}
                          onDeleteRow={() => handleDeleteRow(row.id)}
                          onArchiveRow={() => handleArchiveRow(row.id)}
                          onUpdateTask={onUpdateTask}
                        />
                      );
                    })}

                  <TableEmptyRows
                    height={denseHeight}
                    emptyRows={emptyRows(
                      table.page,
                      table.rowsPerPage,
                      dataFiltered.length
                    )}
                  />

                  <TableNoData notFound={notFound} />
                </TableBody>
              </Table>
            </Scrollbar>
          </TableContainer>

          <TablePaginationCustom
            count={dataFiltered.length}
            page={table.page}
            rowsPerPage={table.rowsPerPage}
            onPageChange={table.onChangePage}
            onRowsPerPageChange={table.onChangeRowsPerPage}
            dense={table.dense}
            onChangeDense={table.onChangeDense}
          />
        </Card>

        {/* </Container> */}

        <ConfirmDialog
          open={confirm.value}
          onClose={confirm.onFalse}
          title="Delete"
          content={
            <>
              Are you sure want to delete{" "}
              <strong> {table.selected.length} </strong> items?
            </>
          }
          action={
            <Button
              variant="contained"
              color="error"
              onClick={() => {
                handleDeleteRows();
                confirm.onFalse();
              }}
            >
              Delete
            </Button>
          }
        />
        <ConfirmDialog
          open={confirmArchive.value}
          onClose={confirmArchive.onFalse}
          title="Archive"
          content={
            <>
              Are you sure want to archive
              <strong> {table.selected.length} </strong> items?
            </>
          }
          action={
            <Button
              variant="contained"
              color="error"
              onClick={() => {
                handleArchiveRows();
                confirmArchive.onFalse();
              }}
            >
              Archive
            </Button>
          }
        />
      </LocalizationProvider>
    </>
  );
}

// ----------------------------------------------------------------------

function applyFilter({
  inputData,
  comparator,
  filters,
  sortBy,
  dateError,
}: {
  inputData: ITaskItem[];
  comparator: (a: any, b: any) => number;
  filters: ITaskTableFilters;
  sortBy: string;
  dateError: boolean;
}) {
  const { name, type, manager, column, startDate, endDate } = filters;
  let filteredData = [...inputData];

  // Filter by status
  if (column?.name && column.name !== "all") {
    filteredData = filteredData.filter(
      (task) => task.status === column.name
    );
  }

  // Apply sorting first
  if (comparator) {
    filteredData.sort(comparator);
  }

  // Filter by task name
  if (name) {
    filteredData = filteredData.filter((task) =>
      task.name.toLowerCase().includes(name.toLowerCase())
    );
  }

  // Filter by date range
  if (!dateError) {
    if (startDate && endDate) {
      filteredData = filteredData.filter((task) => {
        const taskStart = new Date(task.startDate);
        const taskEnd = new Date(task.endDate);
        return taskStart >= new Date(startDate) && taskEnd <= new Date(endDate);
      });
    } else if (startDate) {
      filteredData = filteredData.filter(
        (task) => new Date(task.startDate) >= new Date(startDate)
      );
    } else if (endDate) {
      filteredData = filteredData.filter(
        (task) => new Date(task.endDate) <= new Date(endDate)
      );
    }
  }

  // Filter by task type
  if (type.length) {
    filteredData = filteredData.filter(
      (task) => type.includes(task.type.toLowerCase().trim())
    );
  }

  // Filter by manager
  if (manager && manager.length > 0) {
    filteredData = filteredData.filter((task) =>
      manager.some((selectedManager) => selectedManager.id === task.managerId)
    );
  }

  return filteredData;
}
