import { useId, type ReactNode } from "react";
import { Trans, useTranslation } from "react-i18next";
import { ChevronDown, CircleCheckBig, FolderOpen, Info, Loader2 } from "lucide-react";
import { Browser } from "@wailsio/runtime";
import { Debug as DebugSvc } from "@bindings/services";
import type { DebugBundleResult } from "@bindings/services/models.js";
import { Button } from "@/components/buttons/Button";
import { DialogActions } from "@/components/dialog/DialogActions";
import { DialogDescription } from "@/components/dialog/DialogDescription";
import { DialogHeading } from "@/components/dialog/DialogHeading";
import {
    DropdownMenu,
    DropdownMenuContent,
    DropdownMenuRadioGroup,
    DropdownMenuRadioItem,
    DropdownMenuTrigger,
} from "@/components/DropdownMenu";
import FancyToggleSwitch from "@/components/switches/FancyToggleSwitch";
import HelpText from "@/components/typography/HelpText.tsx";
import { Input } from "@/components/inputs/Input";
import { Label } from "@/components/typography/Label";
import { SquareIcon } from "@/components/SquareIcon";
import { Tooltip } from "@/components/Tooltip";
import { cn } from "@/lib/cn";
import { formatRemaining } from "@/lib/formatters";
import type { AnonymizeLevel, DebugStage } from "@/contexts/DebugBundleContext";
import { useDebugBundleContext } from "@/contexts/DebugBundleContext";
import { SectionGroup, SettingsBottomBar } from "@/modules/settings/SettingsSection.tsx";

const SUPPORT_DOCS_URL = "https://docs.netbird.io/help/report-bug-issues";

