import React, { useEffect, useState } from "react";
import axios from "axios";
import { Button } from "@/prime-react";
import { Column } from "@/prime-react";
import { DataTable } from "@/prime-react";
import { Dialog } from "@/prime-react";
import { InputText } from "@/prime-react";
import { Message } from "@/prime-react";
import { ProgressSpinner } from "@/prime-react";
import { Tag } from "@/prime-react";

const STATUS_SEVERITY = {
    pending:  "info",
    accepted: "success",
    expired:  "warning",
    revoked:  "danger",
};

// "Could not send the invitation email" is true and useless — it is the same sentence whether the
// mailbox is wrong, the credentials are stale or the sending domain is unverified. The controller
// ALREADY returns the underlying reason as `detail`; the panel was dropping it, so an operator on a
// server they cannot SSH into had no way to find out what happened. Show both. (Arfu, 03/09/2026)
function errorText(err, fallback) {
    const body = err?.response?.data || {};
    const head = body.message || fallback;

    return body.detail ? `${head}\n\n${body.detail}` : head;
}

const OrganizationInvitation = () => {
    const [items, setItems] = useState([]);
    const [loading, setLoading] = useState(true);
    const [dialogVisible, setDialogVisible] = useState(false);
    const [email, setEmail] = useState("");
    const [error, setError] = useState(null);
    const [info, setInfo] = useState(null);
    const [sending, setSending] = useState(false);

    // Inline confirm dialog state (resend / revoke)
    const [confirmState, setConfirmState] = useState({
        visible: false,
        action: null,    // "resend" | "revoke"
        id: null,
        running: false,
        error: null,
        info: null,
    });

    const load = async () => {
        setLoading(true);
        try {
            const res = await axios.get("/organization_invitation/list");
            setItems(res.data || []);
        } catch (err) {
            console.error(err);
        } finally {
            setLoading(false);
        }
    };

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

    const openSend = () => {
        setEmail("");
        setError(null);
        setInfo(null);
        setDialogVisible(true);
    };

    const send = async () => {
        setSending(true);
        setError(null);
        try {
            const res = await axios.post("/organization_invitation/send", { email });
            setInfo(res.data?.message || "Sent.");
            await load();
            setTimeout(() => setDialogVisible(false), 600);
        } catch (err) {
            setError(errorText(err, "Failed to send invitation."));
        } finally {
            setSending(false);
        }
    };

    const openConfirm = (action, id) => {
        setConfirmState({ visible: true, action, id, running: false, error: null, info: null });
    };

    const closeConfirm = () => {
        if (confirmState.running) return;
        setConfirmState({ visible: false, action: null, id: null, running: false, error: null, info: null });
    };

    const runConfirm = async () => {
        const { action, id } = confirmState;
        const endpoint = action === "resend"
            ? "/organization_invitation/resend"
            : "/organization_invitation/revoke";
        const successLabel = action === "resend"
            ? "A fresh invitation link has been emailed."
            : "Invitation revoked.";

        setConfirmState(s => ({ ...s, running: true, error: null, info: null }));
        try {
            await axios.post(endpoint, { id });
            setConfirmState(s => ({ ...s, running: false, info: successLabel }));
            await load();
            setTimeout(() => setConfirmState({ visible: false, action: null, id: null, running: false, error: null, info: null }), 700);
        } catch (err) {
            setConfirmState(s => ({
                ...s,
                running: false,
                error: errorText(err, action === "resend"
                    ? "Could not resend the invitation."
                    : "Could not revoke the invitation."),
            }));
        }
    };

    const confirmMeta = {
        resend: {
            header:    "Resend invitation",
            message:   "Resend this invitation? The previous link will stop working.",
            confirm:   "Resend",
            icon:      "pi pi-refresh",
            danger:    false,
        },
        revoke: {
            header:    "Revoke invitation",
            message:   "Revoke this invitation? The link will stop working immediately.",
            confirm:   "Revoke",
            icon:      "pi pi-times",
            danger:    true,
        },
    };

    const dateBody = (val) => val ? new Date(val).toLocaleString("en-HK") : "—";
    const statusBody = (row) => <Tag severity={STATUS_SEVERITY[row.status] || "info"} value={row.status} />;
    const actionsBody = (row) => {
        const isPending = row.status === "pending";
        // Revoked is a decision that this link must stop working, so it is not resendable — the
        // server refuses it, and offering the button would only produce an error. Expired is the
        // opposite: nothing was decided, it ran out, and a resend is the remedy. To bring back a
        // revoked one, invite the address again; a revoked row does not hold it.
        const canResend = isPending || row.status === "expired";
        return (
            <div style={{ display: "flex", gap: 6 }}>
                {canResend && (
                    <Button icon="pi pi-refresh" label="Resend" className="p-button-sm p-button-info"
                        onClick={() => openConfirm("resend", row.id)} />
                )}
                {isPending && (
                    <Button icon="pi pi-times" label="Revoke" className="p-button-sm p-button-danger"
                        onClick={() => openConfirm("revoke", row.id)} />
                )}
            </div>
        );
    };

    return (
        <div className="pt-fade-in">
            <div className="pt-page-head">
                <div>
                    <h2>Organization invitations</h2>
                    <p>Invite organizations to onboard. They'll receive a one-time link valid for 7 days.</p>
                </div>
                <div style={{ display: "flex", gap: 8 }}>
                    <Button icon="pi pi-refresh" label="Refresh" className="p-button-sm p-button-info" onClick={load} />
                    <Button icon="pi pi-plus" label="Invite" className="p-button-sm" onClick={openSend} />
                </div>
            </div>

            <div className="pt-card">
                {loading ? (
                    <div style={{ display: "flex", justifyContent: "center", padding: "40px 0" }}>
                        <ProgressSpinner style={{ width: "2.5rem", height: "2.5rem" }} />
                    </div>
                ) : (
                    <DataTable value={items} paginator rows={10} emptyMessage="No invitations sent yet.">
                        <Column field="id" header="ID" style={{ width: 70 }} />
                        <Column field="email" header="Email" />
                        <Column header="Status" body={statusBody} style={{ width: 130 }} />
                        <Column header="Expires" body={(r) => dateBody(r.expires_at)} />
                        <Column header="Sent" body={(r) => dateBody(r.created_at)} />
                        <Column header="Actions" body={actionsBody} style={{ width: 220 }} />
                    </DataTable>
                )}
            </div>

            <Dialog visible={dialogVisible} onHide={() => !sending && setDialogVisible(false)}
                closable={!sending} closeOnEscape={!sending}
                header="Invite an organization" style={{ width: "28rem" }}>
                <div style={{ display: "flex", flexDirection: "column", gap: 14, position: "relative" }}>
                    <div>
                        <label htmlFor="invite-email" className="form-label">Email</label>
                        <InputText id="invite-email" value={email} onChange={(e) => setEmail(e.target.value)}
                            placeholder="orgname@example.com" autoComplete="off" disabled={sending} />
                    </div>
                    {error && <Message severity="error" text={error} style={{ whiteSpace: "pre-line", wordBreak: "break-word" }} />}
                    {info && <Message severity="success" text={info} />}
                    <div style={{ display: "flex", justifyContent: "flex-end", gap: 8 }}>
                        <Button label="Cancel" className="p-button-sm p-button-secondary"
                            onClick={() => setDialogVisible(false)} disabled={sending} />
                        <Button label={sending ? "Sending…" : "Send invitation"}
                            icon={sending ? null : "pi pi-send"} loading={sending}
                            className="p-button-sm" onClick={send} disabled={sending || !email} />
                    </div>
                </div>
            </Dialog>

            <Dialog visible={confirmState.visible}
                onHide={closeConfirm}
                closable={!confirmState.running} closeOnEscape={!confirmState.running}
                header={confirmState.action ? confirmMeta[confirmState.action].header : ""}
                style={{ width: "26rem" }}>
                {confirmState.action && (
                    <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
                        <p style={{ margin: 0, color: "var(--ink-2)", fontSize: 14, lineHeight: 1.55 }}>
                            {confirmMeta[confirmState.action].message}
                        </p>
                        {confirmState.error && <Message severity="error" text={confirmState.error} />}
                        {confirmState.info && <Message severity="success" text={confirmState.info} />}
                        <div style={{ display: "flex", justifyContent: "flex-end", gap: 8 }}>
                            <Button label="Cancel" className="p-button-sm p-button-secondary"
                                onClick={closeConfirm} disabled={confirmState.running} />
                            <Button label={confirmState.running ? "Working…" : confirmMeta[confirmState.action].confirm}
                                icon={confirmState.running ? null : confirmMeta[confirmState.action].icon}
                                loading={confirmState.running}
                                className={`p-button-sm ${confirmMeta[confirmState.action].danger ? "p-button-danger" : ""}`}
                                onClick={runConfirm} disabled={confirmState.running} />
                        </div>
                    </div>
                )}
            </Dialog>
        </div>
    );
};

export default OrganizationInvitation;
