import { App, Avatar, Button, Col, Drawer, Form, Input, InputNumber, Popconfirm, Row, Select, Space, Switch, Tag, Typography, Upload } from "antd";
import type { ColumnsType } from "antd/es/table";
import { AppstoreOutlined, DeleteOutlined, EditOutlined, GlobalOutlined, LinkOutlined, PictureOutlined, PlusOutlined, ReloadOutlined, RobotOutlined, SaveOutlined, SearchOutlined, UploadOutlined } from "@ant-design/icons";
import { useCallback, useEffect, useMemo, useState } from "react";
import PageContainer from "@/components/shared/PageContainer";
import DataListPanel from "@/components/shared/DataListPanel";
import ListTable from "@/components/shared/ListTable/ListTable";
import AppPagination from "@/components/shared/AppPagination";
import SectionCard from "@/components/shared/SectionCard";
import SummaryStatCards from "@/components/shared/SummaryStatCards";
import { createExternalApp, deleteExternalApp, listExternalApps, type ExternalAppDTO, type ExternalAppVO, updateExternalApp, uploadExternalAppApk, uploadExternalAppIcon } from "@/api/business/externalApp";
import "./ExternalAppManagement.css";

const { Text } = Typography;
const { TextArea } = Input;
const ICON_UPLOAD_ACCEPT = ".png,.jpg,.jpeg,image/png,image/jpeg";

type ExternalAppFormValues = {
  appName: string;
  appType: "native" | "web";
  appInfo?: {
    versionName?: string;
    webUrl?: string;
    packageName?: string;
    apkUrl?: string;
  };
  iconUrl?: string;
  description?: string;
  sortOrder?: number;
  statusEnabled: boolean;
  remark?: string;
};

const STATUS_OPTIONS = [
  { label: "全部状态", value: "all" },
  { label: "已启用", value: "enabled" },
  { label: "已停用", value: "disabled" },
] as const;

function normalizeAppInfo(value: ExternalAppVO["appInfo"]): NonNullable<ExternalAppFormValues["appInfo"]> {
  if (!value || typeof value !== "object") {
    return {};
  }
  const info = value as Record<string, unknown>;
  return {
    versionName: typeof info.versionName === "string" ? info.versionName : undefined,
    webUrl: typeof info.webUrl === "string" ? info.webUrl : undefined,
    packageName: typeof info.packageName === "string" ? info.packageName : undefined,
    apkUrl: typeof info.apkUrl === "string" ? info.apkUrl : undefined,
  };
}

function compactObject<T extends Record<string, unknown>>(value: T): T {
  return Object.fromEntries(Object.entries(value).filter(([, field]) => field !== undefined && field !== null && field !== "")) as T;
}

