import * as React from "react";
import Box, { BoxProps } from "@mui/material/Box";
import TextField from "@mui/material/TextField";
import EditIcon from "@mui/icons-material/Edit";
import Grid from "@mui/material/Unstable_Grid2"; // Grid version 2
import Typography from "@mui/material/Typography";
import Stack from "@mui/material/Stack";
import MenuItem from "@mui/material/MenuItem";
import Select from "@mui/material/Select";
import { useRecoilValue } from "recoil";
import { useSnackbar } from "notistack";
import CircleIcon from "@mui/icons-material/Circle";
import Chip from "@mui/material/Chip";
import SearchIcon from "@mui/icons-material/Search";

import { selectProductList } from "@/utils/mysqlCompatible";
import { sessionState } from "@/recoil/atoms";
import { useInitCRUD } from "@/utils/hook";
import type { SQLResult as SQLResultType } from "@/pages/api/sql/run";

import {
  ActionTemplate,
  ResultPreviewTemplate,
  TextFieldWrapper,
} from "@/components/Sections/MysqlCompatible/Content/Create";

const SQL_CONTENT = `SELECT 
  product_id, 
  product_name, 
  price 
FROM 
  products p 
WHERE 
  price \${sign} \${price} 
ORDER BY 
  \${order}
LIMIT 
  \${limit};`;

