"use client";

import { DoResult } from "@/app/api/do";
import { DoSearchAll, fetchDoSearch, releaseDo ,startBatchReleaseAsync, getBatchReleaseProgress} 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";
import { useSession } from "next-auth/react";
import { SessionWithTokens } from "@/config/authConfig";
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 { data: session } = useSession() as { data: SessionWithTokens | null };
  const currentUserId = session?.id ? parseInt(session.id) : undefined;
  console.log("🔍 DoSearch - session:", session);
console.log("🔍 DoSearch - currentUserId:", currentUserId);
  const [searchTimeout, setSearchTimeout] = useState<NodeJS.Timeout | null>(null);
  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 debouncedSearch = useCallback((query: SearchBoxInputs) => {
    if (searchTimeout) {
      clearTimeout(searchTimeout);
    }
    
    const timeout = setTimeout(() => {
      handleSearch(query);
    }, 300);
    
    setSearchTimeout(timeout);
  }, [handleSearch, searchTimeout]);
  const handleBatchRelease = useCallback(async () => {
    const selectedIds = rowSelectionModel as number[];
    if (!selectedIds.length) return;
  
    console.log("🔍 handleBatchRelease - currentUserId:", currentUserId);
    console.log("🔍 handleBatchRelease - selectedIds:", selectedIds);
  
    const result = await Swal.fire({
      icon: "question",
      title: t("Batch Release"),
      html: `
        <div>
          <p>${t("Selected items on current page")}: ${selectedIds.length}</p>
          <p>${t("Total search results")}: ${searchAllDos.length}</p>
          <hr>
          <p><strong>${t("Choose release option")}:</strong></p>
        </div>
      `,
      showCancelButton: true,
      confirmButtonText: t("Release All Search Results"),
      cancelButtonText: t("Release Selected Only"),
      denyButtonText: t("Cancel"),
      showDenyButton: true,
      confirmButtonColor: "#8dba00",
      cancelButtonColor: "#2196f3",
      denyButtonColor: "#F04438"
    });
  
    if (result.isDenied) return;
  
    let idsToRelease: number[];
    if (result.isConfirmed) {
      idsToRelease = searchAllDos.map(d => d.id);
    } else {
      idsToRelease = selectedIds;
    }
  
    try {
      const startRes = await startBatchReleaseAsync({ ids: idsToRelease, userId: currentUserId ?? 1 });
      const jobId = startRes?.entity?.jobId;
  
      if (!jobId) {
        await Swal.fire({ icon: "error", title: t("Error"), text: t("Failed to start batch release") });
        return;
      }
  
      await Swal.fire({
        title: t("Releasing"),
        html: `
          <div style="text-align:left">
            <div id="br-total">${t("Total")}: 0</div>
            <div id="br-finished">${t("Finished")}: 0</div>
            <div style="margin-top:8px;height:8px;background:#eee;border-radius:4px;">
              <div id="br-bar" style="height:8px;width:0%;background:#8dba00;border-radius:4px;"></div>
            </div>
          </div>
        `,
        allowOutsideClick: false,
        allowEscapeKey: false,
        showConfirmButton: false,
        didOpen: async () => {
          const update = (total:number, finished:number, success:number, failed:number) => {
            const bar = document.getElementById("br-bar") as HTMLElement;
            const pct = total > 0 ? Math.floor((finished / total) * 100) : 0;
            (document.getElementById("br-total") as HTMLElement).innerText = `${t("Total")}: ${total}`;
            (document.getElementById("br-finished") as HTMLElement).innerText = `${t("Finished")}: ${finished}`;
            
            if (bar) bar.style.width = `${pct}%`;
          };
  
          const timer = setInterval(async () => {
            try {
              const p = await getBatchReleaseProgress(jobId);
              const e = p?.entity || {};
              update(e.total ?? 0, e.finished ?? 0, e.success ?? 0, e.failedCount ?? 0);
  
              if (p.code === "FINISHED" || e.running === false) {
                clearInterval(timer);
                Swal.close();
              
                // 简化完成提示 - 只显示完成，不显示成功/失败统计
                await Swal.fire({
                  icon: "success",
                  title: t("Completed"),
                  text: t("Batch release completed"),
                  confirmButtonText: t("OK")
                });
              
                if (currentSearchParams && Object.keys(currentSearchParams).length > 0) {
                  await handleSearch(currentSearchParams);
                }
                setRowSelectionModel([]);
              }
            } catch (err) {
              console.error("progress poll error:", err);
            }
          }, 800);
        }
      });
    } catch (error) {
      console.error("Batch release error:", error);
      await Swal.fire({
        icon: "error",
        title: t("Error"),
        text: t("An error occurred during batch release"),
        confirmButtonText: t("OK")
      });
    }
  }, [rowSelectionModel, t, currentUserId, searchAllDos, currentSearchParams, handleSearch]);


  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;