export default function ExternalAppManagement() {
  const { message } = App.useApp();
  const [form] = Form.useForm<ExternalAppFormValues>();
  const watchedIconUrl = Form.useWatch("iconUrl", form);
  const [loading, setLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [drawerOpen, setDrawerOpen] = useState(false);
  const [editing, setEditing] = useState<ExternalAppVO | null>(null);
  const [records, setRecords] = useState<ExternalAppVO[]>([]);
  const [searchValue, setSearchValue] = useState("");
  const [statusFilter, setStatusFilter] = useState<(typeof STATUS_OPTIONS)[number]["value"]>("all");
  const [appTypeFilter, setAppTypeFilter] = useState<"all" | "native" | "web">("all");
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(10);
  const [uploadingApk, setUploadingApk] = useState(false);
  const [uploadingIcon, setUploadingIcon] = useState(false);

  const loadData = useCallback(async () => {
    setLoading(true);
    try {
      const result = await listExternalApps();
      setRecords(result || []);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    void loadData();
  }, [loadData]);

  const filteredRecords = useMemo(() => {
    const keyword = searchValue.trim().toLowerCase();
    return records.filter((item) => {
      if (appTypeFilter !== "all" && item.appType !== appTypeFilter) {
        return false;
      }
      if (statusFilter === "enabled" && item.status !== 1) {
        return false;
      }
      if (statusFilter === "disabled" && item.status === 1) {
        return false;
      }
      if (!keyword) {
        return true;
      }
      const info = normalizeAppInfo(item.appInfo);
      return [item.appName, item.description, info.versionName, info.webUrl, info.packageName, info.apkUrl, item.creatorUsername].some((field) =>
        String(field || "").toLowerCase().includes(keyword)
      );
    });
  }, [appTypeFilter, records, searchValue, statusFilter]);

  const pagedRecords = useMemo(() => {
    const start = (page - 1) * pageSize;
    return filteredRecords.slice(start, start + pageSize);
  }, [filteredRecords, page, pageSize]);

  useEffect(() => {
    setPage(1);
  }, [searchValue, statusFilter, appTypeFilter]);

  const stats = useMemo(() => ({
    total: records.length,
    native: records.filter((item) => item.appType === "native").length,
    web: records.filter((item) => item.appType === "web").length,
    enabled: records.filter((item) => item.status === 1).length,
  }), [records]);

  const statCards = useMemo(() => [
    { key: "total", label: "应用总数", value: stats.total, icon: <AppstoreOutlined />, color: "#1890ff" },
    { key: "native", label: "原生应用", value: stats.native, icon: <RobotOutlined />, color: "#faad14" },
    { key: "web", label: "Web 应用", value: stats.web, icon: <GlobalOutlined />, color: "#52c41a" },
    { key: "enabled", label: "已启用", value: stats.enabled, icon: <PictureOutlined />, color: "#13c2c2" },
  ], [stats]);

  const openCreate = () => {
    setEditing(null);
    form.resetFields();
    form.setFieldsValue({
      appType: "native",
      statusEnabled: true,
      sortOrder: 0,
      appInfo: {},
    });
    setDrawerOpen(true);
  };

  const openEdit = (record: ExternalAppVO) => {
    setEditing(record);
    form.setFieldsValue({
      appName: record.appName,
      appType: record.appType,
      appInfo: normalizeAppInfo(record.appInfo),
      iconUrl: record.iconUrl,
      description: record.description,
      sortOrder: record.sortOrder,
      statusEnabled: record.status === 1,
      remark: record.remark,
    });
    setDrawerOpen(true);
  };

  const handleDelete = async (record: ExternalAppVO) => {
    await deleteExternalApp(record.id);
    message.success("删除成功");
    await loadData();
  };

  const handleSubmit = async () => {
    const values = await form.validateFields();
    const payload: ExternalAppDTO = {
      appName: values.appName.trim(),
      appType: values.appType,
      appInfo: compactObject(values.appInfo || {}),
      iconUrl: values.iconUrl?.trim(),
      description: values.description?.trim(),
      sortOrder: values.sortOrder,
      status: values.statusEnabled ? 1 : 0,
      remark: values.remark?.trim(),
    };

    setSaving(true);
    try {
      if (editing) {
        await updateExternalApp(editing.id, payload);
        message.success("外部应用更新成功");
      } else {
        await createExternalApp(payload);
        message.success("外部应用创建成功");
      }
      setDrawerOpen(false);
      await loadData();
    } finally {
      setSaving(false);
    }
  };

  const handleUploadApk = async (file: File) => {
    setUploadingApk(true);
    try {
      const result = await uploadExternalAppApk(file);
      const currentInfo = form.getFieldValue("appInfo") || {};
      form.setFieldsValue({
        appInfo: {
          ...currentInfo,
          apkUrl: result.apkUrl || currentInfo.apkUrl,
          packageName: result.packageName || currentInfo.packageName,
          versionName: result.versionName || currentInfo.versionName,
        },
      });
      if (result.appName && !form.getFieldValue("appName")) {
        form.setFieldValue("appName", result.appName);
      }
      message.success("APK 上传成功，已自动回填可解析的 APK 元数据");
    } finally {
      setUploadingApk(false);
    }
  };

  const handleUploadIcon = async (file: File) => {
    setUploadingIcon(true);
    try {
      const result = await uploadExternalAppIcon(file);
      if (result.iconUrl) {
        form.setFieldValue("iconUrl", result.iconUrl);
      }
      message.success("图标上传成功");
    } finally {
      setUploadingIcon(false);
    }
  };

  const beforeUploadIcon = (file: File) => {
    const isAllowedIcon = file.type
      ? file.type === "image/png" || file.type === "image/jpeg"
      : /\.(png|jpe?g)$/i.test(file.name);

    if (!isAllowedIcon) {
      message.warning("应用图标仅支持上传 PNG / JPG 格式");
      return Upload.LIST_IGNORE;
    }

    void handleUploadIcon(file);
    return Upload.LIST_IGNORE;
  };

  const handleToggleStatus = async (record: ExternalAppVO, checked: boolean) => {
    await updateExternalApp(record.id, { status: checked ? 1 : 0 });
    message.success(checked ? "已启用应用" : "已停用应用");
    await loadData();
  };

  const columns: ColumnsType<ExternalAppVO> = [
    {
      title: "应用",
      key: "app",
      width: 260,
      render: (_, record) => (
        <Space>
          <Avatar shape="square" size={44} src={record.iconUrl} icon={<AppstoreOutlined />} />
          <Space direction="vertical" size={0}>
            <Text strong>{record.appName}</Text>
            <Text type="secondary">{record.description || "暂无描述"}</Text>
          </Space>
        </Space>
      ),
    },
    {
      title: "类型",
      dataIndex: "appType",
      key: "appType",
      width: 120,
      render: (value: ExternalAppVO["appType"]) => value === "native" ? <Tag color="green" icon={<RobotOutlined />}>原生应用</Tag> : <Tag color="blue" icon={<GlobalOutlined />}>Web 应用</Tag>,
    },
    {
      title: "入口信息",
      key: "entry",
      width: 260,
      render: (_, record) => {
        const info = normalizeAppInfo(record.appInfo);
        return (
          <Space direction="vertical" size={0}>
            <Text type="secondary">版本：{info.versionName || "-"}</Text>
            <Text type="secondary">{record.appType === "native" ? `包名：${info.packageName || "-"}` : `地址：${info.webUrl || "-"}`}</Text>
          </Space>
        );
      },
    },
    {
      title: "状态",
      key: "status",
      width: 120,
      render: (_, record) => <Switch size="small" checked={record.status === 1} onChange={(checked) => void handleToggleStatus(record, checked)} />,
    },
    {
      title: "排序权重",
      dataIndex: "sortOrder",
      key: "sortOrder",
      width: 90,
      align: "center",
    },
    {
      title: "操作",
      key: "action",
      width: 150,
      fixed: "right",
      render: (_, record) => {
        const info = normalizeAppInfo(record.appInfo);
        const link = record.appType === "native" ? info.apkUrl : info.webUrl;
        return (
          <Space size={4}>
            <Button type="text" icon={<LinkOutlined />} href={link} target="_blank" disabled={!link} />
            <Button type="text" icon={<EditOutlined />} onClick={() => openEdit(record)} />
            <Popconfirm title="确认删除该应用吗？" onConfirm={() => void handleDelete(record)}>
              <Button type="text" danger icon={<DeleteOutlined />} />
            </Popconfirm>
          </Space>
        );
      },
    },
  ];

  return (
    <PageContainer title={null} className="external-app-page">
      <SectionCard
        title="外部应用管理"
        description="统一维护首页九宫格与抽屉入口中的原生应用、Web 服务和应用图标资源。"
        contentClassName="external-app-page__content"
      >
        <SummaryStatCards items={statCards} ariaLabel="外部应用统计" />
        <DataListPanel
          leftActions={
            <Button type="primary" icon={<PlusOutlined />} onClick={openCreate}>
              新增应用
            </Button>
          }
          rightActions={
            <Space wrap>
              <Input placeholder="搜索名称、描述、包名或入口地址" prefix={<SearchOutlined />} allowClear style={{ width: 300 }} value={searchValue} onChange={(event) => setSearchValue(event.target.value)} />
              <Select value={appTypeFilter} style={{ width: 130 }} onChange={(value) => setAppTypeFilter(value)} options={[{ label: "全部类型", value: "all" }, { label: "原生应用", value: "native" }, { label: "Web 应用", value: "web" }]} />
              <Select value={statusFilter} style={{ width: 130 }} onChange={(value) => setStatusFilter(value as typeof statusFilter)} options={STATUS_OPTIONS as unknown as { label: string; value: string }[]} />
              <Button icon={<ReloadOutlined />} onClick={() => void loadData()} loading={loading}>
                刷新
              </Button>
            </Space>
          }
          footer={
            <AppPagination
              current={page}
              pageSize={pageSize}
              total={filteredRecords.length}
              onChange={(nextPage, nextSize) => {
                setPage(nextPage);
                setPageSize(nextSize);
              }}
            />
          }
        >
          <ListTable<ExternalAppVO>
            rowKey="id"
            columns={columns}
            dataSource={pagedRecords}
            loading={loading}
            scroll={{ x: "max-content", y: "100%" }}
            pagination={false}
          />
        </DataListPanel>
      </SectionCard>

      <Drawer title={editing ? "编辑外部应用" : "新增外部应用"} open={drawerOpen} onClose={() => setDrawerOpen(false)} width={700} destroyOnHidden forceRender footer={<div className="app-page__drawer-footer"><Button onClick={() => setDrawerOpen(false)}>取消</Button><Button type="primary" icon={<SaveOutlined />} loading={saving} onClick={() => void handleSubmit()}>保存</Button></div>}>
        <Form form={form} layout="vertical">
          <Row gutter={16}>
            <Col span={16}><Form.Item name="appName" label="应用名称" rules={[{ required: true, message: "请输入应用名称" }]}><Input placeholder="请输入应用名称" /></Form.Item></Col>
            <Col span={8}><Form.Item name="appType" label="应用类型" rules={[{ required: true, message: "请选择应用类型" }]}><Select options={[{ label: "原生应用", value: "native" }, { label: "Web 应用", value: "web" }]} /></Form.Item></Col>
          </Row>

          <Form.Item name="iconUrl" hidden>
            <Input />
          </Form.Item>

          <Form.Item label="应用图标" className="external-app-icon-form-item">
            <Upload
              accept={ICON_UPLOAD_ACCEPT}
              showUploadList={false}
              beforeUpload={(file) => beforeUploadIcon(file as File)}
            >
              <button
                type="button"
                className={watchedIconUrl ? "external-app-icon-picker has-image" : "external-app-icon-picker"}
                disabled={uploadingIcon}
                aria-label="上传应用图标"
              >
                <span className="external-app-icon-picker__preview">
                  {watchedIconUrl ? (
                    <Avatar shape="square" size={72} src={watchedIconUrl} icon={<PictureOutlined />} />
                  ) : (
                    <PictureOutlined />
                  )}
                </span>
                <span className="external-app-icon-picker__text">
                  {uploadingIcon ? "上传中..." : watchedIconUrl ? "更换图标" : "点击上传图标"}
                </span>
                <span className="external-app-icon-picker__hint">PNG / JPG</span>
              </button>
            </Upload>
          </Form.Item>

          <Form.Item noStyle shouldUpdate={(prev, curr) => prev.appType !== curr.appType}>
            {({ getFieldValue }) => getFieldValue("appType") === "native" ? (
              <>
                <Form.Item label="上传 APK">
                  <Upload showUploadList={false} beforeUpload={(file) => { void handleUploadApk(file as File); return Upload.LIST_IGNORE; }}>
                    <Button icon={<UploadOutlined />} loading={uploadingApk}>上传并回填 APK 信息</Button>
                  </Upload>
                </Form.Item>
                <Row gutter={16}>
                  <Col span={12}><Form.Item name={["appInfo", "versionName"]} label="版本号"><Input placeholder="如 1.0.0" /></Form.Item></Col>
                  <Col span={12}><Form.Item name={["appInfo", "packageName"]} label="包名"><Input placeholder="com.example.app" /></Form.Item></Col>
                </Row>
                <Form.Item name={["appInfo", "apkUrl"]} label="APK 地址" rules={[{ required: true, message: "请上传或填写 APK 地址" }]}><Input prefix={<LinkOutlined />} placeholder="https://..." /></Form.Item>
              </>
            ) : (
              <>
                <Row gutter={16}>
                  <Col span={12}><Form.Item name={["appInfo", "versionName"]} label="版本号"><Input placeholder="可选" /></Form.Item></Col>
                  <Col span={12}><Form.Item name={["appInfo", "webUrl"]} label="Web 地址" rules={[{ required: true, message: "请输入 Web 地址" }]}><Input prefix={<GlobalOutlined />} placeholder="https://..." /></Form.Item></Col>
                </Row>
              </>
            )}
          </Form.Item>

          <Form.Item name="description" label="应用描述"><TextArea rows={3} placeholder="请输入应用用途说明" /></Form.Item>
          <Row gutter={16}>
            <Col span={12}><Form.Item name="sortOrder" label="排序权重"><InputNumber min={0} style={{ width: "100%" }} /></Form.Item></Col>
            <Col span={12}><Form.Item name="remark" label="备注"><Input placeholder="选填" /></Form.Item></Col>
          </Row>
          <Form.Item name="statusEnabled" label="启用状态" valuePropName="checked"><Switch /></Form.Item>
        </Form>
      </Drawer>
    </PageContainer>
  );
}
