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 { Dropdown } from "@/prime-react";
import { InputNumber } from "@/prime-react";
import { InputText } from "@/prime-react";
import { Message } from "@/prime-react";
import { MultiSelect } from "@/prime-react";
import { ProgressSpinner } from "@/prime-react";
import { Tag } from "@/prime-react";
import { useConfirm } from "@/shared/ConfirmDialog";
import { notifyError, notifySuccess } from "../shared/toast";

// What THIS organization asks its own members, on top of the platform-wide profile.
//
// The endpoints existed since the org-scoped config was built, but nothing ever called them: a
// tenant could SEE these fields (on Members, and on the customer's own profile) and fill them in,
// while having no way to define them. Found 20/08/2026 by asking where user_org_detail_config is
// set — the answer was nowhere.
//
// Not to be confused with the admin's User Detail Config. That one is GLOBAL, lives on the admin
// panel, and shares this URL path on a different host; this one is per-tenant and can be narrowed
// to particular user types.
//
// Mirrors App\Enums\DetailFieldType.
const TYPES = [
    { label: "Text (short)", value: 1 },  { label: "Text (long)", value: 2 },
    { label: "Email", value: 3 },         { label: "Phone", value: 4 },
    { label: "URL", value: 5 },           { label: "Whole number", value: 6 },
    { label: "Decimal", value: 7 },       { label: "Yes / No", value: 8 },
    { label: "Date", value: 9 },          { label: "Time", value: 10 },
    { label: "Date & time", value: 11 },  { label: "Choose one", value: 12 },
    { label: "Choose many", value: 13 },  { label: "File", value: 14 },
    { label: "Image", value: 15 },        { label: "JSON", value: 16 },
];
const NEEDS_OPTIONS = [12, 13];

const blank = () => ({
    open: false, id: null, key: "", label: "", description: "",
    type: 1, options: "", required: 0, enabled: 1, order: 0, user_type_ids: [],
    busy: false, error: null,
});