export function SettingsTroubleshooting() {
    const { t } = useTranslation();
    const durationId = useId();
    const {
        anonymizeLevel,
        setAnonymizeLevel,
        systemInfo,
        setSystemInfo,
        upload,
        setUpload,
        trace,
        setTrace,
        capture,
        setCapture,
        traceMinutes,
        setTraceMinutes,
        capturePackets,
        setCapturePackets,
        run,
        stage,
        cancel,
        reset,
    } = useDebugBundleContext();

    if (stage.kind === "done") {
        return (
            <DoneResult result={stage.result} uploaded={stage.uploadAttempted} onClose={reset} />
        );
    }
    if (stage.kind !== "idle") {
        return <ProgressSection stage={stage} onCancel={cancel} />;
    }

    return (
        <SectionGroup title={t("settings.troubleshooting.section.title")}>
            <div className={"flex items-center justify-between gap-6"}>
                <div className={"max-w-md flex-1"}>
                    <Label as={"div"}>
                        <span className={"inline-flex items-center gap-1.5"}>
                            {t("settings.troubleshooting.anonymize.label")}
                            <Tooltip
                                content={
                                    <div className={"max-w-xs whitespace-normal leading-relaxed"}>
                                        {t("settings.troubleshooting.anonymize.info")}
                                    </div>
                                }
                            >
                                <Info
                                    size={14}
                                    aria-label={t("settings.troubleshooting.anonymize.label")}
                                    className={"shrink-0 cursor-default text-nb-gray-400"}
                                />
                            </Tooltip>
                        </span>
                    </Label>
                    <HelpText margin={false}>
                        {t("settings.troubleshooting.anonymize.help")}
                    </HelpText>
                </div>
                <div className={"shrink-0"}>
                    <DropdownMenu>
                        <DropdownMenuTrigger asChild>
                            <button
                                type={"button"}
                                aria-label={t("settings.troubleshooting.anonymize.label")}
                                className={cn(
                                    "inline-flex h-[40px] min-w-[160px] items-center justify-between gap-2 px-3",
                                    "rounded-md border bg-white dark:bg-nb-gray-900",
                                    "border-neutral-200 dark:border-nb-gray-700",
                                    "cursor-default text-xs font-semibold text-nb-gray-100 outline-none",
                                    "hover:border-nb-gray-600 data-[state=open]:border-nb-gray-600",
                                )}
                            >
                                {t(`settings.troubleshooting.anonymize.${anonymizeLevel}`)}
                                <ChevronDown
                                    size={16}
                                    aria-hidden={"true"}
                                    className={"shrink-0 text-nb-gray-200"}
                                />
                            </button>
                        </DropdownMenuTrigger>
                        <DropdownMenuContent align={"end"} className={"min-w-[160px]"}>
                            <DropdownMenuRadioGroup
                                value={anonymizeLevel}
                                onValueChange={(v) => setAnonymizeLevel(v as AnonymizeLevel)}
                            >
                                <DropdownMenuRadioItem value={"none"}>
                                    {t("settings.troubleshooting.anonymize.none")}
                                </DropdownMenuRadioItem>
                                <DropdownMenuRadioItem value={"default"}>
                                    {t("settings.troubleshooting.anonymize.default")}
                                </DropdownMenuRadioItem>
                                <DropdownMenuRadioItem value={"strict"}>
                                    {t("settings.troubleshooting.anonymize.strict")}
                                </DropdownMenuRadioItem>
                            </DropdownMenuRadioGroup>
                        </DropdownMenuContent>
                    </DropdownMenu>
                </div>
            </div>
            <FancyToggleSwitch
                value={systemInfo}
                onChange={setSystemInfo}
                label={t("settings.troubleshooting.systemInfo.label")}
                helpText={t("settings.troubleshooting.systemInfo.help")}
            />
            <FancyToggleSwitch
                value={upload}
                onChange={setUpload}
                label={t("settings.troubleshooting.upload.label")}
                helpText={t("settings.troubleshooting.upload.help")}
            />
            <FancyToggleSwitch
                value={trace}
                onChange={setTrace}
                label={t("settings.troubleshooting.trace.label")}
                helpText={t("settings.troubleshooting.trace.help")}
            />
            <FancyToggleSwitch
                value={capture}
                onChange={setCapture}
                label={t("settings.troubleshooting.capture.label")}
                helpText={t("settings.troubleshooting.capture.help")}
            />
            <div className={"flex flex-col gap-4"}>
                <FancyToggleSwitch
                    value={capturePackets}
                    onChange={setCapturePackets}
                    label={t("settings.troubleshooting.packets.label")}
                    helpText={t("settings.troubleshooting.packets.help")}
                    disabled={!capture}
                />
                <div
                    className={"flex items-center justify-between gap-6"}
                    {...(capture ? {} : { inert: "" })}
                >
                    <div className={"max-w-md flex-1"}>
                        <Label htmlFor={durationId} disabled={!capture}>
                            {t("settings.troubleshooting.duration.label")}
                        </Label>
                        <HelpText margin={false} disabled={!capture}>
                            {t("settings.troubleshooting.duration.help")}
                        </HelpText>
                    </div>
                    <div className={"w-40 shrink-0"}>
                        <Input
                            id={durationId}
                            type={"number"}
                            min={1}
                            max={30}
                            value={traceMinutes}
                            onChange={(e) =>
                                setTraceMinutes(
                                    Math.max(1, Math.min(30, Number(e.target.value) || 1)),
                                )
                            }
                            customSuffix={t("settings.troubleshooting.duration.suffix")}
                            disabled={!capture}
                        />
                    </div>
                </div>
            </div>

            <SettingsBottomBar>
                <Button variant={"primary"} size={"md"} onClick={run}>
                    {t("settings.troubleshooting.create")}
                </Button>
            </SettingsBottomBar>
        </SectionGroup>
    );
}

function CenteredPanel({ children }: Readonly<{ children: ReactNode }>) {
    return (
        <div
            className={
                "absolute inset-0 flex flex-col items-center justify-center gap-5 p-8 text-center"
            }
        >
            {children}
        </div>
    );
}

function ProgressSection({
    stage,
    onCancel,
}: Readonly<{ stage: DebugStage; onCancel: () => void }>) {
    const { t } = useTranslation();
    const cancelling = stage.kind === "cancelling";
    return (
        <CenteredPanel>
            <SquareIcon icon={Loader2} className={"[&_svg]:animate-spin"} />

            <div className={"flex max-w-sm flex-col items-center gap-2"}>
                <DialogHeading className={"text-balance"}>{stageLabel(stage, t)}</DialogHeading>
                <DialogDescription>
                    {t("settings.troubleshooting.progress.description")}
                </DialogDescription>
            </div>

            {stage.kind === "capturing" && (
                <div
                    className={
                        "font-mono text-2xl font-semibold tabular-nums tracking-wider text-nb-gray-50"
                    }
                    aria-live={"polite"}
                >
                    {formatRemaining(stage.remainingSec)}
                </div>
            )}

            <DialogActions className={"max-w-[220px]"}>
                <Button
                    autoFocus
                    variant={"secondary"}
                    size={"md"}
                    className={"w-full"}
                    onClick={onCancel}
                    disabled={cancelling}
                >
                    {t("common.cancel")}
                </Button>
            </DialogActions>
        </CenteredPanel>
    );
}

