import React, { useEffect, useReducer, useCallback, useRef } from "react";
import { createPortal } from "react-dom";
import { useOutletContext } from "react-router";
import {
  TreeSelector,
  type TreeItemWithUnknown,
} from "../../components/TreeSelector";
import { LoadMore } from "../../components/LoadMore";
import { orderByTypes } from "../../store/Types";
import { productReducer, initialState } from "../../store/product";
import * as actions from "../../store/product/action";
import {
  getCategoryTree,
  productList,
  productDetail,
  productDelete,
  productEdit,
  upload,
} from "../../api";
import {
  type Category,
  ProductOrderBys,
  type ProductOrderBysType,
  UploadScences,
} from "../../api/models";
import styles from "./index.module.css";

export function Component() {
  const [states, dispatch] = useReducer(productReducer, initialState);
  const asideContainer = useOutletContext<HTMLDivElement>();
  const keywordRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    async function getTree() {
      try {
        const resp = await getCategoryTree();
        if (resp.isSucced) {
          dispatch(actions.setCategories(resp.data || []));
        } else {
          throw Error(resp.message || "");
        }
      } finally {
        dispatch(actions.setLoading(false));
      }
    }

    getTree();
  }, []);

  function categoryChecked(item: TreeItemWithUnknown) {
    const category = item as Category;
    dispatch(actions.setCategory(category));
  }

  const search = useCallback(async () => {
    try {
      dispatch(actions.setIsSearch(true));

      const orderBys: ProductOrderBysType[] = [];
      if (
        !states.orderBys.createTime ||
        states.orderBys.createTime == orderByTypes.ASC
      )
        orderBys.push(ProductOrderBys.CreateTimeDesc);
      if (
        !states.orderBys.categoryId ||
        states.orderBys.categoryId == orderByTypes.ASC
      )
        orderBys.push(ProductOrderBys.Category);
      else orderBys.push(ProductOrderBys.CategoryDesc);
      if (
        !states.orderBys.createTime ||
        states.orderBys.createTime == orderByTypes.ASC
      )
        orderBys.push(ProductOrderBys.CreateTime);
      else orderBys.push(ProductOrderBys.CreateTimeDesc);

      const result = await productList({
        categoryId: states.categoryId,
        keyword: states.keyword,
        orderBys: orderBys,
        pageIndex: states.pageIndex,
        pageSize: states.pageSize,
      });
      if (result.isSucced) {
        dispatch(
          actions.setSearchResult({
            pageCount: result.data?.pageCount || 0,
            products: result.data?.data || [],
          }),
        );
      } else {
        alert(result.message || "服务器错误");
      }
    } finally {
      dispatch(actions.setIsSearch(false));
    }
  }, [
    states.categoryId,
    states.keyword,
    states.orderBys,
    states.pageIndex,
    states.pageSize,
  ]);

  useEffect(() => {
    search();
  }, [search]);

  async function onLoadMore() {
    dispatch(actions.setPageIndex(states.pageIndex + 1));
  }

  async function viewDetailClick(id: number) {
    try {
      const detailResult = await productDetail(id);
      if (detailResult.isSucced) {
        dispatch(actions.setEditProduct({ ...detailResult.data }));
      } else {
        throw Error(detailResult.message || "服务器错误");
      }
    } catch (err) {
      throw Error(err as string);
    }
  }

  async function pictureSelected(e: React.ChangeEvent) {
    const el = e.target as HTMLInputElement;
    if (el.files && el.files.length) {
      try {
        const uploadResult = await upload({
          file: el.files[0],
          scences: UploadScences.Product,
        });
        if (uploadResult.isSucced) {
          dispatch(
            actions.setEditProduct({
              logoName: uploadResult.data?.newName,
              logoUrl: uploadResult.data?.url,
            }),
          );
        } else {
          throw Error(uploadResult.message || "服务器错误");
        }
      } catch (err) {
        throw Error(err as string);
      }
    }
  }

  const saveDetail = useCallback(async () => {
    if (!states.editProduct.categoryId) {
      alert("请选择分类");
      return;
    }
    if (!states.editProduct.name) {
      alert("请输入名称");
      return;
    }
    if (!states.editProduct.minimumUnit) {
      alert("请输入单位");
      return;
    }
    if (!states.editProduct.unitPrice) {
      alert("请输入单价");
      return;
    }
    try {
      const editResult = await productEdit({
        categoryId: states.editProduct.categoryId || 0,
        description: states.editProduct.description || "",
        detail: states.editProduct.detail || "",
        id: states.editProduct.id || 0,
        logoName: states.editProduct.logoName || "",
        minimumUnit: states.editProduct.minimumUnit || "",
        name: states.editProduct.name || "",
        unitPrice: states.editProduct.unitPrice || 0,
      });
      if (editResult.isSucced) {
        alert("保存成功");
      } else {
        throw Error(editResult.message || "服务器错误");
      }
    } catch (err) {
      throw Error(err as string);
    }
  }, [states.editProduct]);

  async function deleteProduct(productId: number) {
    try {
      const deleteResult = await productDelete(productId);
      if (deleteResult.isSucced) {
        dispatch(actions.removeProduct(productId));
      } else {
        throw Error(deleteResult.message || "服务器错误");
      }
    } catch (err) {
      throw Error(err as string);
    }
  }

  function searchClick() {
    if (keywordRef.current) {
      dispatch(actions.setKeyword(keywordRef.current.value));
    }
  }

  return (
    <>
      <div className={styles.container}>
        <div className={styles.filter}>
          <div className={styles.search}>
            {!states.isLoading && (
              <TreeSelector
                items={states.categories}
                onChecked={categoryChecked}
              />
            )}
            <div className={styles.keyword}>
              <input
                ref={keywordRef}
                type="text"
                placeholder="请输入关键词"
                // value={states.keyword}
                // onChange={(e) => dispatch(actions.setKeyword(e.target.value))}
                onKeyDown={(e) => {
                  if (e.key == "Enter") searchClick();
                }}
              />
              <a onClick={searchClick}>
                <i className="ss ssi-sousuo"></i>
              </a>
            </div>
          </div>
          <ul className={styles.sort}>
            <li>
              <a onClick={() => dispatch(actions.toggleOrderByCreateTime())}>
                创建时间&nbsp;
                {states.orderBys.createTime ? (
                  <i
                    className={`ss ssi-triangleupfill ${states.orderBys.createTime == "asc" ? "" : styles.desc}`}
                  ></i>
                ) : (
                  <></>
                )}
              </a>
            </li>
            <li>
              <a onClick={() => dispatch(actions.toggleOrderBySoldAmount())}>
                售出数量&nbsp;
                {states.orderBys.soldAmount ? (
                  <i
                    className={`ss ssi-triangleupfill ${states.orderBys.soldAmount == "asc" ? "" : styles.desc}`}
                  ></i>
                ) : (
                  <></>
                )}
                <i></i>
              </a>
            </li>
          </ul>
        </div>
        <div className={styles.content}>
          {states.products.map((prod) => {
            return (
              <div
                key={prod.id}
                className={styles.card}
                onClick={() => viewDetailClick(prod.id)}
              >
                <div className={styles.body}>
                  <div className={styles.logo}>
                    <img src={prod.logoUrl || ""} />
                  </div>
                  <div className={styles.text}>
                    <p className={styles.name}>{prod.name}</p>
                    <p>{prod.categoryName}</p>
                    <p>
                      <span>{prod.unitPrice}</span>元/
                      <span>{prod.minimumUnit}</span>
                    </p>
                    <p>已售：{prod.soldAmount}</p>
                    <p>{prod.createTime}</p>
                    <p className={styles.desc}>{prod.description}</p>
                  </div>
                </div>
                <div className={styles.footer}>
                  <button onClick={() => deleteProduct(prod.id)}>删除</button>
                </div>
              </div>
            );
          })}
          <LoadMore
            pageIndex={states.pageIndex}
            pageCount={states.pageCount}
            loadMore={onLoadMore}
          />
        </div>
      </div>

      {asideContainer &&
        createPortal(
          <div className={styles.aside}>
            <div className={styles.form}>
              <div className={styles.formGroup}>
                <label>分类</label>
                <input
                  type="text"
                  value={states.editProduct.categoryName || ""}
                  disabled
                />
              </div>
              <div className={styles.formGroup}>
                <label>名称</label>
                <input
                  type="text"
                  placeholder="请输入名称"
                  value={states.editProduct.name || ""}
                  onChange={(e) =>
                    dispatch(actions.setEditProduct({ name: e.target.value }))
                  }
                />
              </div>
              <div className={styles.formGroup}>
                <label>描述</label>
                <textarea
                  placeholder="请输入描述"
                  value={states.editProduct.description || ""}
                  onChange={(e) =>
                    dispatch(
                      actions.setEditProduct({ description: e.target.value }),
                    )
                  }
                  rows={4}
                />
              </div>
              <div className={styles.formGroup}>
                <label>图片</label>
                <div>
                  {states.editProduct.logoUrl && (
                    <img src={states.editProduct.logoUrl || ""} />
                  )}
                  <input
                    type="file"
                    accept="image/*"
                    onChange={pictureSelected}
                  />
                </div>
              </div>
              <div className={styles.formGroup}>
                <label>最小销售单位</label>
                <input
                  type="text"
                  placeholder="请输入最小销售单位"
                  value={states.editProduct.minimumUnit || ""}
                  onChange={(e) =>
                    dispatch(
                      actions.setEditProduct({ minimumUnit: e.target.value }),
                    )
                  }
                />
              </div>
              <div className={styles.formGroup}>
                <label>单价</label>
                <input
                  type="number"
                  value={states.editProduct.unitPrice || ""}
                  onChange={(e) =>
                    dispatch(
                      actions.setEditProduct({
                        unitPrice: Number.parseFloat(e.target.value),
                      }),
                    )
                  }
                />
              </div>
              <div className={styles.formGroup}>
                <textarea rows={10}>TODO:</textarea>
              </div>
              <div className={styles.btnGroup}>
                <button onClick={saveDetail}>保存</button>
              </div>
            </div>
          </div>,
          asideContainer,
        )}
    </>
  );
}