export default function SelectContent() {
  const [sql, setSql] = React.useState(SQL_CONTENT);
  const [sign, setSign] = React.useState(">");
  const [price, setPrice] = React.useState<number | null>(20);
  const [order, setOrder] = React.useState("price");
  const [limit, setLimit] = React.useState(10);
  const [priceError, setPriceError] = React.useState<string | null>(null);
  const [result, setResult] = React.useState<SQLResultType | null>(null);
  const [submitting, setSubmitting] = React.useState(false);

  const { enqueueSnackbar } = useSnackbar();
  const session = useRecoilValue(sessionState);
  const [isInitCRUD] = useInitCRUD((error) => {
    enqueueSnackbar(`Error[init simple CRUD]: ${error?.message}`, {
      variant: "error",
    });
    // setGlobalLoading(false);
  }, !!session);

  React.useEffect(() => {
    const newSql = SQL_CONTENT.replace(/\${sign}/g, sign)
      .replace(/\${price}/g, price?.toString() || "")
      .replace(/\${order}/g, order)
      .replace(/\${limit}/g, limit.toString());
    setSql(newSql);
  }, [sign, price, order, limit]);

  const handleEditPrice = (event: React.ChangeEvent<HTMLInputElement>) => {
    const value = event.target.value.trim();
    if (value.length === 0) {
      setPriceError("Price cannot be empty");
      setPrice(null);
    } else {
      const price = Number(value);
      if (isNaN(price)) {
        setPriceError("Price must be a number");
        setPrice(null);
      } else if (price <= 0 || price > 1000000) {
        setPriceError("Price must be a positive number");
        setPrice(null);
      } else {
        setPriceError(null);
        setPrice(price);
      }
    }
  };

  const handleSubmmit = async () => {
    if (!price) {
      setPriceError("Price cannot be empty");
      return;
    }
    setSubmitting(true);
    setResult(null);
    try {
      const result = await selectProductList({
        operator: sign,
        price: `${price}`,
        sortBy: order,
        pageSize: `${limit}`,
      });
      setResult(result);
    } catch (error: any) {
      console.error(error);
      enqueueSnackbar(`Error[run SQL]: ${error?.message}`, {
        variant: "error",
      });
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <>
      <ActionTemplate
        inputTitle="Search products with options:"
        sqlContent={sql}
        handleSubmmit={handleSubmmit}
        disableSubbmit={!!priceError || !isInitCRUD}
        submitting={!isInitCRUD || submitting}
        submitBtnLabel={!isInitCRUD ? "Init sample data" : "Run SQL and Search"}
        result={
          result?.rows?.length
            ? `OK, affects ${result?.rows?.length} row (s).`
            : null
        }
      >
        <TextFieldWrapper title="Price" titleSx={{ width: 200 }}>
          <Select
            size="small"
            id="sign"
            value={sign}
            onChange={(event) => {
              const value = event.target.value;
              setSign(value as string);
            }}
            sx={{
              mr: 1,
            }}
          >
            <MenuItem value=">">{`>`}</MenuItem>
            <MenuItem value="<">{`<`}</MenuItem>
          </Select>
          <TextField
            id="price"
            size="small"
            InputProps={{
              endAdornment: (
                <EditIcon
                  sx={{
                    color: "rgba(168, 177, 193, 0.3)",
                  }}
                />
              ),
            }}
            defaultValue={price}
            onChange={handleEditPrice}
            error={!!priceError}
            helperText={priceError}
          />
        </TextFieldWrapper>
        <TextFieldWrapper title="Sort by" titleSx={{ width: 200 }}>
          <Select
            size="small"
            id="sign"
            value={order}
            onChange={(event) => {
              const value = event.target.value;
              setOrder(value as string);
            }}
            sx={{
              width: "304px",
            }}
          >
            <MenuItem value="price">Price(low - high)</MenuItem>
            <MenuItem value="price desc">Price(High - low)</MenuItem>
            <MenuItem value="product_name">Product Name(low - high)</MenuItem>
            <MenuItem value="product_name desc">
              Product Name(High - low)
            </MenuItem>
          </Select>
        </TextFieldWrapper>
        <TextFieldWrapper title="Products per page" titleSx={{ width: 200 }}>
          <Select
            size="small"
            id="sign"
            value={limit}
            onChange={(event) => {
              const value = event.target.value;
              setLimit(value as number);
            }}
            sx={{
              width: "304px",
            }}
          >
            <MenuItem value={1}>1</MenuItem>
            <MenuItem value={5}>5</MenuItem>
            <MenuItem value={10}>10</MenuItem>
            <MenuItem value={20}>20</MenuItem>
          </Select>
        </TextFieldWrapper>
      </ActionTemplate>

      <ResultPreviewTemplate>
        <BrowserStyleContainer
          price={price}
          sign={sign}
          order={order}
          limit={limit}
          items={
            result?.rows?.map((i) => ({
              id: i.productId,
              name: i.productName,
              price: i.price,
            })) || []
          }
        />
      </ResultPreviewTemplate>
    </>
  );
}

type ProductInfoType = {
  id: number;
  name: string;
  price: string;
};

export function BrowserStyleTemplate(props: {
  children: React.ReactNode;
  containerSx?: BoxProps["sx"];
}) {
  const { children, containerSx } = props;

  return (
    <>
      <Box
        height={28}
        sx={{
          width: "100%",
          backgroundColor: "#EAEEF4",
          borderRadius: "6px 6px 0px 0px",

          display: "flex",
          alignItems: "center",
          px: 1,
        }}
      >
        <Stack direction="row" spacing={0.5}>
          <CircleIcon
            sx={{
              width: 8,
              height: 8,
              fill: "#EA3523",
            }}
          />
          <CircleIcon
            sx={{
              width: 8,
              height: 8,
              fill: "#FFC702",
            }}
          />
          <CircleIcon
            sx={{
              width: 8,
              height: 8,
              fill: "#2ADD87",
            }}
          />
        </Stack>
      </Box>
      <Box
        sx={{
          width: "100%",
          backgroundColor: "#fff",
          p: 1,
          ...containerSx,
        }}
      >
        {children}
      </Box>
    </>
  );
}

function BrowserStyleContainer(props: {
  price?: number | string | null;
  sign?: string;
  order?: string;
  limit?: number;
  items?: ProductInfoType[];
}) {
  const { price, sign, order, limit, items } = props;

  return (
    <>
      <Box>
        <BrowserStyleTemplate>
          <Box
            sx={{
              border: "1px solid #E4E4E4",
              borderRadius: "24px",
              px: 1,
              py: 0.5,
              display: "flex",
              alignItems: "center",
              gap: 0.5,
            }}
          >
            <Typography
              component="div"
              fontWeight={500}
              fontSize={12}
              color="text.secondary"
            >
              Search results with
            </Typography>
            <Chip
              size="small"
              label={`Price: \$${price} - ${sign === ">" ? "Higher" : "Lower"}`}
            />
            <Chip size="small" label={`Sort: ${order}`} />
            <SearchIcon
              sx={{
                marginLeft: "auto",
              }}
            />
          </Box>

          <Grid container>
            {items?.map((item) => (
              <Grid xs={6} sm={6} md={4} key={item.id}>
                <ProductInfo id={item.id} name={item.name} price={item.price} />
              </Grid>
            ))}
            {items?.length === 0 && (
              <Grid xs={12} sm={12} md={12}>
                <Typography
                  component="div"
                  fontWeight={500}
                  fontSize={12}
                  color="text.secondary"
                  sx={{
                    textAlign: "center",
                    mt: 2,
                  }}
                >
                  There are no results that match the filter criteria.
                </Typography>
              </Grid>
            )}
          </Grid>
        </BrowserStyleTemplate>
      </Box>
    </>
  );
}

function ProductInfo(props: ProductInfoType) {
  const { id, name, price } = props;

  return (
    <Box>
      <Box
        borderRadius={6}
        width="100%"
        height="auto"
        minHeight={100}
        sx={{
          backgroundImage: `url(/img/mock-product.jpg)`,
          backgroundPosition: "center",
          backgroundSize: "cover",
          mb: 1,
        }}
      />
      <Typography fontWeight={600} fontSize={12} gutterBottom>
        {name || `<PRODUCT NAME>`}
      </Typography>
      <Typography
        fontWeight={600}
        fontSize={20}
        fontStyle="italic"
        color="#C22222"
        gutterBottom
      >
        ${price}
      </Typography>
    </Box>
  );
}