function DoneResult({
    result,
    uploaded,
    onClose,
}: Readonly<{
    result: DebugBundleResult;
    uploaded: boolean;
    onClose: () => void;
}>) {
    const { t } = useTranslation();
    const showKey = uploaded && Boolean(result.uploadedKey);
    const uploadFailed = uploaded && !result.uploadedKey;
    const onRevealPath = () => {
        if (!result.path) return;
        DebugSvc.RevealFile(result.path).catch((err: unknown) =>
            console.error("reveal debug bundle file", err),
        );
    };
    return (
        <CenteredPanel>
            <SquareIcon icon={CircleCheckBig} className={"[&_svg]:text-green-500"} />

            <div className={"flex max-w-sm flex-col items-center gap-2"}>
                <DialogHeading className={"text-balance"}>
                    {showKey
                        ? t("settings.troubleshooting.done.uploadedTitle")
                        : t("settings.troubleshooting.done.savedTitle")}
                </DialogHeading>
                <DialogDescription>
                    {showKey ? (
                        <Trans
                            i18nKey={"settings.troubleshooting.done.uploadedDescription"}
                            components={{
                                docs: (
                                    <a
                                        href={SUPPORT_DOCS_URL}
                                        aria-label={t("settings.about.community.documentation")}
                                        onClick={(e) => {
                                            e.preventDefault();
                                            Browser.OpenURL(SUPPORT_DOCS_URL).catch(() =>
                                                globalThis.open(SUPPORT_DOCS_URL, "_blank"),
                                            );
                                        }}
                                        className={"text-netbird hover:underline"}
                                    >
                                        {/* content is provided by <Trans> */}
                                        <span />
                                    </a>
                                ),
                            }}
                        />
                    ) : (
                        t("settings.troubleshooting.done.savedDescription")
                    )}
                </DialogDescription>
            </div>

            <div className={"flex w-full max-w-sm flex-col gap-3"}>
                {showKey && <Input value={result.uploadedKey} readOnly copy />}

                {result.path && !showKey && (
                    <Input
                        value={result.path}
                        readOnly
                        aria-label={t("settings.troubleshooting.done.savedTitle")}
                        customSuffix={
                            <button
                                type={"button"}
                                onClick={onRevealPath}
                                className={"pointer-events-auto transition-all hover:text-white"}
                                aria-label={t("settings.troubleshooting.done.openFileLocation")}
                            >
                                <FolderOpen size={16} aria-hidden={"true"} />
                            </button>
                        }
                    />
                )}

                {uploadFailed && (
                    <div
                        role={"alert"}
                        className={
                            "rounded-md border border-red-500/30 bg-red-500/10 px-3 py-2 text-xs text-red-300"
                        }
                    >
                        {result.uploadFailureReason
                            ? t("settings.troubleshooting.uploadFailedWithReason", {
                                  reason: result.uploadFailureReason,
                              })
                            : t("settings.troubleshooting.uploadFailed")}
                    </div>
                )}
            </div>

            <DialogActions className={"max-w-[220px]"}>
                {showKey ? (
                    <Button
                        autoFocus
                        variant={"primary"}
                        size={"md"}
                        className={"w-full"}
                        copy={result.uploadedKey}
                    >
                        {t("settings.troubleshooting.done.copyKey")}
                    </Button>
                ) : (
                    result.path && (
                        <Button
                            autoFocus
                            variant={"primary"}
                            size={"md"}
                            className={"w-full"}
                            onClick={onRevealPath}
                        >
                            <FolderOpen size={14} aria-hidden={"true"} />
                            {t("settings.troubleshooting.done.openFolder")}
                        </Button>
                    )
                )}
                <Button variant={"secondary"} size={"md"} className={"w-full"} onClick={onClose}>
                    {t("common.close")}
                </Button>
            </DialogActions>
        </CenteredPanel>
    );
}

const stageLabel = (
    stage: DebugStage,
    t: (key: string, options?: Record<string, unknown>) => string,
): string => {
    switch (stage.kind) {
        case "reconnecting":
            return t("settings.troubleshooting.stage.reconnecting");
        case "capturing":
            return t("settings.troubleshooting.stage.capturing");
        case "bundling":
            return t("settings.troubleshooting.stage.bundling");
        case "uploading":
            return t("settings.troubleshooting.stage.uploading");
        case "cancelling":
            return t("settings.troubleshooting.stage.cancelling");
        default:
            return "";
    }
};
