"use client";

import { DoResult } from "@/app/api/do";
import { DoSearchAll, fetchDoSearch, releaseDo } from "@/app/api/do/actions";
import { useRouter } from "next/navigation";
import React, { ForwardedRef, useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { Criterion } from "../SearchBox";
import { isEmpty, sortBy, uniqBy, upperFirst } from "lodash";
import { arrayToDateString, arrayToDayjs } from "@/app/utils/formatUtil";
import SearchBox from "../SearchBox/SearchBox";
import { EditNote } from "@mui/icons-material";
import InputDataGrid from "../InputDataGrid";
import { CreateConsoDoInput } from "@/app/api/do/actions";
import { TableRow } from "../InputDataGrid/InputDataGrid";
import {
  FooterPropsOverrides,
  GridColDef,
  GridRowModel,
  GridToolbarContainer,
  useGridApiRef,
} from "@mui/x-data-grid";
import {
  FormProvider,
  SubmitErrorHandler,
  SubmitHandler,
  useForm,
} from "react-hook-form"; 
import { Box, Button, Grid, Stack, Typography, TablePagination } from "@mui/material";
import StyledDataGrid from "../StyledDataGrid";
import { GridRowSelectionModel } from "@mui/x-data-grid";
import Swal from "sweetalert2";

type Props = {
  filterArgs?: Record<string, any>;
  searchQuery?: Record<string, any>;
  onDeliveryOrderSearch: () => void;
};
type SearchBoxInputs = Record<"code" | "status" | "estimatedArrivalDate" | "orderDate" | "supplierName" | "shopName" | "deliveryOrderLines" | "codeTo" | "statusTo" | "estimatedArrivalDateTo" | "orderDateTo" | "supplierNameTo" | "shopNameTo" | "deliveryOrderLinesTo" , string>;
type SearchParamNames = keyof SearchBoxInputs;

// put all this into a new component
// ConsoDoForm
type EntryError =
  | {
      [field in keyof DoResult]?: string;
    }
  | undefined;
type DoRow = TableRow<Partial<DoResult>, EntryError>;


const DoSearch: React.FC<Props> = ({filterArgs, searchQuery, onDeliveryOrderSearch}) => {
  const apiRef = useGridApiRef();

  const formProps = useForm<CreateConsoDoInput>({
    defaultValues: {},
  });
  const errors = formProps.formState.errors;

  
  const { t } = useTranslation("do");
  const router = useRouter();
  const [rowSelectionModel, setRowSelectionModel] =
    useState<GridRowSelectionModel>([]);

  const [searchAllDos, setSearchAllDos] = useState<DoSearchAll[]>([]);

  const [pagingController, setPagingController] = useState({
    pageNum: 1,
    pageSize: 10,
  });

  const handlePageChange = useCallback((event: unknown, newPage: number) => {
    const newPagingController = {
      ...pagingController,
      pageNum: newPage + 1,
    };
    setPagingController(newPagingController);
  },[pagingController]);

  const handlePageSizeChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
    const newPageSize = parseInt(event.target.value, 10);
    const newPagingController = {
      pageNum: 1,
      pageSize: newPageSize,
    };
    setPagingController(newPagingController);
  }, []);

  const pagedRows = useMemo(() => {
  const start = (pagingController.pageNum - 1) * pagingController.pageSize;
  return searchAllDos.slice(start, start + pagingController.pageSize);
  }, [searchAllDos, pagingController]);

  const [currentSearchParams, setCurrentSearchParams] = useState<SearchBoxInputs>({
    code: "",
    status: "",
    estimatedArrivalDate: "",
    orderDate: "",
    supplierName: "",
    shopName: "",
    deliveryOrderLines: "",
    codeTo: "",
    statusTo: "",
    estimatedArrivalDateTo: "",
    orderDateTo: "",
    supplierNameTo: "",
    shopNameTo: "",
    deliveryOrderLinesTo: ""
  });

  const [hasSearched, setHasSearched] = useState(false);
  const [hasResults, setHasResults] = useState(false);

  useEffect(() =>{
    setPagingController(p => ({
      ...p,
      pageNum: 1,
    }));
  }, [searchAllDos]);


  //INITIALIZATION
  useEffect(() => {
    const loadItems = async () => {
      try{
        //const itemsData = await fetchDoSearch("","","","","","","");
        //setSearchAllDos(itemsData);
      }
      catch (error){
        console.error("Loading Error: ", error);
        setSearchAllDos([]);
      };
    };
    loadItems();
    console.log("success");
  },[]);


  const searchCriteria: Criterion<SearchParamNames>[] = useMemo(
    () => [
      { label: t("Code"), paramName: "code", type: "text" },

      {
        label: t("Order Date From"),
        label2: t("Order Date To"),
        paramName: "orderDate",
        type: "dateRange",
      },
      { label: t("Shop Name"), paramName: "shopName", type: "text" },

      {
        label: t("Estimated Arrival From"),
        label2: t("Estimated Arrival To"),
        paramName: "estimatedArrivalDate",
        type: "dateRange",
      },

      {
        label: t("Status"),
        paramName: "status",
        type: "autocomplete",
        options:[
          {label: t('Pending'), value: 'pending'},
          {label: t('Receiving'), value: 'receiving'},
          {label: t('Completed'), value: 'completed'}
        ]
      }
    ],
    [t],
  );

  const onReset = useCallback(async () => {
    try {
      //const data = await fetchDoSearch("", "", "", "", "","","");
      //setSearchAllDos(data);
      setHasSearched(false);
      setHasSearched(false);
    } 
    catch (error) {
      console.error("Error: ", error);
      setSearchAllDos([]);
  }
  }, []);

  const onDetailClick = useCallback(
    (doResult: DoResult) => {
      router.push(`/do/edit?id=${doResult.id}`);
    },
    [router],
  );

  const validationTest = useCallback(
    (
      newRow: GridRowModel<DoRow>,
      //   rowModel: GridRowSelectionModel
    ): EntryError => {
      const error: EntryError = {};
      console.log(newRow);
      //   if (!newRow.lowerLimit) {
      //     error["lowerLimit"] = "lower limit cannot be null"
      //   }
      //   if (newRow.lowerLimit && newRow.upperLimit && newRow.lowerLimit > newRow.upperLimit) {
      //     error["lowerLimit"] = "lower limit should not be greater than upper limit"
      //     error["upperLimit"] = "lower limit should not be greater than upper limit"
      //   }
      return Object.keys(error).length > 0 ? error : undefined;
    },
    [],
  );

  const columns = useMemo<GridColDef[]>(
    () => [
      // {
      //     name: "id",
      //     label: t("Details"),
      //     onClick: onDetailClick,
      //     buttonIcon: <EditNote />,
      // },
      {
        field: "id",
        headerName: t("Details"),
        width: 100,
        renderCell: (params) => (
          <Button
            variant="outlined"
            size="small"
            startIcon={<EditNote />}
            onClick={() => onDetailClick(params.row)}
          >
            {t("Details")}
          </Button>
        ),
      },
      {
        field: "code",
        headerName: t("code"),
        flex: 1.5,
      },
      {
        field: "shopName",
        headerName: t("Shop Name"),
        flex: 1,
      },
      {
        field: "supplierName",
        headerName: t("Supplier Name"),
        flex: 1,
      },
      {
        field: "orderDate",
        headerName: t("Order Date"),
        flex: 1,
        renderCell: (params) => {
          return params.row.orderDate
            ? arrayToDateString(params.row.orderDate)
            : "N/A";
        },
      },
      {
        field: "estimatedArrivalDate",
        headerName: t("Estimated Arrival"),
        flex: 1,
        renderCell: (params) => {
          return params.row.estimatedArrivalDate
            ? arrayToDateString(params.row.estimatedArrivalDate)
            : "N/A";
        },
      },
      {
        field: "status",
        headerName: t("Status"),
        flex: 1,
        renderCell: (params) => {
          return t(upperFirst(params.row.status));
        },
      },
    ],
    [t, arrayToDateString],
  );

  const onSubmit = useCallback<SubmitHandler<CreateConsoDoInput>>(
    async (data, event) => {
      const hasErrors = false;
      console.log(errors);
    },
    [],
  );
  const onSubmitError = useCallback<SubmitErrorHandler<CreateConsoDoInput>>(
    (errors) => {},
    [],
  );
  //SEARCH FUNCTION
  const handleSearch = useCallback(async (query: SearchBoxInputs) => {
    try {

      setCurrentSearchParams(query);

      let orderStartDate = query.orderDate;
      let orderEndDate = query.orderDateTo;
      let estArrStartDate = query.estimatedArrivalDate;
      let estArrEndDate = query.estimatedArrivalDateTo;
      const time = "T00:00:00";

      if(orderStartDate != ""){
        orderStartDate = query.orderDate + time;
      }
      if(orderEndDate != ""){
        orderEndDate = query.orderDateTo + time;
      }
      if(estArrStartDate != ""){
        estArrStartDate = query.estimatedArrivalDate + time;
      }
      if(estArrEndDate != ""){
        estArrEndDate = query.estimatedArrivalDateTo + time;
      }
      
      let status = "";
      if(query.status == "All"){
        status = "";
      }
      else{
        status = query.status;
      }
      
      const data = await fetchDoSearch(
        query.code || "",
        query.shopName || "",
        status,
        orderStartDate,
        orderEndDate,
        estArrStartDate,
        estArrEndDate
      );

      setSearchAllDos(data);
      setHasSearched(true);
      setHasResults(data.length > 0);
    } catch (error) {
      console.error("Error: ", error);
    }
  }, []);

  const handleBatchRelease = useCallback(async () => {
    const query = currentSearchParams;

    let orderStartDate = query.orderDate;
    let orderEndDate = query.orderDateTo;
    let estArrStartDate = query.estimatedArrivalDate;
    let estArrEndDate = query.estimatedArrivalDateTo;
    const time = "T00:00:00";

if(orderStartDate != ""){
      orderStartDate = query.orderDate + time;
    }
    if(orderEndDate != ""){
      orderEndDate = query.orderDateTo + time;
    }
    if(estArrStartDate != ""){
      estArrStartDate = query.estimatedArrivalDate + time;
    }
    if(estArrEndDate != ""){
      estArrEndDate = query.estimatedArrivalDateTo + time;
    }
    
    let status = "";
    if(query.status == "All"){
      status = "";
    }
    else{
      status = query.status;
    }

    const batchReleaseData = await fetchDoSearch(
      query.code || "",
      query.shopName || "",
      status,
      orderStartDate,
      orderEndDate,
      estArrStartDate,
      estArrEndDate
    );

    const extractedIds = batchReleaseData.map(item => item.id);
    const extractedIdsCount = batchReleaseData.map(item => item.id).length;
    const extractedItemsCount = batchReleaseData.flatMap(item => item.deliveryOrderLines).length;

    console.log("Batch Release Data:", batchReleaseData);
    console.log("Query:", query);
    console.log("IDs: " + extractedIds);
    console.log("Total Shops: " + extractedIdsCount);
    console.log("Total Items: " + extractedItemsCount);

    const result = await Swal.fire(
      {
        icon: "info",
        title: t("Batch Release"),
        html: t("Selected Shop(s): ") + extractedIdsCount.toString() + `</p>`+
        t("Selected Item(s): ") + extractedItemsCount.toString() + `</p>`,
        showCancelButton: true,
        confirmButtonText: t("Confirm"),
        cancelButtonText: t("Cancel"),
        confirmButtonColor: "#638a01",
        cancelButtonColor: "#d33"
      });
      if (result.isConfirmed) {
        Swal.fire({
          title: t("Releasing"),
          text: t("Please wait"),
          allowOutsideClick: false,
          allowEscapeKey: false,
          showConfirmButton: false,
          didOpen: () => {
            Swal.showLoading();
          }
        });
        
        await Promise.all(extractedIds.map((id) => releaseDo({ id: id })));

        Swal.fire({
          position: "bottom-end",
          icon: "success",
          text: t("Batch release completed successfully."),
          showConfirmButton: false,
          timer: 1500
        });
      }


  }, [currentSearchParams]);


  return (
    <>
      <FormProvider {...formProps}>
        <Stack
          spacing={2}
          component="form"
          onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)}
        >
          <Grid container>
            <Grid item xs={8}>
              <Typography variant="h4" marginInlineEnd={2}>
                {t("Delivery Order")}
              </Typography>
            </Grid>
            <Grid
              item
              xs={4}
              display="flex"
              justifyContent="end"
              alignItems="end"
            >
            <Stack spacing={2} direction="row">
              {/*<Button
                name="submit"
                variant="contained"
                //   startIcon={<Check />}
                type="submit"
              >
                {t("Create")}
              </Button>*/}
              {hasSearched && hasResults && (
                <Button
                  name="batch_release"
                  variant="contained"
                  onClick={handleBatchRelease}
                >
                  {t("Batch Release")}
                </Button>
              )}

            </Stack>
              
            </Grid>
          </Grid>

          <SearchBox
            criteria={searchCriteria}

            onSearch={handleSearch}

            onReset={onReset}
          />

          <StyledDataGrid
            rows={pagedRows}
            columns={columns}
            checkboxSelection
            rowSelectionModel={rowSelectionModel}
            onRowSelectionModelChange={(newRowSelectionModel) => {
              setRowSelectionModel(newRowSelectionModel);
              formProps.setValue("ids", newRowSelectionModel);
            }}
            slots={{
              footer: FooterToolbar,
              noRowsOverlay: NoRowsOverlay,
            }}
          />
          
          <TablePagination
          component="div"
          count={searchAllDos.length}
          page={(pagingController.pageNum - 1)}
          rowsPerPage={pagingController.pageSize}
          onPageChange={handlePageChange}
          onRowsPerPageChange={handlePageSizeChange}
          rowsPerPageOptions={[10, 25, 50]}
        />

        </Stack>

      </FormProvider>
    </>
  );
};


const FooterToolbar: React.FC<FooterPropsOverrides> = ({ child }) => {
  return <GridToolbarContainer sx={{ p: 2 }}>{child}</GridToolbarContainer>;
};
const NoRowsOverlay: React.FC = () => {
  const { t } = useTranslation("home");
  return (
    <Box
      display="flex"
      justifyContent="center"
      alignItems="center"
      height="100%"
    >
      <Typography variant="caption">{t("Add some entries!")}</Typography>
    </Box>
  );
};

export default DoSearch;
