import { useState, type ReactNode } from 'react';
import { REGEXP_ONLY_DIGITS } from 'input-otp';
import { Button } from '@/components/base/buttons/button';
import { Dialog, Modal, ModalOverlay } from '@/components/application/modals/modal';
import { PinInput } from '@/components/base/pin-input/pin-input';
import { FeaturedIcon } from '@/components/foundations/featured-icon/featured-icon';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faShieldKeyhole, faLock, faLockOpen } from '@fortawesome/pro-duotone-svg-icons';
import type { FC } from 'react';
import { notify } from '@/lib/toast';
import { cx } from '@/utils/cx';

const ShieldIcon: FC<{ className?: string }> = ({ className }) => (
    <FontAwesomeIcon icon={faShieldKeyhole} className={className} />
);

const API_URL = import.meta.env.VITE_API_URL ?? 'http://localhost:4100';

type MaintAction = {
    endpoint: string;
    label: string;
    description: string;
    needsPreStep?: boolean;
    agentPickerEndpoint?: string;
    clientSideHandler?: (payload: any) => Promise<{ status: string; message: string }>;
};

type LockedRow = { agentId: string; displayName: string; heldByIp: string; lockedAt: string };
type FreeRow = { agentId: string; displayName: string };
type SessionStatus = { locked: LockedRow[]; free: FreeRow[] };

type MaintOtpModalProps = {
    isOpen: boolean;
    onOpenChange: (open: boolean) => void;
    action: MaintAction | null;
    preStepContent?: ReactNode;
    preStepPayload?: Record<string, any>;
    preStepReady?: boolean;
};