const MemberFields = () => {
    const [confirmEl, confirm] = useConfirm();
    const [fields, setFields] = useState([]);
    const [userTypes, setUserTypes] = useState([]);
    const [loading, setLoading] = useState(true);
    const [edit, setEdit] = useState(blank());

    const load = async () => {
        setLoading(true);
        try {
            // Two calls: the config list does not carry the user types, and the restriction
            // control is unusable without their names.
            const [f, t] = await Promise.all([
                axios.get("/user_detail_config/list"),
                axios.get("/user_type/list"),
            ]);
            setFields(Array.isArray(f.data) ? f.data : (f.data?.items || []));
            setUserTypes(Array.isArray(t.data) ? t.data : (t.data?.items || []));
        } catch (err) {
            notifyError(err.response?.data?.message || "Could not load fields.");
        } finally {
            setLoading(false);
        }
    };

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

    const openEdit = (row) => setEdit({
        ...blank(), open: true,
        id: row._id || row.id,
        key: row.key || "", label: row.label || "", description: row.description || "",
        type: row.type ?? 1,
        options: (row.options || []).join(", "),
        required: row.required ?? 0, enabled: row.enabled ?? 1, order: row.order ?? 0,
        user_type_ids: (row.user_type_ids || []).map(Number),
    });

    const save = async () => {
        setEdit(e => ({ ...e, busy: true, error: null }));
        const payload = {
            key: edit.key, label: edit.label, description: edit.description || null,
            type: edit.type, required: edit.required, enabled: edit.enabled, order: edit.order,
            user_type_ids: edit.user_type_ids,
            options: NEEDS_OPTIONS.includes(edit.type)
                ? edit.options.split(",").map(o => o.trim()).filter(Boolean)
                : [],
        };
        try {
            if (edit.id) await axios.put("/user_detail_config/edit", { id: edit.id, ...payload });
            else         await axios.post("/user_detail_config/create", payload);
            setEdit(blank());
            notifySuccess("Saved.");
            await load();
        } catch (err) {
            setEdit(e => ({ ...e, busy: false, error: err.response?.data?.message || "Could not save." }));
        }
    };

    const remove = async (row) => {
        const ok = await confirm({
            title: `Remove "${row.label || row.key}"?`,
            body: "The field stops being asked. Values already recorded are KEPT — they reappear if you add the field back.",
            confirmLabel: "Remove",
            destructive: true,
        });
        if (!ok) return;

        try {
            await axios.post("/user_detail_config/delete", { id: row._id || row.id });
            notifySuccess("Field removed.");
            await load();
        } catch (err) {
            notifyError(err.response?.data?.message || "Could not remove.");
        }
    };

    // An empty list means every member, not "nobody" — the opposite of what a blank cell suggests.
    const scopeBody = (row) => {
        const ids = (row.user_type_ids || []).map(Number);
        if (ids.length === 0) return <span style={{ color: "var(--muted)" }}>every member</span>;
        return (
            <div style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
                {ids.map(id => <Tag key={id} value={userTypes.find(t => Number(t.id) === id)?.name || `#${id}`} />)}
            </div>
        );
    };

    return (
        <div className="pt-fade-in">
            {confirmEl}
            <div className="pt-page-head">
                <div>
                    <h2>Member fields</h2>
                    <p>What your organization asks its own members, on top of the platform profile. Leave the user types empty to ask everyone.</p>
                </div>
                <Button icon="pi pi-plus" label="New field" className="p-button-sm"
                    onClick={() => setEdit({ ...blank(), open: true })} />
            </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={fields} dataKey="_id" emptyMessage="No fields yet.">
                        <Column field="label" header="Label" />
                        <Column field="key" header="Key" body={(r) => (
                            <span style={{ fontFamily: "var(--mono)", fontSize: 12.5 }}>{r.key}</span>
                        )} />
                        <Column header="Type" body={(r) => TYPES.find(t => t.value === r.type)?.label || r.type} />
                        <Column header="Asked of" body={scopeBody} />
                        <Column header="Required" style={{ width: 100 }}
                            body={(r) => r.required === 1 ? <Tag severity="warning" value="required" /> : "—"} />
                        <Column header="Status" style={{ width: 110 }}
                            body={(r) => r.enabled === 1
                                ? <Tag severity="success" value="on" />
                                : <Tag severity="danger" value="off" />} />
                        <Column header="" style={{ width: 150, textAlign: "right" }} body={(row) => (
                            <div style={{ display: "flex", gap: 6, justifyContent: "flex-end" }}>
                                <Button icon="pi pi-pencil" className="p-button-sm p-button-info" onClick={() => openEdit(row)} />
                                <Button icon="pi pi-trash" className="p-button-sm p-button-danger" onClick={() => remove(row)} />
                            </div>
                        )} />
                    </DataTable>
                )}
            </div>

            <Dialog visible={edit.open} onHide={() => !edit.busy && setEdit(blank())}
                header={edit.id ? "Edit field" : "New field"} style={{ width: "32rem" }}>
                <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
                    <div>
                        <label htmlFor="mf-label" className="form-label">Label</label>
                        <InputText id="mf-label" value={edit.label} disabled={edit.busy} style={{ width: "100%" }}
                            placeholder="e.g. Emergency contact"
                            onChange={(e) => setEdit(s => ({ ...s, label: e.target.value }))} />
                    </div>
                    <div>
                        <label htmlFor="mf-key" className="form-label">Key</label>
                        <InputText id="mf-key" value={edit.key} disabled={edit.busy || !!edit.id} style={{ width: "100%" }}
                            placeholder="emergency_contact"
                            onChange={(e) => setEdit(s => ({ ...s, key: e.target.value }))} />
                        <small style={{ color: "var(--muted)" }}>
                            Lowercase letters, digits and underscores. Unique within your organization, and fixed
                            once created, because it is how stored values are found.
                        </small>
                    </div>
                    <div>
                        <label htmlFor="mf-type" className="form-label">Type</label>
                        <Dropdown id="mf-type" value={edit.type} options={TYPES} disabled={edit.busy}
                            style={{ width: "100%" }} onChange={(e) => setEdit(s => ({ ...s, type: e.value }))} />
                    </div>
                    {NEEDS_OPTIONS.includes(edit.type) && (
                        <div>
                            <label htmlFor="mf-options" className="form-label">Choices</label>
                            <InputText id="mf-options" value={edit.options} disabled={edit.busy} style={{ width: "100%" }}
                                placeholder="Morning, Afternoon, Evening"
                                onChange={(e) => setEdit(s => ({ ...s, options: e.target.value }))} />
                            <small style={{ color: "var(--muted)" }}>Comma separated.</small>
                        </div>
                    )}
                    <div>
                        <label htmlFor="mf-types" className="form-label">Ask which members</label>
                        <MultiSelect id="mf-types" value={edit.user_type_ids} options={userTypes}
                            optionLabel="name" optionValue="id" display="chip" disabled={edit.busy}
                            placeholder="Every member" style={{ width: "100%" }}
                            onChange={(e) => setEdit(s => ({ ...s, user_type_ids: e.value }))} />
                        <small style={{ color: "var(--muted)" }}>
                            Leave empty to ask everyone. Narrowed to a type, the field is only shown to — and only
                            enforced on — members who hold it.
                        </small>
                    </div>
                    <div style={{ display: "flex", gap: 10 }}>
                        <div style={{ flex: 1 }}>
                            <label htmlFor="mf-required" className="form-label">Required</label>
                            <Dropdown id="mf-required" value={edit.required} disabled={edit.busy} style={{ width: "100%" }}
                                options={[{ label: "Optional", value: 0 }, { label: "Required", value: 1 }]}
                                onChange={(e) => setEdit(s => ({ ...s, required: e.value }))} />
                        </div>
                        <div style={{ flex: 1 }}>
                            <label htmlFor="mf-enabled" className="form-label">Status</label>
                            <Dropdown id="mf-enabled" value={edit.enabled} disabled={edit.busy} style={{ width: "100%" }}
                                options={[{ label: "On", value: 1 }, { label: "Off", value: 0 }]}
                                onChange={(e) => setEdit(s => ({ ...s, enabled: e.value }))} />
                        </div>
                        <div style={{ width: 110 }}>
                            <label htmlFor="mf-order" className="form-label">Order</label>
                            <InputNumber id="mf-order" value={edit.order} disabled={edit.busy} min={0}
                                onValueChange={(e) => setEdit(s => ({ ...s, order: e.value ?? 0 }))} style={{ width: "100%" }} />
                        </div>
                    </div>

                    {edit.error && <Message severity="error" text={edit.error} />}

                    <div style={{ display: "flex", justifyContent: "flex-end", gap: 8 }}>
                        <Button label="Cancel" className="p-button-sm p-button-secondary" disabled={edit.busy}
                            onClick={() => setEdit(blank())} />
                        <Button label={edit.busy ? "Saving…" : "Save"} className="p-button-sm" loading={edit.busy}
                            disabled={edit.busy || !edit.key || !edit.label} onClick={save} />
                    </div>
                </div>
            </Dialog>
        </div>
    );
};

export default MemberFields;
