import { DeleteOutlined, SettingOutlined } from '@ant-design/icons';
import { css } from '@emotion/css';
import { Avatar, Card, Layout, Menu, message, PageHeader, Popconfirm, Spin, Switch, Tabs } from 'antd';
import React, { createContext, useContext, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { Redirect, useHistory, useRouteMatch } from 'react-router-dom';
import { ACLPane } from '../acl';
import { useAPIClient, useRequest } from '../api-client';
import { CollectionManagerPane } from '../collection-manager';
import { useDocumentTitle } from '../document-title';
import { Icon } from '../icon';
import { RouteSwitchContext } from '../route-switch';
import { useCompile } from '../schema-component';
import { BlockTemplatesPane } from '../schema-templates';
import { SystemSettingsPane } from '../system-settings';

export const SettingsCenterContext = createContext<any>({});

const PluginCard = (props) => {
  const history = useHistory<any>();
  const { data = {} } = props;
  const api = useAPIClient();
  const { t } = useTranslation();
  return (
    <Card
      bordered={false}
      style={{ width: 'calc(20% - 24px)', marginRight: 24, marginBottom: 24 }}
      actions={[
        data.enabled ? (
          <SettingOutlined
            onClick={() => {
              history.push(`/admin/settings/${data.name}`);
            }}
          />
        ) : null,
        <Popconfirm
          title={t('Are you sure to delete this plugin?')}
          onConfirm={async () => {
            await api.request({
              url: `pm:remove/${data.name}`,
            });
            message.success(t('插件删除成功'));
            window.location.reload();
          }}
          onCancel={() => {}}
          okText={t('Yes')}
          cancelText={t('No')}
        >
          <DeleteOutlined />
        </Popconfirm>,
        <Switch
          size={'small'}
          onChange={async (checked) => {
            await api.request({
              url: `pm:${checked ? 'enable' : 'disable'}/${data.name}`,
            });
            message.success(checked ? t('插件激活成功') : t('插件禁用成功'));
            window.location.reload();
          }}
          defaultChecked={data.enabled}
        ></Switch>,
      ].filter(Boolean)}
    >
      <Card.Meta
        className={css`
          .ant-card-meta-avatar {
            margin-top: 8px;
            .ant-avatar {
              border-radius: 2px;
            }
          }
        `}
        avatar={<Avatar />}
        description={data.description}
        title={
          <span>
            {data.name}
            <span
              className={css`
                display: block;
                color: rgba(0, 0, 0, 0.45);
                font-weight: normal;
                font-size: 13px;
                // margin-left: 8px;
              `}
            >
              {data.version}
            </span>
          </span>
        }
      />
    </Card>
  );
};

const BuiltInPluginCard = (props) => {
  const { data } = props;
  return (
    <Card
      bordered={false}
      style={{ width: 'calc(20% - 24px)', marginRight: 24, marginBottom: 24 }}
      // actions={[<a>Settings</a>, <a>Remove</a>, <Switch size={'small'} defaultChecked={true}></Switch>]}
    >
      <Card.Meta
        className={css`
          .ant-card-meta-avatar {
            margin-top: 8px;
            .ant-avatar {
              border-radius: 2px;
            }
          }
        `}
        avatar={<Avatar />}
        description={data.description}
        title={
          <span>
            {data.name}
            <span
              className={css`
                display: block;
                color: rgba(0, 0, 0, 0.45);
                font-weight: normal;
                font-size: 13px;
                // margin-left: 8px;
              `}
            >
              {data.version}
            </span>
          </span>
        }
      />
    </Card>
  );
};

const LocalPlugins = () => {
  const { data, loading } = useRequest({
    url: 'applicationPlugins:list',
    params: {
      filter: {
        'builtIn.$isFalsy': true,
      },
      sort: 'name',
    },
  });
  if (loading) {
    return <Spin />;
  }
  return (
    <>
      {data?.data?.map((item) => {
        return <PluginCard key={item.id} data={item} />;
      })}
    </>
  );
};

const BuiltinPlugins = () => {
  const { data, loading } = useRequest({
    url: 'applicationPlugins:list',
    params: {
      filter: {
        'builtIn.$isTruly': true,
      },
      sort: 'name',
    },
  });
  if (loading) {
    return <Spin />;
  }
  return (
    <>
      {data?.data?.map((item) => {
        return <BuiltInPluginCard data={item} />;
      })}
    </>
  );
};

const MarketplacePlugins = () => {
  const { t } = useTranslation();
  return <div style={{ fontSize: 18 }}>{t('Coming soon...')}</div>;
};

const PluginList = (props) => {
  const match = useRouteMatch<any>();
  const history = useHistory<any>();
  const { tabName = 'local' } = match.params || {};
  const { setTitle } = useDocumentTitle();
  const { t } = useTranslation();

  return (
    <div>
      <PageHeader
        ghost={false}
        title={t('Plugin manager')}
        footer={
          <Tabs
            activeKey={tabName}
            onChange={(activeKey) => {
              history.push(`/admin/pm/list/${activeKey}`);
            }}
          >
            <Tabs.TabPane tab={t('Local')} key={'local'} />
            <Tabs.TabPane tab={t('Built-in')} key={'built-in'} />
            <Tabs.TabPane tab={t('Marketplace')} key={'marketplace'} />
          </Tabs>
        }
      />
      <div style={{ margin: 24, display: 'flex', flexFlow: 'row wrap' }}>
        {React.createElement(
          {
            local: LocalPlugins,
            'built-in': BuiltinPlugins,
            marketplace: MarketplacePlugins,
          }[tabName],
        )}
      </div>
    </div>
  );
};

const settings = {
  acl: {
    title: '{{t("ACL")}}',
    icon: 'LockOutlined',
    tabs: {
      roles: {
        title: '{{t("Roles & Permissions")}}',
        component: ACLPane,
      },
    },
  },
  'block-templates': {
    title: '{{t("Block templates")}}',
    icon: 'LayoutOutlined',
    tabs: {
      list: {
        title: '{{t("Block templates")}}',
        component: BlockTemplatesPane,
      },
    },
  },
  'collection-manager': {
    icon: 'DatabaseOutlined',
    title: '{{t("Collection manager")}}',
    tabs: {
      collections: {
        title: '{{t("Collections & Fields")}}',
        component: CollectionManagerPane,
      },
    },
  },
  'system-settings': {
    icon: 'SettingOutlined',
    title: '{{t("System settings")}}',
    tabs: {
      'system-settings': {
        title: '{{t("System settings")}}',
        component: SystemSettingsPane,
      },
    },
  },
};

const SettingsCenter = (props) => {
  const match = useRouteMatch<any>();
  const history = useHistory<any>();
  const items = useContext(SettingsCenterContext);
  const compile = useCompile();
  const firstUri = useMemo(() => {
    const keys = Object.keys(items).sort();
    const pluginName = keys.shift();
    const tabName = Object.keys(items?.[pluginName]?.tabs || {}).shift();
    return `/admin/settings/${pluginName}/${tabName}`;
  }, [items]);
  const { pluginName, tabName } = match.params || {};
  if (!pluginName) {
    return <Redirect to={firstUri} />;
  }
  if (!items[pluginName]) {
    return <Redirect to={firstUri} />;
  }
  if (!tabName) {
    const firstTabName = Object.keys(items[pluginName]?.tabs).shift();
    return <Redirect to={`/admin/settings/${pluginName}/${firstTabName}`} />;
  }
  const component = items[pluginName]?.tabs?.[tabName]?.component;
  const menuItems: any = Object.keys(items)
    .sort()
    .map((key) => {
      const item = items[key];
      const tabKey = Object.keys(item.tabs).shift();
      return {
        label: compile(item.title),
        key: key,
        icon: item.icon ? <Icon type={item.icon} /> : null,
      };
    });
  return (
    <Layout>
      <div
        style={
          {
            '--side-menu-width': '200px',
          } as Record<string, string>
        }
        className={css`
          width: var(--side-menu-width);
          overflow: hidden;
          flex: 0 0 var(--side-menu-width);
          max-width: var(--side-menu-width);
          min-width: var(--side-menu-width);
          pointer-events: none;
        `}
      ></div>
      <Layout.Sider
        className={css`
          height: 100%;
          position: fixed;
          padding-top: 46px;
          left: 0;
          top: 0;
          background: rgba(0, 0, 0, 0);
          z-index: 100;
        `}
        theme={'light'}
      >
        <Menu
          selectedKeys={[pluginName]}
          style={{ height: 'calc(100vh - 46px)', overflowY: 'auto', overflowX: 'hidden' }}
          onClick={(e) => {
            const item = items[e.key];
            const tabKey = Object.keys(item.tabs).shift();
            history.push(`/admin/settings/${e.key}/${tabKey}`);
          }}
          items={menuItems as any}
        />
      </Layout.Sider>
      <Layout.Content>
        <PageHeader
          ghost={false}
          title={compile(items[pluginName]?.title)}
          footer={
            <Tabs
              activeKey={tabName}
              onChange={(activeKey) => {
                history.push(`/admin/settings/${pluginName}/${activeKey}`);
              }}
            >
              {Object.keys(items[pluginName]?.tabs).map((tabKey) => {
                const tab = items[pluginName].tabs?.[tabKey];
                return <Tabs.TabPane tab={compile(tab?.title)} key={tabKey} />;
              })}
            </Tabs>
          }
        />
        <div style={{ margin: 24 }}>{component && React.createElement(component)}</div>
      </Layout.Content>
    </Layout>
  );
};

export const SettingsCenterProvider = (props) => {
  const { settings = {} } = props;
  const items = useContext(SettingsCenterContext);
  return (
    <SettingsCenterContext.Provider value={{ ...items, ...settings }}>{props.children}</SettingsCenterContext.Provider>
  );
};

export const PMProvider = (props) => {
  const { routes, ...others } = useContext(RouteSwitchContext);
  routes[1].routes.unshift(
    {
      type: 'route',
      path: '/admin/pm/list/:tabName?',
      component: PluginList,
    },
    {
      type: 'route',
      path: '/admin/settings/:pluginName?/:tabName?',
      component: SettingsCenter,
      uiSchemaUid: routes[1].uiSchemaUid,
    },
  );
  return (
    <SettingsCenterProvider settings={settings}>
      <RouteSwitchContext.Provider value={{ ...others, routes }}>{props.children}</RouteSwitchContext.Provider>
    </SettingsCenterProvider>
  );
};

export default PMProvider;

export * from './PluginManagerLink';
