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 { Message } from "@/prime-react";
import { ProgressSpinner } from "@/prime-react";
import { Tag } from "@/prime-react";
import FlowGraph from "@/shared/FlowGraph";
import { FLOW_KIND, FLOW_KIND_CODE, FLOW_STATUS, FLOW_STATUS_CODE } from "@/shared/status";
import ChatflowFilters, { ALL, asParams, EMPTY_FILTERS } from "../shared/ChatflowFilters";

// Status and kind are INT-backed enums on the row (App\Enums\FlowStatus / FlowKind). The page
// used to hand `row.status` straight to a <Tag> and colour it by the strings "draft"/"published",
// so every flow on the platform rendered as a blue "2".
const STATUSES = [
    { label: "All statuses", value: ALL },
    { label: "Draft",        value: FLOW_STATUS.DRAFT },
    { label: "Published",    value: FLOW_STATUS.PUBLISHED },
    { label: "Archived",     value: FLOW_STATUS.ARCHIVED },
];

const KINDS = [
    { label: "All kinds",    value: ALL },
    { label: "Conversation", value: FLOW_KIND.CONVERSATION },
    { label: "Child flow",   value: FLOW_KIND.CHILD },
];

const statusSeverity = (s) => ({
    [FLOW_STATUS.DRAFT]:     "warning",
    [FLOW_STATUS.PUBLISHED]: "success",
    [FLOW_STATUS.ARCHIVED]:  "secondary",
}[s] || "info");

