"use client";

import type { WpSiteUser } from "@domainops/shared-types";
import { App, Button, Form, Input, Modal, Popconfirm, Tooltip } from "antd";
import { CopyOutlined, EyeInvisibleOutlined, EyeOutlined, KeyOutlined, ReloadOutlined } from "@ant-design/icons";
import { useState } from "react";
import { revealWpUserPassword, setWpUserPassword } from "@/lib/api/wordpress";
import { ApiError } from "@/lib/api/client";

/**
 * A WordPress login's password: hidden by default, shown or copied only on
 * request (each reveal is audited server-side), changed to a chosen value or
 * reset to a generated one. Whatever is set is applied on the live site first.
 */
export function PasswordCell({
  user,
  canReveal,
  canManage,
  onChanged,
}: {
  user: WpSiteUser;
  canReveal: boolean;
  canManage: boolean;
  onChanged: () => void;
}) {
  const { message } = App.useApp();
  const [password, setPassword] = useState<string | null>(null);
  const [isShown, setIsShown] = useState(false);
  const [isBusy, setIsBusy] = useState(false);
  const [isChangeOpen, setIsChangeOpen] = useState(false);
  const [form] = Form.useForm<{ password: string }>();

  async function fetchPassword(): Promise<string | null> {
    if (password !== null) return password;

    try {
      const result = await revealWpUserPassword(user.id);

      if (result.password === null || result.password === "") {
        message.info("No password is stored for this login - use Change or Reset to set one.");

        return null;
      }

      setPassword(result.password);

      return result.password;
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't read that password.");

      return null;
    }
  }

  async function handleToggle() {
    if (isShown) {
      setIsShown(false);

      return;
    }

    if ((await fetchPassword()) !== null) setIsShown(true);
  }

  async function handleCopy() {
    const value = await fetchPassword();
    if (value === null) return;

    try {
      await navigator.clipboard.writeText(value);
      message.success("Password copied.");
    } catch {
      message.error("Couldn't copy - show the password and copy it by hand.");
    }
  }

  async function apply(next?: string) {
    setIsBusy(true);
    try {
      const result = await setWpUserPassword(user.id, next);
      setPassword(result.password);
      setIsShown(true);
      message.success(next ? "Password changed on the site." : "Password reset on the site - the new one is shown.");
      setIsChangeOpen(false);
      form.resetFields();
      onChanged();
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't change that password.");
    } finally {
      setIsBusy(false);
    }
  }

  return (
    <div className="flex items-center gap-1 flex-wrap dms_wp_password_cell">
      <span className="font-mono dms_wp_password_value" style={{ minWidth: 70 }}>
        {isShown && password !== null ? password : "••••••••"}
      </span>
      {canReveal && (
        <>
          <Tooltip title={isShown ? "Hide" : "Show"}>
            <Button size="small" type="text" icon={isShown ? <EyeInvisibleOutlined /> : <EyeOutlined />} onClick={() => void handleToggle()} className="dms_wp_password_toggle_btn" />
          </Tooltip>
          <Tooltip title="Copy">
            <Button size="small" type="text" icon={<CopyOutlined />} onClick={() => void handleCopy()} className="dms_wp_password_copy_btn" />
          </Tooltip>
        </>
      )}
      {canManage && (
        <>
          <Tooltip title="Set a new password">
            <Button size="small" icon={<KeyOutlined />} onClick={() => setIsChangeOpen(true)} className="dms_wp_password_change_btn">
              Change
            </Button>
          </Tooltip>
          <Popconfirm
            title={`Reset the password for ${user.username}?`}
            description="A new random password is set on the site now. The old one stops working."
            okText="Reset"
            onConfirm={() => apply()}
          >
            <Button size="small" icon={<ReloadOutlined />} loading={isBusy} className="dms_wp_password_reset_btn">
              Reset
            </Button>
          </Popconfirm>
        </>
      )}

      <Modal
        title={`Change password - ${user.username}`}
        open={isChangeOpen}
        onCancel={() => setIsChangeOpen(false)}
        onOk={() => form.submit()}
        okText="Change password"
        confirmLoading={isBusy}
        mask={{ closable: false }}
        destroyOnHidden
        className="dms_wp_password_modal"
      >
        <Form form={form} layout="vertical" onFinish={(values) => apply(values.password)} className="dms_wp_password_form">
          <Form.Item
            className="dms_wp_password_new_field"
            name="password"
            label="New password"
            rules={[{ required: true, message: "Enter a new password" }, { min: 8, message: "At least 8 characters" }]}
          >
            <Input.Password autoComplete="new-password" className="dms_wp_password_new_input" />
          </Form.Item>
        </Form>
      </Modal>
    </div>
  );
}
