"use client";

import { zodResolver } from "@hookform/resolvers/zod";
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@workspace/ui/components/accordion";
import { Badge } from "@workspace/ui/components/badge";
import { Button } from "@workspace/ui/components/button";
import { Checkbox } from "@workspace/ui/components/checkbox";
import { Form } from "@workspace/ui/components/form";
import { Label } from "@workspace/ui/components/label";
import { ScrollArea } from "@workspace/ui/components/scroll-area";
import {
  Sheet,
  SheetContent,
  SheetFooter,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from "@workspace/ui/components/sheet";
import { Switch } from "@workspace/ui/components/switch";
import { EnhancedInput } from "@workspace/ui/composed/enhanced-input";
import { cn } from "@workspace/ui/lib/utils";
import { updateServer } from "@workspace/ui/services/admin/server";
import { useState } from "react";
import { useForm, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import {
  formSchema,
  getProtocolDefaultConfig,
  protocols as PROTOCOLS,
  useProtocolFields,
} from "./form-schema";
import { renderGroupCard } from "./server-form";

type SimpleFieldKey = "name" | "country" | "city" | "address";
type FieldKey = SimpleFieldKey | "protocols";

interface SimplePatch {
  name: string;
  country: string;
  city: string;
  address: string;
}

export default function ServerBatchSheet({
  rows,
  onSuccess,
}: {
  rows: API.Server[];
  onSuccess: () => void;
}) {
  const { t } = useTranslation("servers");
  const [open, setOpen] = useState(false);
  const [loading, setLoading] = useState(false);
  const [accordionValue, setAccordionValue] = useState<string>();

  const [enabledFields, setEnabledFields] = useState<Set<FieldKey>>(new Set());
  const [patch, setPatch] = useState<SimplePatch>({
    name: "",
    country: "",
    city: "",
    address: "",
  });

  const PROTOCOL_FIELDS = useProtocolFields();

  const protocolForm = useForm({
    resolver: zodResolver(formSchema),
    defaultValues: {
      name: "",
      address: "",
      country: "",
      city: "",
      protocols: PROTOCOLS.map((type) => getProtocolDefaultConfig(type)),
    },
  });

  const protocolsValues = useWatch({
    control: protocolForm.control,
    name: "protocols",
  });

  function toggleField(key: FieldKey) {
    setEnabledFields((prev) => {
      const next = new Set(prev);
      if (next.has(key)) next.delete(key);
      else next.add(key);
      return next;
    });
  }

  function isEnabled(key: FieldKey) {
    return enabledFields.has(key);
  }

  async function handleSubmit() {
    if (rows.length === 0) return;
    if (enabledFields.size === 0) {
      toast.warning(
        t(
          "batch_no_fields_selected",
          "Please select at least one field to update"
        )
      );
      return;
    }

    // Validate enabled simple fields
    if (enabledFields.has("name") && !patch.name.trim()) {
      toast.warning(t("batch_name_required", "Name cannot be empty"));
      return;
    }
    if (enabledFields.has("address") && !patch.address.trim()) {
      toast.warning(t("batch_address_required", "Address cannot be empty"));
      return;
    }

    const activePatch: Record<string, any> = {};
    for (const key of enabledFields) {
      if (key === "protocols") {
        const formValues = protocolForm.getValues();
        const filteredProtocols = (formValues.protocols || []).filter(
          (p: any) => {
            const port = Number(p?.port);
            return p && Number.isFinite(port) && port > 0 && port <= 65_535;
          }
        );
        activePatch.protocols = filteredProtocols;
      } else {
        activePatch[key] = patch[key];
      }
    }

    setLoading(true);
    try {
      const results = await Promise.allSettled(
        rows.map((row) => {
          const body: API.UpdateServerRequest = {
            id: row.id,
            name: row.name,
            country: row.country as string | undefined,
            city: row.city as string | undefined,
            address: row.address,
            sort: row.sort,
            protocols: row.protocols,
            ...activePatch,
          };
          return updateServer(body);
        })
      );

      const succeeded = results.filter((r) => r.status === "fulfilled").length;
      const failed = results.filter((r) => r.status === "rejected").length;

      if (failed === 0) {
        toast.success(
          t("batch_updated", "Updated {{count}} servers", { count: succeeded })
        );
        setOpen(false);
        setEnabledFields(new Set());
        onSuccess();
      } else if (succeeded > 0) {
        toast.warning(
          t("batch_partial", "{{succeeded}} updated, {{failed}} failed", {
            succeeded,
            failed,
          })
        );
        onSuccess();
      } else {
        toast.error(t("batch_update_failed", "Batch update failed"));
      }
    } finally {
      setLoading(false);
    }
  }

  function handleOpen() {
    setEnabledFields(new Set());
    setPatch({ name: "", country: "", city: "", address: "" });
    protocolForm.reset({
      name: "",
      address: "",
      country: "",
      city: "",
      protocols: PROTOCOLS.map((type) => getProtocolDefaultConfig(type)),
    });
    setAccordionValue(undefined);
    setOpen(true);
  }

  const simpleFields: Array<{
    key: SimpleFieldKey;
    label: string;
    placeholder?: string;
  }> = [
    { key: "name", label: t("name", "Name") },
    { key: "country", label: t("country", "Country") },
    { key: "city", label: t("city", "City") },
    {
      key: "address",
      label: t("address", "Address"),
      placeholder: t("address_placeholder", "Server address"),
    },
  ];

  return (
    <Sheet onOpenChange={setOpen} open={open}>
      <SheetTrigger asChild>
        <Button onClick={handleOpen} variant="outline">
          {t("batch_update", "Batch Update")}
        </Button>
      </SheetTrigger>

      <SheetContent className="w-[700px] max-w-full gap-0 md:max-w-3xl">
        <SheetHeader>
          <SheetTitle>
            {t("batch_update_title", "Batch Update ({{count}} servers)", {
              count: rows.length,
            })}
          </SheetTitle>
        </SheetHeader>

        <ScrollArea className="h-[calc(100dvh-48px-36px-36px-env(safe-area-inset-top))] px-6 pt-4">
          <p className="mb-4 text-muted-foreground text-sm">
            {t(
              "batch_update_desc",
              "Check the fields you want to overwrite. Unchecked fields will keep their original values."
            )}
          </p>

          <Form {...protocolForm}>
            <form className="space-y-5">
              {/* Simple text fields */}
              {simpleFields.map(({ key, label, placeholder }) => (
                <div className="flex items-start gap-3" key={key}>
                  <Checkbox
                    checked={isEnabled(key)}
                    id={`batch-server-${key}`}
                    onCheckedChange={() => toggleField(key)}
                  />
                  <div className="flex-1 space-y-1.5">
                    <Label
                      className={isEnabled(key) ? "" : "text-muted-foreground"}
                      htmlFor={`batch-server-${key}`}
                    >
                      {label}
                    </Label>
                    <div
                      className={
                        isEnabled(key) ? "" : "pointer-events-none opacity-40"
                      }
                    >
                      <EnhancedInput
                        onValueChange={(v) =>
                          setPatch((p) => ({ ...p, [key]: String(v ?? "") }))
                        }
                        placeholder={placeholder}
                        value={patch[key]}
                      />
                    </div>
                  </div>
                </div>
              ))}

              {/* Protocol Configurations */}
              <div className="flex items-start gap-3">
                <Checkbox
                  checked={isEnabled("protocols")}
                  id="batch-server-protocols"
                  onCheckedChange={() => toggleField("protocols")}
                />
                <div className="flex-1 space-y-1.5">
                  <Label
                    className={
                      isEnabled("protocols") ? "" : "text-muted-foreground"
                    }
                    htmlFor="batch-server-protocols"
                  >
                    {t("protocol_configurations", "Protocol Configurations")}
                  </Label>
                  <p className="text-muted-foreground text-xs">
                    {t(
                      "protocol_configurations_desc",
                      "Enable and configure the required protocol types"
                    )}
                  </p>
                  <div
                    className={
                      isEnabled("protocols")
                        ? ""
                        : "pointer-events-none opacity-40"
                    }
                  >
                    <Accordion
                      className="w-full space-y-3"
                      collapsible
                      onValueChange={setAccordionValue}
                      type="single"
                      value={accordionValue}
                    >
                      {PROTOCOLS.map((type) => {
                        const i = Math.max(0, PROTOCOLS.indexOf(type));
                        const current = (protocolsValues?.[i] || {}) as Record<
                          string,
                          any
                        >;
                        const isProtocolEnabled = current?.enable;
                        const fields = PROTOCOL_FIELDS[type] || [];
                        return (
                          <AccordionItem
                            className="mb-2 rounded-lg border"
                            key={type}
                            value={type}
                          >
                            <AccordionTrigger className="px-4 py-3 hover:no-underline">
                              <div className="flex w-full items-center justify-between">
                                <div className="flex flex-col items-start gap-1">
                                  <div className="flex items-center gap-1">
                                    <span className="font-medium capitalize">
                                      {type}
                                    </span>
                                    {current.transport && (
                                      <Badge
                                        className="text-xs"
                                        variant="secondary"
                                      >
                                        {current.transport.toUpperCase()}
                                      </Badge>
                                    )}
                                    {current.security &&
                                      current.security !== "none" && (
                                        <Badge
                                          className="text-xs"
                                          variant="outline"
                                        >
                                          {current.security.toUpperCase()}
                                        </Badge>
                                      )}
                                    {current.port && (
                                      <Badge className="text-xs">
                                        {current.port}
                                      </Badge>
                                    )}
                                  </div>
                                  <span
                                    className={cn(
                                      "text-xs",
                                      isProtocolEnabled
                                        ? "text-green-500"
                                        : "text-muted-foreground"
                                    )}
                                  >
                                    {isProtocolEnabled
                                      ? t("enabled", "Enabled")
                                      : t("disabled", "Disabled")}
                                  </span>
                                </div>
                                <Switch
                                  checked={!!isProtocolEnabled}
                                  className="mr-2"
                                  onCheckedChange={(checked) => {
                                    protocolForm.setValue(
                                      `protocols.${i}.enable` as any,
                                      checked
                                    );
                                  }}
                                  onClick={(e) => e.stopPropagation()}
                                />
                              </div>
                            </AccordionTrigger>
                            <AccordionContent className="px-4 pt-0 pb-4">
                              <div className="-mx-4 space-y-4 rounded-b-lg border-t px-4 pt-4">
                                {renderGroupCard(
                                  t("basic", "Basic Configuration"),
                                  fields,
                                  "basic",
                                  protocolForm.control,
                                  protocolForm,
                                  i,
                                  current
                                )}
                                {renderGroupCard(
                                  t("obfs", "Obfuscation"),
                                  fields,
                                  "obfs",
                                  protocolForm.control,
                                  protocolForm,
                                  i,
                                  current
                                )}
                                {renderGroupCard(
                                  t("transport", "Transport"),
                                  fields,
                                  "transport",
                                  protocolForm.control,
                                  protocolForm,
                                  i,
                                  current
                                )}
                                {renderGroupCard(
                                  t("security", "Security"),
                                  fields,
                                  "security",
                                  protocolForm.control,
                                  protocolForm,
                                  i,
                                  current
                                )}
                                {renderGroupCard(
                                  t("reality", "Reality"),
                                  fields,
                                  "reality",
                                  protocolForm.control,
                                  protocolForm,
                                  i,
                                  current
                                )}
                                {renderGroupCard(
                                  t("encryption", "Encryption"),
                                  fields,
                                  "encryption",
                                  protocolForm.control,
                                  protocolForm,
                                  i,
                                  current
                                )}
                              </div>
                            </AccordionContent>
                          </AccordionItem>
                        );
                      })}
                    </Accordion>
                  </div>
                </div>
              </div>
            </form>
          </Form>
        </ScrollArea>

        <SheetFooter className="flex-row justify-end gap-2 pt-3">
          <Button
            disabled={loading}
            onClick={() => setOpen(false)}
            variant="outline"
          >
            {t("cancel", "Cancel")}
          </Button>
          <Button disabled={loading} onClick={handleSubmit}>
            {t("confirm", "Confirm")}
          </Button>
        </SheetFooter>
      </SheetContent>
    </Sheet>
  );
}