export const MaintOtpModal = ({ isOpen, onOpenChange, action, preStepContent, preStepPayload, preStepReady = true }: MaintOtpModalProps) => {
    const [otp, setOtp] = useState('');
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState<string | null>(null);
    // Phase-2 state: once the OTP passes and the action uses an agent
    // picker, we swap the PIN input for a two-bucket list (Locked / Free)
    // fetched from `agentPickerEndpoint`. The operator picks a locked
    // agent, then Confirm posts to the real `endpoint`.
    const [sessionStatus, setSessionStatus] = useState<SessionStatus | null>(null);
    const [pickedAgentId, setPickedAgentId] = useState<string | null>(null);
    // OTP is held across the two-phase flow so we don't force the user
    // to re-enter it after the picker loads.
    const [verifiedOtp, setVerifiedOtp] = useState<string | null>(null);

    const reset = () => {
        setOtp('');
        setError(null);
        setSessionStatus(null);
        setPickedAgentId(null);
        setVerifiedOtp(null);
        setLoading(false);
    };

    const handleClose = () => {
        onOpenChange(false);
        reset();
    };

    const postMaint = async (endpoint: string, body: Record<string, any>, otpHeader: string) => {
        const res = await fetch(`${API_URL}/api/maint/${endpoint}`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json', 'x-maint-otp': otpHeader },
            body: JSON.stringify(body),
        });
        const data = await res.json().catch(() => ({}));
        return { ok: res.ok, data };
    };

    const runPickerAction = async (pickedId: string, otpHeader: string) => {
        if (!action) return;
        setLoading(true);
        setError(null);
        const payload = { ...preStepPayload, agentId: pickedId };
        const { ok, data } = await postMaint(action.endpoint, payload, otpHeader);
        setLoading(false);
        if (ok) {
            notify.success(action.label, data.message ?? 'Completed successfully');
            onOpenChange(false);
            reset();
        } else {
            setError(data.message ?? 'Failed');
        }
    };

    const handleSubmit = async () => {
        if (!action || otp.length < 6) return;
        setLoading(true);
        setError(null);

        try {
            // Two-phase agent-picker flow — OTP first, then fetch list,
            // then the operator picks which agent to act on.
            if (action.agentPickerEndpoint) {
                const { ok, data } = await postMaint(action.agentPickerEndpoint, {}, otp);
                if (!ok) {
                    setError(data.message ?? 'Invalid maintenance code');
                    setLoading(false);
                    return;
                }
                setSessionStatus(data as SessionStatus);
                setVerifiedOtp(otp);
                setLoading(false);
                return;
            }

            if (action.clientSideHandler) {
                const { ok, data } = await postMaint('force-ready', {}, otp);
                if (!ok) {
                    setError(data.message ?? 'Invalid maintenance code');
                    setLoading(false);
                    return;
                }
                const result = await action.clientSideHandler(preStepPayload);
                notify.success(action.label, result.message ?? 'Completed');
                onOpenChange(false);
                reset();
                return;
            }

            // Default: single-shot endpoint with agentId from the CC agent's
            // own local config (cc-agent context). Supervisors hitting this
            // path without agent config used to get 400 — the agent-picker
            // branch above is the fix.
            const agentCfg = localStorage.getItem('helix_agent_config');
            const agentId = agentCfg ? JSON.parse(agentCfg).ozonetelAgentId : undefined;
            const payload = { ...preStepPayload, ...(agentId ? { agentId } : {}) };
            const { ok, data } = await postMaint(action.endpoint, payload, otp);
            if (ok) {
                notify.success(action.label, data.message ?? 'Completed successfully');
                onOpenChange(false);
                reset();
            } else {
                setError(data.message ?? 'Failed');
            }
        } catch {
            setError('Request failed');
        } finally {
            setLoading(false);
        }
    };

    const handleOtpChange = (value: string) => {
        setOtp(value);
        setError(null);
    };

    if (!action) return null;

    const showPicker = Boolean(action.agentPickerEndpoint && sessionStatus && verifiedOtp);
    const showOtp = (!action.needsPreStep || preStepReady) && !showPicker;
    const confirmDisabled = showPicker
        ? !pickedAgentId || loading
        : otp.length < 6 || loading || (action.needsPreStep && !preStepReady);

    const handleConfirm = async () => {
        if (showPicker && pickedAgentId && verifiedOtp) {
            await runPickerAction(pickedAgentId, verifiedOtp);
        } else {
            await handleSubmit();
        }
    };

    return (
        <ModalOverlay isOpen={isOpen} onOpenChange={handleClose} isDismissable>
            <Modal className="sm:max-w-[440px]">
                <Dialog>
                    {() => (
                        <div className="flex w-full flex-col rounded-xl bg-primary shadow-xl ring-1 ring-secondary overflow-hidden">
                            {/* Header */}
                            <div className="flex flex-col items-center gap-4 px-6 pt-6 pb-5">
                                <FeaturedIcon icon={ShieldIcon} color="brand" theme="light" size="md" />
                                <div className="flex flex-col items-center gap-1 text-center">
                                    <h2 className="text-lg font-semibold text-primary">{action.label}</h2>
                                    <p className="text-sm text-tertiary">{action.description}</p>
                                </div>
                            </div>

                            {/* Pre-step content (e.g., campaign selection) */}
                            {action.needsPreStep && preStepContent && !showPicker && (
                                <div className="px-6 pb-4">
                                    {preStepContent}
                                </div>
                            )}

                            {showOtp && (
                                <div className="flex flex-col items-center gap-2 px-6 pb-5">
                                    <PinInput size="sm">
                                        <PinInput.Label>Enter maintenance code</PinInput.Label>
                                        <PinInput.Group
                                            maxLength={6}
                                            pattern={REGEXP_ONLY_DIGITS}
                                            value={otp}
                                            onChange={handleOtpChange}
                                            onComplete={handleSubmit}
                                            containerClassName="flex flex-row gap-2 h-14"
                                        >
                                            <PinInput.Slot index={0} className="!size-12 !text-display-sm" />
                                            <PinInput.Slot index={1} className="!size-12 !text-display-sm" />
                                            <PinInput.Slot index={2} className="!size-12 !text-display-sm" />
                                            <PinInput.Separator />
                                            <PinInput.Slot index={3} className="!size-12 !text-display-sm" />
                                            <PinInput.Slot index={4} className="!size-12 !text-display-sm" />
                                            <PinInput.Slot index={5} className="!size-12 !text-display-sm" />
                                        </PinInput.Group>
                                    </PinInput>
                                    {error && (
                                        <p className="text-sm text-error-primary mt-1">{error}</p>
                                    )}
                                </div>
                            )}

                            {showPicker && sessionStatus && (
                                <div className="px-6 pb-5 space-y-4">
                                    <div>
                                        <div className="flex items-center gap-2 mb-2">
                                            <FontAwesomeIcon icon={faLock} className="size-3.5 text-fg-error-primary" />
                                            <p className="text-xs font-semibold uppercase text-secondary">
                                                Locked ({sessionStatus.locked.length})
                                            </p>
                                        </div>
                                        {sessionStatus.locked.length === 0 ? (
                                            <p className="text-sm text-tertiary pl-5">No active session locks.</p>
                                        ) : (
                                            <div className="space-y-1.5">
                                                {sessionStatus.locked.map((row) => {
                                                    const selected = pickedAgentId === row.agentId;
                                                    return (
                                                        <button
                                                            key={row.agentId}
                                                            type="button"
                                                            onClick={() => setPickedAgentId(row.agentId)}
                                                            className={cx(
                                                                'w-full flex items-start justify-between gap-3 rounded-lg border p-3 text-left transition duration-100 ease-linear',
                                                                selected
                                                                    ? 'border-brand bg-brand-primary_alt'
                                                                    : 'border-secondary hover:border-brand hover:bg-secondary',
                                                            )}
                                                        >
                                                            <div className="min-w-0">
                                                                <p className="text-sm font-medium text-primary truncate">{row.displayName}</p>
                                                                <p className="text-xs text-tertiary truncate">
                                                                    <code className="font-mono">{row.agentId}</code> — held by {row.heldByIp}
                                                                </p>
                                                                <p className="text-xs text-quaternary">
                                                                    since {new Date(row.lockedAt).toLocaleString()}
                                                                </p>
                                                            </div>
                                                            {selected && (
                                                                <span className="shrink-0 text-xs font-semibold text-brand-secondary">Selected</span>
                                                            )}
                                                        </button>
                                                    );
                                                })}
                                            </div>
                                        )}
                                    </div>

                                    <div>
                                        <div className="flex items-center gap-2 mb-2">
                                            <FontAwesomeIcon icon={faLockOpen} className="size-3.5 text-fg-success-primary" />
                                            <p className="text-xs font-semibold uppercase text-secondary">
                                                Free ({sessionStatus.free.length})
                                            </p>
                                        </div>
                                        {sessionStatus.free.length === 0 ? (
                                            <p className="text-sm text-tertiary pl-5">No free agents.</p>
                                        ) : (
                                            <div className="space-y-1.5">
                                                {sessionStatus.free.map((row) => (
                                                    <div
                                                        key={row.agentId}
                                                        className="flex items-center justify-between gap-3 rounded-lg border border-secondary bg-disabled_subtle p-3 opacity-70"
                                                    >
                                                        <div className="min-w-0">
                                                            <p className="text-sm font-medium text-secondary truncate">{row.displayName}</p>
                                                            <p className="text-xs text-quaternary truncate">
                                                                <code className="font-mono">{row.agentId}</code>
                                                            </p>
                                                        </div>
                                                        <span className="shrink-0 text-xs font-medium text-success-primary">Already free</span>
                                                    </div>
                                                ))}
                                            </div>
                                        )}
                                    </div>

                                    {error && (
                                        <p className="text-sm text-error-primary">{error}</p>
                                    )}
                                </div>
                            )}

                            {/* Footer */}
                            <div className="flex items-center gap-3 border-t border-secondary px-6 py-4">
                                <Button size="md" color="secondary" onClick={handleClose} className="flex-1">
                                    Cancel
                                </Button>
                                <Button
                                    size="md"
                                    color="primary"
                                    isDisabled={confirmDisabled}
                                    isLoading={loading}
                                    onClick={handleConfirm}
                                    className="flex-1"
                                >
                                    Confirm
                                </Button>
                            </div>
                        </div>
                    )}
                </Dialog>
            </Modal>
        </ModalOverlay>
    );
};
