import {
  CheckOutlined,
  DeleteOutlined,
  EditOutlined,
  FilterOutlined,
  SearchOutlined,
  SortAscendingOutlined,
  UndoOutlined,
} from "@ant-design/icons";
import {
  Badge,
  Button,
  ConfigProvider,
  Input,
  Space,
  type ThemeConfig,
} from "antd";
import { memo, useEffect, useState } from "react";
import { LoaderFunction } from "react-router-dom";
import { v4 as v4uuid } from "uuid";
import { useSnapshot } from "valtio";
import { subscribeKey } from "valtio/utils";

import { type CardMeta, searchCards } from "@/api";
import { deckStore, type IDeck, initStore } from "@/stores";
import {
  Background,
  IconFont,
  Loading,
  ScrollableArea,
  YgoCard,
} from "@/ui/Shared";

import { CardDetail } from "./CardDetail";
import { DeckSelect } from "./DeckSelect";
import styles from "./index.module.scss";
import {
  type EditingDeck,
  editingDeckToIDeck,
  iDeckToEditingDeck,
} from "./utils";

const theme: ThemeConfig = {
  components: {
    Layout: {
      colorBgBody: "transparent",
    },
  },
};

export const loader: LoaderFunction = async () => {
  // 必须先加载卡组，不然页面会崩溃
  if (!initStore.decks) {
    await new Promise<void>((rs) => {
      subscribeKey(initStore, "decks", (done) => done && rs());
    });
  }
  return null;
};

export const Component: React.FC = () => {
  const snapDecks = useSnapshot(deckStore);
  const { sqlite } = useSnapshot(initStore);
  const [selectedDeck, setSelectedDeck] = useState<IDeck>(deckStore.decks[0]);

  return (
    <ConfigProvider theme={theme}>
      <Background />
      <div className={styles.layout} style={{ width: "100%" }}>
        <div className={styles.sider}>
          <ScrollableArea className={styles["deck-select-container"]}>
            <DeckSelect
              decks={snapDecks.decks}
              selected={selectedDeck.deckName}
              onSelect={(name) =>
                setSelectedDeck(deckStore.get(name) ?? deckStore.decks[0])
              }
              onDelete={(id) => console.log(id)}
              onDownload={(id) => console.log(id)}
              onAdd={() => console.log("add")}
            />
          </ScrollableArea>
          <CardDetail code={123} open={false} onClose={() => {}} />
        </div>
        <div className={styles.content}>
          <div className={styles.deck}>
            <DeckEditor deck={selectedDeck} onSave={() => {}} />
          </div>
          <div className={styles.select}>
            {sqlite.progress === 1 ? (
              <CardSelect />
            ) : (
              <div className={styles.container}>
                <Loading />
              </div>
            )}
          </div>
        </div>
      </div>
    </ConfigProvider>
  );
};
Component.displayName = "Build";

/** 正在编辑的卡组 */
const DeckEditor: React.FC<{
  deck: IDeck;
  onSave: (deck: IDeck) => void;
}> = ({ deck, onSave }) => {
  const [editingDeck, setEditingDeck] = useState<EditingDeck>({
    deckName: deck.deckName,
    main: [],
    extra: [],
    side: [],
  });
  useEffect(() => {
    iDeckToEditingDeck(deck).then(setEditingDeck);
  }, [deck]);
  return (
    <div className={styles.container}>
      <Space className={styles.title}>
        <Input
          placeholder="请输入卡组名字"
          bordered={false}
          prefix={<EditOutlined />}
          style={{ width: 400 }}
          onChange={(e) =>
            setEditingDeck({ ...editingDeck, deckName: e.target.value })
          }
          value={editingDeck.deckName}
        />
        <Space style={{ marginRight: 6 }}>
          <Button type="text" size="small" icon={<DeleteOutlined />}>
            清空
          </Button>
          <Button type="text" size="small" icon={<UndoOutlined />}>
            重置
          </Button>
          <Button
            type="text"
            size="small"
            icon={<CheckOutlined />}
            onClick={() => onSave(editingDeckToIDeck(editingDeck))}
          >
            保存
          </Button>
        </Space>
      </Space>
      <ScrollableArea className={styles["deck-zone"]}>
        {(["main", "extra", "side"] as const).map((type) => (
          <div key={type} className={styles[type]}>
            <div className={styles["card-continer"]}>
              {editingDeck[type].map((item) => (
                <Card value={item} key={v4uuid()} />
              ))}
            </div>
          </div>
        ))}
      </ScrollableArea>
    </div>
  );
};

/** 卡片库，选择卡片加入正在编辑的卡组 */
const CardSelect: React.FC = () => {
  const [searchWord, setSearchWord] = useState("");
  const [searchResult, setSearchResult] = useState<CardMeta[]>([]);
  const handleSearch = async () => {
    const result = await searchCards(searchWord);
    setSearchResult(result);
  };
  return (
    <div className={styles.container}>
      <div className={styles.title}>
        <Input
          placeholder="搜索卡片"
          bordered={false}
          suffix={
            <Button
              type="text"
              icon={<SearchOutlined />}
              onClick={handleSearch}
            />
          }
          value={searchWord}
          onChange={(e) => setSearchWord(e.target.value)}
          onKeyUp={(e) => e.key === "Enter" && handleSearch()}
        />
      </div>
      <div className={styles["select-btns"]}>
        <Button block type="text" icon={<FilterOutlined />}>
          筛选
          {/* TODO: 下面这个Badge应根据有无筛选规则而显示 */}
          {false && <Badge dot offset={[5, -5]} />}
        </Button>
        <Button block type="text" icon={<SortAscendingOutlined />}>
          <span>
            排列
            <span className={styles["search-count"]}>
              ({searchResult.length})
            </span>
          </span>
          {false && <Badge dot offset={[5, -5]} />}
        </Button>
        <Button block type="text" icon={<DeleteOutlined />}>
          重置
        </Button>
      </div>
      <ScrollableArea className={styles["search-cards-container"]}>
        {searchResult.length ? (
          <SearchResults results={searchResult} />
        ) : (
          <div className={styles.empty}>
            <IconFont type="icon-empty" size={40} />
            <div>无搜索结果</div>
          </div>
        )}
      </ScrollableArea>
    </div>
  );
};

/** 搜索区的搜索结果，使用memo避免重复渲染 */
const SearchResults: React.FC<{
  results: CardMeta[];
}> = memo(({ results }) => (
  <div className={styles["search-cards"]}>
    {results.map((item) => (
      <Card value={item} key={v4uuid()} />
    ))}
  </div>
));

/** 本组件内使用的单张卡片，增加了文字在图片下方 */
const Card: React.FC<{ value: CardMeta }> = memo(({ value }) => (
  <div className={styles.card}>
    <div className={styles.cardname}>{value.text.name}</div>
    <YgoCard className={styles.cardcover} code={value.id} />
  </div>
));
