import { ReactComponent as MoreModelIcon } from '@/assets/svg/more-model.svg';
import { useSetModalState } from '@/hooks/commonHooks';
import {
  LlmItem,
  useFetchLlmFactoryListOnMount,
  useFetchMyLlmListOnMount,
} from '@/hooks/llmHooks';
import { ReactComponent as MoonshotIcon } from '@/icons/moonshot.svg';
import { ReactComponent as OpenAiIcon } from '@/icons/openai.svg';
import { ReactComponent as TongYiIcon } from '@/icons/tongyi.svg';
import { ReactComponent as WenXinIcon } from '@/icons/wenxin.svg';
import { ReactComponent as ZhiPuIcon } from '@/icons/zhipu.svg';
import { SettingOutlined, UserOutlined } from '@ant-design/icons';
import {
  Avatar,
  Button,
  Card,
  Col,
  Collapse,
  CollapseProps,
  Divider,
  Flex,
  List,
  Row,
  Space,
  Spin,
  Typography,
} from 'antd';
import { useCallback } from 'react';
import SettingTitle from '../components/setting-title';
import ApiKeyModal from './api-key-modal';
import {
  useSelectModelProvidersLoading,
  useSubmitApiKey,
  useSubmitSystemModelSetting,
} from './hooks';
import SystemModelSettingModal from './system-model-setting-modal';

import styles from './index.less';

const IconMap = {
  'Tongyi-Qianwen': TongYiIcon,
  Moonshot: MoonshotIcon,
  OpenAI: OpenAiIcon,
  'ZHIPU-AI': ZhiPuIcon,
  文心一言: WenXinIcon,
};

const LlmIcon = ({ name }: { name: string }) => {
  const Icon = IconMap[name as keyof typeof IconMap];
  return Icon ? (
    <Icon width={48} height={48}></Icon>
  ) : (
    <Avatar shape="square" size="large" icon={<UserOutlined />} />
  );
};

const { Text } = Typography;
interface IModelCardProps {
  item: LlmItem;
  clickApiKey: (llmFactory: string) => void;
}

const ModelCard = ({ item, clickApiKey }: IModelCardProps) => {
  const { visible, switchVisible } = useSetModalState();

  const handleApiKeyClick = () => {
    clickApiKey(item.name);
  };

  const handleShowMoreClick = () => {
    switchVisible();
  };

  return (
    <List.Item>
      <Card className={styles.addedCard}>
        <Row align={'middle'}>
          <Col span={12}>
            <Flex gap={'middle'} align="center">
              <LlmIcon name={item.name} />
              <Flex vertical gap={'small'}>
                <b>{item.name}</b>
                <Text>{item.tags}</Text>
              </Flex>
            </Flex>
          </Col>
          <Col span={12} className={styles.factoryOperationWrapper}>
            <Space size={'middle'}>
              <Button onClick={handleApiKeyClick}>
                API-Key
                <SettingOutlined />
              </Button>
              <Button onClick={handleShowMoreClick}>
                <Flex gap={'small'}>
                  Show more models
                  <MoreModelIcon />
                </Flex>
              </Button>
            </Space>
          </Col>
        </Row>
        {visible && (
          <List
            size="small"
            dataSource={item.llm}
            className={styles.llmList}
            renderItem={(item) => <List.Item>{item.name}</List.Item>}
          />
        )}
      </Card>
    </List.Item>
  );
};

const UserSettingModel = () => {
  const factoryList = useFetchLlmFactoryListOnMount();
  const llmList = useFetchMyLlmListOnMount();
  const loading = useSelectModelProvidersLoading();
  const {
    saveApiKeyLoading,
    initialApiKey,
    onApiKeySavingOk,
    apiKeyVisible,
    hideApiKeyModal,
    showApiKeyModal,
  } = useSubmitApiKey();
  const {
    saveSystemModelSettingLoading,
    onSystemSettingSavingOk,
    systemSettingVisible,
    hideSystemSettingModal,
    showSystemSettingModal,
  } = useSubmitSystemModelSetting();

  const handleApiKeyClick = useCallback(
    (llmFactory: string) => {
      showApiKeyModal({ llm_factory: llmFactory });
    },
    [showApiKeyModal],
  );

  const handleAddModel = (llmFactory: string) => () => {
    handleApiKeyClick(llmFactory);
  };

  const items: CollapseProps['items'] = [
    {
      key: '1',
      label: 'Added models',
      children: (
        <List
          grid={{ gutter: 16, column: 1 }}
          dataSource={llmList}
          renderItem={(item) => (
            <ModelCard item={item} clickApiKey={handleApiKeyClick}></ModelCard>
          )}
        />
      ),
    },
    {
      key: '2',
      label: 'Models to be added',
      children: (
        <List
          grid={{
            gutter: 24,
            xs: 1,
            sm: 2,
            md: 3,
            lg: 4,
            xl: 4,
            xxl: 8,
          }}
          dataSource={factoryList}
          renderItem={(item) => (
            <List.Item>
              <Card className={styles.toBeAddedCard}>
                <Flex vertical gap={'large'}>
                  <LlmIcon name={item.name} />
                  <Flex vertical gap={'middle'}>
                    <b>{item.name}</b>
                    <Text>{item.tags}</Text>
                  </Flex>
                </Flex>
                <Divider></Divider>
                <Button type="link" onClick={handleAddModel(item.name)}>
                  Add the model
                </Button>
              </Card>
            </List.Item>
          )}
        />
      ),
    },
  ];

  return (
    <>
      <Spin spinning={loading}>
        <section className={styles.modelWrapper}>
          <SettingTitle
            title="Model Setting"
            description="Manage your account settings and preferences here."
            showRightButton
            clickButton={showSystemSettingModal}
          ></SettingTitle>
          <Divider></Divider>
          <Collapse defaultActiveKey={['1']} ghost items={items} />
        </section>
      </Spin>
      <ApiKeyModal
        visible={apiKeyVisible}
        hideModal={hideApiKeyModal}
        loading={saveApiKeyLoading}
        initialValue={initialApiKey}
        onOk={onApiKeySavingOk}
      ></ApiKeyModal>
      <SystemModelSettingModal
        visible={systemSettingVisible}
        onOk={onSystemSettingSavingOk}
        hideModal={hideSystemSettingModal}
        loading={saveSystemModelSettingLoading}
      ></SystemModelSettingModal>
    </>
  );
};

export default UserSettingModel;
