import * as React from "react";
import { AlertCircleIcon, EyeIcon, InfoIcon } from "lucide-react";
import {
  Query,
  Utils as QbUtils,
  type ImmutableTree,
} from "@react-awesome-query-builder/ui";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Checkbox } from "@/components/ui/checkbox";
import { Label } from "@/components/ui/label";
import { Field, FieldLabel } from "@/components/ui/field";
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
import { cn } from "@/lib/utils";
import type {
  ContactAlertDialogProps,
  ContactAlertQueryBuilderProps,
  ContactAlertSeverity,
} from "./types";
import { AlertSharingType } from "./types";
import {
  ALERT_QUERY_FIELDS,
  QB_CONFIG,
  SEVERITY_LABELS,
  createAlertTree,
} from "./config";
import { isTreeValid } from "./utils";
import { CustomBuilderUI } from "./builder-ui";

// ---------------------------------------------------------------------------
// ContactAlertQueryBuilder
// ---------------------------------------------------------------------------

export function ContactAlertQueryBuilder({
  value,
  onChange,
  fields = ALERT_QUERY_FIELDS,
  className,
}: ContactAlertQueryBuilderProps) {
  const defaultOpenItems = React.useMemo(() => {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const json = QbUtils.getTree(value) as any;
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    return (json?.children1 ?? []).map((c: any) => c.id ?? "").filter(Boolean);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const renderBuilder = React.useCallback(
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    (props: any) => (
      <CustomBuilderUI
        tree={props.tree}
        actions={props.actions}
        fields={fields}
        defaultOpenItems={defaultOpenItems}
        className={className}
      />
    ),
    [fields, defaultOpenItems, className],
  );

  return (
    <Query
      {...QB_CONFIG}
      value={value}
      onChange={(newTree) => onChange(newTree)}
      renderBuilder={renderBuilder}
    />
  );
}

// ---------------------------------------------------------------------------
// ContactAlertDialog
// ---------------------------------------------------------------------------

export function ContactAlertDialog({
  open,
  onOpenChange,
  mode = "create",
  initialName = "",
  initialSeverity = "NEED_ACTION",
  initialQuery,
  isCompanyAdmin = false,
  initialShareAcrossCompany = false,
  onSave,
  onError,
  isLoading = false,
  className,
}: ContactAlertDialogProps) {
  const [name, setName] = React.useState(initialName);
  const [severity, setSeverity] =
    React.useState<ContactAlertSeverity>(initialSeverity);
  const [tree, setTree] = React.useState<ImmutableTree>(() =>
    createAlertTree(initialQuery),
  );
  const [shareAcrossCompany, setShareAcrossCompany] = React.useState(
    initialShareAcrossCompany,
  );

  React.useEffect(() => {
    if (open) {
      setName(initialName);
      setSeverity(initialSeverity);
      setTree(createAlertTree(initialQuery));
      setShareAcrossCompany(initialShareAcrossCompany);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [open]);

  const hasValidRule = React.useMemo(() => isTreeValid(tree), [tree]);
  const canSave = name.trim().length > 0 && hasValidRule && !isLoading;

  function handleSave() {
    if (!canSave) return;
    let filterSegment: ImmutableTree;
    try {
      filterSegment = QbUtils.sanitizeTree(tree, QB_CONFIG).fixedTree;
    } catch (e) {
      onError?.(e instanceof Error ? e : new Error(String(e)));
      return;
    }
    onSave({
      name: name.trim(),
      severity,
      filterSegment,
      sharingType: shareAcrossCompany
        ? AlertSharingType.COMPANY
        : AlertSharingType.PRIVATE,
    });
  }

  return (
    <Dialog open={open} onOpenChange={isLoading ? undefined : onOpenChange}>
      <DialogContent size="2xl" className={className}>
        <DialogHeader>
          <DialogTitle>
            {mode === "edit" ? "Update Alert" : "Create Alert"}
          </DialogTitle>
        </DialogHeader>

        {/* Severity */}
        <div className="flex flex-col gap-1.5">
          <p className="text-sm font-medium text-foreground">
            Alert trigger severity
          </p>
          <ToggleGroup
            type="single"
            variant="outline"
            size="sm"
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            value={severity as any}
            onValueChange={(v) =>
              v && setSeverity(v as unknown as ContactAlertSeverity)
            }
          >
            {(
              ["NEED_ACTION", "WATCH", "HEALTHY"] as ContactAlertSeverity[]
            ).map((s) => (
              <ToggleGroupItem
                key={s}
                value={s}
                className={cn(
                  s === "NEED_ACTION" &&
                    "data-pressed:bg-destructive/10 data-pressed:inset-ring-destructive data-pressed:text-destructive-text data-pressed:hover:bg-destructive/10",
                  s === "WATCH" &&
                    "data-pressed:bg-warning/10 data-pressed:inset-ring-warning data-pressed:text-warning-text data-pressed:hover:bg-warning/10",
                  s === "HEALTHY" &&
                    "data-pressed:bg-info/10 data-pressed:inset-ring-info data-pressed:text-info-text data-pressed:hover:bg-info/10",
                )}
              >
                {s === "NEED_ACTION" && (
                  <AlertCircleIcon className="size-3.5" />
                )}
                {s === "WATCH" && <EyeIcon className="size-3.5" />}
                {s === "HEALTHY" && <InfoIcon className="size-3.5" />}
                {SEVERITY_LABELS[s]}
              </ToggleGroupItem>
            ))}
          </ToggleGroup>
        </div>

        {/* Name */}
        <Field>
          <FieldLabel>Alert name</FieldLabel>
          <Input
            value={name}
            onChange={(e) => setName(e.target.value)}
            placeholder="e.g. High equity opportunity"
          />
        </Field>

        {/* Share across company */}
        {isCompanyAdmin && (
          <div className="flex items-center gap-2">
            <Checkbox
              id="alert-share"
              checked={shareAcrossCompany}
              onCheckedChange={(v) => setShareAcrossCompany(!!v)}
            />
            <Label htmlFor="alert-share" className="cursor-pointer font-normal">
              Share across company
            </Label>
          </div>
        )}

        {/* Query builder */}
        <div className="flex flex-col gap-1.5">
          <p className="text-sm font-medium text-foreground">
            Filter conditions
          </p>
          <ContactAlertQueryBuilder
            value={tree}
            onChange={setTree}
            fields={ALERT_QUERY_FIELDS}
          />
        </div>

        <DialogFooter>
          <Button
            variant="outline"
            onClick={() => onOpenChange(false)}
            disabled={isLoading}
          >
            Cancel
          </Button>
          <Button disabled={!canSave} onClick={handleSave}>
            {mode === "edit" ? "Update Alert" : "Create Alert"}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