const Chatflow = () => {
    const [flows, setFlows] = useState([]);
    const [organizations, setOrganizations] = useState([]);
    const [filters, setFilters] = useState(EMPTY_FILTERS);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);
    const [detail, setDetail] = useState(null);
    const [detailLoading, setDetailLoading] = useState(false);
    const [versionId, setVersionId] = useState(null);
    const [definition, setDefinition] = useState(null);
    const [view, setView] = useState("graph");

    const load = async (f = filters) => {
        setLoading(true);
        setError(null);
        try {
            const res = await axios.get("/flow/list", { params: asParams(f) });
            setFlows(res.data?.flows || []);
            setOrganizations(res.data?.organizations || []);
        } catch (err) {
            console.error(err);
            // An empty table and a failed request look identical otherwise, which is how a broken
            // screen reads as "no data" for a week.
            setError(err.response?.data?.message || "Could not load flows.");
            setFlows([]);
        } finally {
            setLoading(false);
        }
    };

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

    const apply = (f = filters) => { setFilters(f); load(f); };
    const clear = () => apply(EMPTY_FILTERS);

    const openDetail = async (row) => {
        setDetail({ id: row.id });
        setDetailLoading(true);
        setDefinition(null);
        setVersionId(null);
        setView("graph");
        try {
            const res = await axios.get("/flow/get", { params: { id: row.id } });
            setDetail(res.data);
            setDefinition(res.data?.definition || null);
            const opened = res.data?.versions?.find(v => v.version === res.data?.definition_version);
            setVersionId(opened?.id || res.data?.versions?.[0]?.id || null);
        } catch (err) {
            console.error(err);
            setDetail({ id: row.id, error: err.response?.data?.message || "Could not load this flow." });
        } finally {
            setDetailLoading(false);
        }
    };

    const loadVersion = async (id) => {
        setVersionId(id);
        try {
            const res = await axios.get("/flow_version/get", { params: { id } });
            setDefinition(res.data?.flow_version?.definition || null);
        } catch (err) {
            console.error(err);
            setDefinition(null);
        }
    };

    const orgBody = (row) => (
        row.organization_name
            ? <span>{row.organization_name} <span style={{ opacity: .55 }}>#{row.organization_id}</span></span>
            // A flow whose org is gone is test residue or a half-deleted tenant. Saying so beats a
            // blank cell, which is what the column showed for every one of them.
            : <span style={{ opacity: .6 }}>#{row.organization_id} (deleted)</span>
    );
    const keyBody = (row) => (
        <div>
            <code>{row.flow_key}</code>
            {row.name ? <div style={{ fontSize: 12, opacity: .7 }}>{row.name}</div> : null}
        </div>
    );
    const kindBody = (row) => (
        <Tag value={FLOW_KIND_CODE[row.kind] || "—"} severity={row.kind === FLOW_KIND.CHILD ? "warning" : "info"} />
    );
    const statusBody = (row) => (
        <Tag value={FLOW_STATUS_CODE[row.status] || row.status} severity={statusSeverity(row.status)} />
    );
    const dateBody = (k) => (row) => row[k] ? new Date(row[k]).toLocaleString("en-HK") : "—";
    const actionsBody = (row) => (
        <Button icon="pi pi-eye" label="Inspect" className="p-button-sm p-button-text" onClick={() => openDetail(row)} />
    );

    const versionOptions = (detail?.versions || []).map(v => ({
        label: `v${v.version} · ${v.node_count} node${v.node_count === 1 ? "" : "s"}`,
        value: v.id,
    }));

    return (
        <div className="pt-fade-in">
            <div className="pt-page-head">
                <div>
                    <h2>Flows</h2>
                    <p>All chatflows across organizations.</p>
                </div>
                <Button icon="pi pi-refresh" label="Refresh" className="p-button-sm p-button-info" onClick={() => load()} />
            </div>

            <ChatflowFilters
                value={filters} onChange={setFilters} onApply={apply} onClear={clear} busy={loading}
                organizations={organizations} statuses={STATUSES} kinds={KINDS}
                placeholder="Search flow key or name…"
            />

            <div className="pt-card">
                {error ? <Message severity="error" text={error} style={{ width: "100%", marginBottom: 12 }} /> : null}
                {loading ? (
                    <div style={{ display: "flex", justifyContent: "center", padding: "40px 0" }}>
                        <ProgressSpinner style={{ width: "2.5rem", height: "2.5rem" }} />
                    </div>
                ) : (
                    <DataTable value={flows} paginator rows={15} emptyMessage="No flows match these filters.">
                        <Column field="id" header="ID" style={{ width: 80 }} />
                        <Column header="Organization" body={orgBody} />
                        <Column header="Flow key" body={keyBody} />
                        <Column header="Kind" body={kindBody} style={{ width: 130 }} />
                        <Column header="Status" body={statusBody} style={{ width: 120 }} />
                        <Column field="version_count" header="Versions" style={{ width: 100 }} />
                        <Column field="published_version" header="Published v" style={{ width: 120 }} />
                        <Column header="Updated" body={dateBody("updated_at")} style={{ width: 190 }} />
                        <Column header="" body={actionsBody} style={{ width: 120 }} />
                    </DataTable>
                )}
            </div>

            <Dialog
                header={detail ? `Flow #${detail.id}${detail.flow?.flow_key ? ` — ${detail.flow.flow_key}` : ""}` : "Flow"}
                visible={!!detail}
                style={{ width: "82vw", maxWidth: 1200 }}
                onHide={() => { setDetail(null); setDefinition(null); }}
            >
                {detailLoading ? (
                    <div style={{ display: "flex", justifyContent: "center", padding: 40 }}>
                        <ProgressSpinner style={{ width: "2rem", height: "2rem" }} />
                    </div>
                ) : detail?.error ? (
                    <Message severity="error" text={detail.error} style={{ width: "100%" }} />
                ) : detail?.flow ? (
                    <div style={{ display: "grid", gap: 16 }}>
                        <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 16 }}>
                            <div>
                                <div style={{ fontWeight: 600, marginBottom: 4 }}>Organization</div>
                                <div>{detail.organization?.name || "—"} <span style={{ opacity: .6 }}>(#{detail.flow.organization_id})</span></div>
                            </div>
                            <div>
                                <div style={{ fontWeight: 600, marginBottom: 4 }}>Kind</div>
                                <div>{kindBody(detail.flow)}</div>
                            </div>
                            <div>
                                <div style={{ fontWeight: 600, marginBottom: 4 }}>Status</div>
                                <div>{statusBody(detail.flow)}</div>
                            </div>
                            <div>
                                <div style={{ fontWeight: 600, marginBottom: 4 }}>Published version</div>
                                <div>{detail.flow.published_version ? `v${detail.flow.published_version}` : "not published"}</div>
                            </div>
                        </div>

                        <div>
                            <div style={{ display: "flex", gap: 10, alignItems: "center", marginBottom: 8, flexWrap: "wrap" }}>
                                <div style={{ fontWeight: 600 }}>Definition</div>
                                <Dropdown options={versionOptions} value={versionId} style={{ width: 220 }}
                                    onChange={(e) => loadVersion(e.value)} placeholder="Version"
                                    emptyMessage="No versions" />
                                <div style={{ display: "flex", gap: 4 }}>
                                    <Button label="Graph" icon="pi pi-sitemap"
                                        className={`p-button-sm ${view === "graph" ? "p-button-info" : "p-button-text"}`}
                                        onClick={() => setView("graph")} />
                                    <Button label="JSON" icon="pi pi-code"
                                        className={`p-button-sm ${view === "json" ? "p-button-info" : "p-button-text"}`}
                                        onClick={() => setView("json")} />
                                </div>
                            </div>

                            {!definition ? (
                                <div style={{ padding: 24, textAlign: "center", opacity: .7 }}>
                                    This flow has no version to show.
                                </div>
                            ) : view === "graph" ? (
                                <FlowGraph definition={definition} height={440} />
                            ) : (
                                <pre style={{ background: "#0f172a", color: "#f1f5f9", padding: 12, borderRadius: 6, fontSize: 12, maxHeight: 440, overflow: "auto" }}>
                                    {JSON.stringify(definition, null, 2)}
                                </pre>
                            )}
                        </div>

                    </div>
                ) : null}
            </Dialog>
        </div>
    );
};

export default Chatflow;
