"use client";

import type { TwoFactorDevice } from "@domainops/shared-types";
import { App, Button, Card, Form, Input, List, Modal, Tag, Typography } from "antd";
import { DeleteOutlined } from "@ant-design/icons";
import { useCallback, useEffect, useState } from "react";
import { listTwoFactorDevices, removeTwoFactorDevice, renameTwoFactorDevice } from "@/lib/api/auth";
import { ApiError } from "@/lib/api/client";
import { TwoFactorEnrollForm } from "@/components/features/TwoFactorEnrollForm";
import { useAuth } from "@/lib/auth/AuthProvider";

const MAX_DEVICES = 2;

interface RemoveCodeFormValues {
  code: string;
}

export function TwoFactorDevicesCard() {
  const { message } = App.useApp();
  const { refresh } = useAuth();
  const [devices, setDevices] = useState<TwoFactorDevice[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [isAdding, setIsAdding] = useState(false);
  const [removingDevice, setRemovingDevice] = useState<TwoFactorDevice | null>(null);
  const [isRemoving, setIsRemoving] = useState(false);
  const [removeForm] = Form.useForm<RemoveCodeFormValues>();

  const load = useCallback(async () => {
    setIsLoading(true);
    try {
      setDevices(await listTwoFactorDevices());
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't load your devices.");
    } finally {
      setIsLoading(false);
    }
  }, [message]);

  useEffect(() => {
    // eslint-disable-next-line react-hooks/set-state-in-effect
    void load();
  }, [load]);

  function handleEnrolled(device: TwoFactorDevice) {
    setDevices((prev) => [...prev, device]);
    setIsAdding(false);
    void refresh();
  }

  async function handleRename(device: TwoFactorDevice, label: string) {
    if (!label.trim() || label === device.label) return;
    try {
      const updated = await renameTwoFactorDevice(device.id, label.trim());
      setDevices((prev) => prev.map((d) => (d.id === device.id ? updated : d)));
      message.success("Device renamed.");
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't rename that device.");
    }
  }

  async function handleRemoveConfirm(values: RemoveCodeFormValues) {
    if (!removingDevice) return;
    setIsRemoving(true);
    try {
      await removeTwoFactorDevice(removingDevice.id, values.code);
      message.success(`${removingDevice.label} removed.`);
      setDevices((prev) => prev.filter((d) => d.id !== removingDevice.id));
      setRemovingDevice(null);
      removeForm.resetFields();
      void refresh();
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "That code didn't work.");
    } finally {
      setIsRemoving(false);
    }
  }

  const canAddMore = devices.length < MAX_DEVICES;

  return (
    <Card title="Two-Factor Authentication" loading={isLoading} className="dms_2fa_devices_card">
      <Typography.Paragraph type="secondary">
        Up to {MAX_DEVICES} authenticator devices (e.g. a phone and a backup). A code from any of them signs you
        in.
      </Typography.Paragraph>

      <List
        className="dms_2fa_devices_list"
        dataSource={devices}
        locale={{ emptyText: "No devices enrolled yet." }}
        renderItem={(device) => (
          <List.Item
            className="dms_2fa_device_row"
            actions={[
              <Button
                key="remove"
                size="small"
                danger
                icon={<DeleteOutlined />}
                onClick={() => setRemovingDevice(device)}
                className="dms_2fa_remove_device_btn"
              >
                Remove
              </Button>,
            ]}
          >
            <List.Item.Meta
              title={
                <Typography.Text
                  editable={{
                    onChange: (value) => handleRename(device, value),
                    tooltip: "Rename this device",
                  }}
                  className="dms_2fa_device_label_text"
                >
                  {device.label}
                </Typography.Text>
              }
              description={
                <span className="flex gap-2 items-center flex-wrap">
                  {device.platform && <Tag>{device.platform}</Tag>}
                  {device.enrolled_ip && <Tag>Enrolled from {device.enrolled_ip}</Tag>}
                  <Tag>Added {new Date(device.created_at).toLocaleDateString()}</Tag>
                  <span>
                    {device.last_used_at
                      ? `Last used ${new Date(device.last_used_at).toLocaleString()}`
                      : "Never used"}
                  </span>
                </span>
              }
            />
          </List.Item>
        )}
      />

      {canAddMore &&
        (isAdding ? (
          <TwoFactorEnrollForm autoStart onEnrolled={handleEnrolled} onCancel={() => setIsAdding(false)} />
        ) : (
          <Button
            type="primary"
            onClick={() => setIsAdding(true)}
            className="dms_2fa_add_device_btn"
            style={{ marginTop: devices.length ? 16 : 0 }}
          >
            Add a device
          </Button>
        ))}

      <Modal
        title={`Remove "${removingDevice?.label}"?`}
        open={!!removingDevice}
        onCancel={() => {
          setRemovingDevice(null);
          removeForm.resetFields();
        }}
        onOk={() => removeForm.submit()}
        okButtonProps={{ danger: true, loading: isRemoving }}
        className="dms_2fa_remove_device_modal"
        destroyOnHidden
      >
        <Typography.Paragraph type="secondary">
          Enter a current code from any of your enrolled devices to confirm.
        </Typography.Paragraph>
        <Form<RemoveCodeFormValues> form={removeForm} layout="vertical" onFinish={handleRemoveConfirm}>
          <Form.Item
            name="code"
            label="Authentication code"
            rules={[{ required: true, len: 6, message: "6-digit code" }]}
            className="dms_2fa_remove_code_field"
          >
            <Input placeholder="123456" inputMode="numeric" maxLength={6} autoFocus />
          </Form.Item>
        </Form>
      </Modal>
    </Card>
  );
}
