import { Button, Card, Drawer, Form, Input, Popconfirm, Select, Space, Table, Tag, Typography, message } from "antd";
import { DeleteOutlined, DesktopOutlined, EditOutlined, PlusOutlined, SearchOutlined, UserOutlined } from "@ant-design/icons";
import { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { createDevice, deleteDevice, listDevices, listUsers, updateDevice } from "@/api";
import PageHeader from "@/components/shared/PageHeader";
import { useDict } from "@/hooks/useDict";
import { usePermission } from "@/hooks/usePermission";
import type { DeviceInfo, SysUser } from "@/types";
import { getStandardPagination } from "@/utils/pagination";
import "./index.less";

const { Text } = Typography;

type DeviceFormValues = {
  userId: number;
  deviceCode: string;
  deviceName?: string;
  status: number;
};

export default function Devices() {
  const { t } = useTranslation();
  const { can } = usePermission();
  const { items: statusDict } = useDict("sys_common_status");
  const [loading, setLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [searchText, setSearchText] = useState("");

  const handleSearch = () => {};

  const handleResetSearch = () => {
    setSearchText("");
  };
  const [devices, setDevices] = useState<DeviceInfo[]>([]);
  const [users, setUsers] = useState<SysUser[]>([]);
  const [open, setOpen] = useState(false);
  const [editing, setEditing] = useState<DeviceInfo | null>(null);
  const [form] = Form.useForm<DeviceFormValues>();

  const loadData = async () => {
    setLoading(true);
    try {
      const [deviceList, userList] = await Promise.all([listDevices(), listUsers()]);
      setDevices(deviceList || []);
      setUsers(userList || []);
    } finally {
      setLoading(false);
    }
  };

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

  const userMap = useMemo(() => {
    const map: Record<number, SysUser> = {};
    users.forEach((user) => {
      map[user.userId] = user;
    });
    return map;
  }, [users]);

  const filteredData = useMemo(() => {
    if (!searchText) {
      return devices;
    }
    const lower = searchText.toLowerCase();
    return devices.filter((device) => {
      const owner = userMap[device.userId];
      return (
        device.deviceCode.toLowerCase().includes(lower) ||
        (device.deviceName || "").toLowerCase().includes(lower) ||
        (owner?.displayName || "").toLowerCase().includes(lower) ||
        String(device.userId).includes(lower)
      );
    });
  }, [devices, searchText, userMap]);

  const openCreate = () => {
    setEditing(null);
    form.resetFields();
    form.setFieldsValue({ status: 1 });
    setOpen(true);
  };

  const openEdit = (record: DeviceInfo) => {
    setEditing(record);
    form.setFieldsValue({
      userId: record.userId,
      deviceCode: record.deviceCode,
      deviceName: record.deviceName,
      status: record.status ?? 1
    });
    setOpen(true);
  };

  const submit = async () => {
    const values = await form.validateFields();
    setSaving(true);
    try {
      const payload: Partial<DeviceInfo> = {
        userId: values.userId,
        deviceCode: values.deviceCode,
        deviceName: values.deviceName,
        status: values.status
      };

      if (editing) {
        await updateDevice(editing.deviceId, payload);
      } else {
        await createDevice(payload);
      }

      message.success(t("devicesExt.operationSucceeded"));
      setOpen(false);
      await loadData();
    } finally {
      setSaving(false);
    }
  };

  const remove = async (id: number) => {
    await deleteDevice(id);
    message.success(t("devicesExt.operationSucceeded"));
    await loadData();
  };

  return (
    <div className="app-page devices-page">
      <PageHeader title={t("devices.title")} subtitle={t("devices.subtitle")} />

      <Card className="devices-table-card app-page__filter-card" styles={{ body: { padding: "16px" } }}>
        <div className="app-page__toolbar" style={{ justifyContent: "space-between", width: "100%" }}>
          <div className="app-page__toolbar">
            <Input
              placeholder={t("devicesExt.searchPlaceholder")}
              prefix={<SearchOutlined aria-hidden="true" />}
              style={{ width: 360 }}
              value={searchText}
              onChange={(event) => setSearchText(event.target.value)}
              allowClear
              aria-label={t("devicesExt.searchLabel")}
            />
            <Button type="primary" icon={<SearchOutlined aria-hidden="true" />} onClick={handleSearch}>{t("common.search")}</Button>
            <Button onClick={handleResetSearch}>{t("common.reset")}</Button>
          </div>
          {can("device:create") ? (
            <Button type="primary" icon={<PlusOutlined aria-hidden="true" />} onClick={openCreate}>
              {t("common.create")}
            </Button>
          ) : null}
        </div>
      </Card>

      <Card className="app-page__content-card flex-1 flex flex-col overflow-hidden" styles={{ body: { padding: 0, flex: 1, display: "flex", flexDirection: "column", overflow: "hidden" } }}>
        <Table<DeviceInfo>
          rowKey="deviceId"
          dataSource={filteredData}
          loading={loading}
          size="middle"
          scroll={{ y: "calc(100vh - 350px)" }}
          pagination={getStandardPagination(filteredData.length, 1, 1000)}
          columns={[
            {
              title: t("devicesExt.device"),
              key: "device",
              render: (_value: unknown, record) => (
                <Space>
                  <div className="device-icon-placeholder">
                    <DesktopOutlined aria-hidden="true" />
                  </div>
                  <div>
                    <div className="device-name font-medium">{record.deviceName || t("devicesExt.unnamedDevice")}</div>
                    <div className="device-code text-xs text-gray-400 tabular-nums">{record.deviceCode}</div>
                  </div>
                </Space>
              )
            },
            {
              title: t("devices.owner"),
              key: "user",
              render: (_value: unknown, record) => {
                const owner = userMap[record.userId];
                return owner ? (
                  <Space>
                    <UserOutlined aria-hidden="true" style={{ color: "#8c8c8c" }} />
                    <span>{owner.displayName}</span>
                    <Text type="secondary" style={{ fontSize: "12px" }} className="tabular-nums">
                      ({t("devicesExt.ownerId")}: {record.userId})
                    </Text>
                  </Space>
                ) : (
                  <span className="tabular-nums">{t("devicesExt.ownerId")}: {record.userId}</span>
                );
              }
            },
            {
              title: t("common.status"),
              dataIndex: "status",
              width: 100,
              render: (status: number) => {
                const item = statusDict.find((dictItem) => dictItem.itemValue === String(status));
                return <Tag color={status === 1 ? "green" : "red"}>{item?.itemLabel || (status === 1 ? t("devicesExt.enabled") : t("devicesExt.disabled"))}</Tag>;
              }
            },
            {
              title: t("devices.updateTime"),
              dataIndex: "updatedAt",
              width: 180,
              render: (text: string) => (
                <Text type="secondary" className="tabular-nums">
                  {text?.replace("T", " ").substring(0, 19)}
                </Text>
              )
            },
            {
              title: t("common.action"),
              key: "action",
              width: 120,
              fixed: "right",
              render: (_value: unknown, record) => (
                <Space>
                  {can("device:update") ? (
                    <Button type="text" icon={<EditOutlined aria-hidden="true" />} onClick={() => openEdit(record)} aria-label={t("devicesExt.editDevice")} />
                  ) : null}
                  {can("device:delete") ? (
                    <Popconfirm title={t("devicesExt.deleteDevice")} onConfirm={() => remove(record.deviceId)}>
                      <Button type="text" danger icon={<DeleteOutlined aria-hidden="true" />} aria-label={t("common.delete")} />
                    </Popconfirm>
                  ) : null}
                </Space>
              )
            }
          ]}
        />
      </Card>

      <Drawer
        title={
          <div className="device-drawer-title">
            <DesktopOutlined className="mr-2" aria-hidden="true" />
            {editing ? t("devices.drawerTitleEdit") : t("devicesExt.drawerTitleCreate")}
          </div>
        }
        open={open}
        onClose={() => setOpen(false)}
        width={420}
        destroyOnClose
        footer={
          <div className="app-page__drawer-footer">
            <Button onClick={() => setOpen(false)}>{t("common.cancel")}</Button>
            <Button type="primary" loading={saving} onClick={submit}>
              {t("common.save")}
            </Button>
          </div>
        }
      >
        <Form form={form} layout="vertical">
          <Form.Item label={t("devices.owner")} name="userId" rules={[{ required: true, message: t("devicesExt.selectOwner") }]}>
            <Select
              showSearch
              placeholder={t("devicesExt.searchSelectUser")}
              optionFilterProp="label"
              options={users.map((user) => ({ label: `${user.displayName} (@${user.username})`, value: user.userId }))}
            />
          </Form.Item>
          <Form.Item label={t("devices.deviceCode")} name="deviceCode" rules={[{ required: true, message: t("devicesExt.deviceCodeRequired") }]}>
            <Input placeholder={t("devicesExt.deviceCodePlaceholder")} />
          </Form.Item>
          <Form.Item label={t("devices.deviceName")} name="deviceName">
            <Input placeholder={t("devicesExt.deviceNamePlaceholder")} />
          </Form.Item>
          <Form.Item label={t("common.status")} name="status" initialValue={1}>
            <Select options={statusDict.map((item) => ({ value: Number(item.itemValue), label: item.itemLabel }))} />
          </Form.Item>
        </Form>
      </Drawer>
    </div>
  );
}