"use client";

import * as React from "react";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { Check, ChevronsUpDown, Loader, LockIcon } from "lucide-react";
import { toast } from "sonner";
import { useRouter } from "next/navigation";

import {
  Sheet,
  SheetClose,
  SheetContent,
  SheetDescription,
  SheetFooter,
  SheetHeader,
  SheetTitle,
} from "@/components/ui/sheet";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Form,
  FormField,
  FormItem,
  FormLabel,
  FormControl,
  FormMessage,
  FormDescription,
} from "@/components/ui/form";
import {
  Popover,
  PopoverTrigger,
  PopoverContent,
} from "@/components/ui/popover";
import {
  Command,
  CommandInput,
  CommandList,
  CommandGroup,
  CommandItem,
  CommandEmpty,
} from "@/components/ui/command";

import { DataTableColumnJSON } from "./form-data-table-columns";
import { updateFormDataInDB } from "@/lib/forms-plant/services";
import { cn } from "@/lib/utils";
import { useParams } from "next/navigation";
import { useTranslation } from "@/i18n/client";

/** =============================================================
 *  🔄  UpdateTagSheet with grouped fields by `head` property
 *  -----------------------------------------------------------
 *  - Consecutive columns that share the same `head` value will be
 *    rendered under a section title (the head itself).
 *  - Columns without a head still appear normally.
 *
 *  NOTE: Only rendering logic is touched – all validation,
 *        read‑only checks, and mutation logic stay the same.
 * ============================================================*/

interface UpdateTagSheetProps extends React.ComponentPropsWithoutRef<typeof Sheet> {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  columns: DataTableColumnJSON[];
  rowData: Record<string, any> | null;
  formCode: string;
  projectCode: string;
  packageCode: string;
  editableFieldsMap?: Map<string, string[]>; // 새로 추가
  /** 업데이트 성공 시 호출될 콜백 */
  onUpdateSuccess?: (updatedValues: Record<string, any>) => void;
}

export function UpdateTagSheet({
  open,
  onOpenChange,
  columns,
  rowData,
  formCode,
  projectCode,
  packageCode,
  editableFieldsMap = new Map(),
  onUpdateSuccess,
  ...props
}: UpdateTagSheetProps) {
  // ───────────────────────────────────────────────────────────────
  // hooks & helpers
  // ───────────────────────────────────────────────────────────────
  const [isPending, startTransition] = React.useTransition();
  const router = useRouter();

  const params = useParams();
  const lng = (params?.lng as string) || "ko";
  const { t } = useTranslation(lng, "engineering");

  /* ----------------------------------------------------------------
   * 1️⃣  Editable‑field helpers (unchanged)
   * --------------------------------------------------------------*/
  const editableFields = React.useMemo(() => {
    if (!rowData?.TAG_NO || !editableFieldsMap.has(rowData.TAG_NO)) {
      return [] as string[];
    }
    return editableFieldsMap.get(rowData.TAG_NO) || [];
  }, [rowData?.TAG_NO, editableFieldsMap]);

  const isFieldEditable = React.useCallback((column: DataTableColumnJSON) => {
    if (column.shi === "OUT" || column.shi === null) return false; // SHI‑only
    if (column.key === "TAG_NO" || column.key === "TAG_DESC") return false;
    if (column.key === "status") return false;
    return editableFields.includes(column.key);
    // return true
  }, [editableFields]);

  const isFieldReadOnly = React.useCallback((column: DataTableColumnJSON) => !isFieldEditable(column), [isFieldEditable]);

  const getReadOnlyReason = React.useCallback((column: DataTableColumnJSON) => {
    if (column.shi === "OUT" || column.shi === null) return t("updateTagSheet.readOnlyReasons.shiOnly");
    if (column.key !== "TAG_NO" && column.key !== "TAG_DESC") {
      if (!rowData?.TAG_NO || !editableFieldsMap.has(rowData.TAG_NO)) {
        return t("updateTagSheet.readOnlyReasons.noEditableFields");
      }
      if (!editableFields.includes(column.key)) {
        return t("updateTagSheet.readOnlyReasons.notEditableForTag");
      }
    }
    return t("updateTagSheet.readOnlyReasons.readOnly");
  }, [rowData?.TAG_NO, editableFieldsMap, editableFields, t]);

  /* ----------------------------------------------------------------
   * 2️⃣  Zod dynamic schema & form state (unchanged)
   * --------------------------------------------------------------*/
  const dynamicSchema = React.useMemo(() => {
    const shape: Record<string, z.ZodTypeAny> = {};
    for (const col of columns) {
      if (col.type === "NUMBER") {
        shape[col.key] = z
          .union([z.coerce.number(), z.nan()])
          .transform((val) => (isNaN(val as number) ? undefined : val))
          .optional();
      } else {
        shape[col.key] = z.string().optional();
      }
    }
    return z.object(shape);
  }, [columns]);

  const form = useForm({
    resolver: zodResolver(dynamicSchema),
    defaultValues: React.useMemo(() => {
      if (!rowData) return {};
      return columns.reduce<Record<string, any>>((acc, col) => {
        acc[col.key] = rowData[col.key] ?? "";
        return acc;
      }, {});
    }, [rowData, columns]),
  });

  React.useEffect(() => {
    if (!rowData) {
      form.reset({});
      return;
    }
    const defaults: Record<string, any> = {};
    columns.forEach((col) => {
      defaults[col.key] = rowData[col.key] ?? "";
    });
    form.reset(defaults);
  }, [rowData, columns, form]);

  /* ----------------------------------------------------------------
   * 3️⃣  Grouping logic – figure out consecutive columns that share
   *     the same `head` value. This mirrors `groupColumnsByHead` that
   *     you already use for the table view.
   * --------------------------------------------------------------*/
  const groupedColumns = React.useMemo(() => {
    // Ensure original ordering by `seq` where present
    const sorted = [...columns].sort((a, b) => {
      const seqA = a.seq ?? 999999;
      const seqB = b.seq ?? 999999;
      return seqA - seqB;
    });

    const groups: { head: string | null; cols: DataTableColumnJSON[] }[] = [];
    let i = 0;
    while (i < sorted.length) {
      const curr = sorted[i];
      const head = curr.head?.trim() || null;
      if (!head) {
        groups.push({ head: null, cols: [curr] });
        i += 1;
        continue;
      }

      // Collect consecutive columns with the same head
      const cols: DataTableColumnJSON[] = [curr];
      let j = i + 1;
      while (j < sorted.length && sorted[j].head?.trim() === head) {
        cols.push(sorted[j]);
        j += 1;
      }
      groups.push({ head, cols });
      i = j;
    }
    return groups;
  }, [columns]);

  /* ----------------------------------------------------------------
   * 4️⃣  Submission handler (unchanged)
   * --------------------------------------------------------------*/
  async function onSubmit(values: Record<string, any>) {
    startTransition(async () => {
      try {
        // Restore read‑only fields to their original value before saving
        const finalValues: Record<string, any> = { ...values };
        columns.forEach((col) => {
          if (isFieldReadOnly(col)) {
            finalValues[col.key] = rowData?.[col.key] ?? "";
          }
        });

        const { success, message } = await updateFormDataInDB(
          formCode,
          projectCode,
          packageCode,
          finalValues,
        );

        if (!success) {
          toast.error(message);
          return;
        }

        toast.success(t("updateTagSheet.messages.updateSuccess"));

        const updatedData = { ...rowData, ...finalValues, TAG_NO: rowData?.TAG_NO };
        onUpdateSuccess?.(updatedData);
        router.refresh();
        onOpenChange(false);
      } catch (error) {
        console.error("Error updating form data:", error);
        toast.error(t("updateTagSheet.messages.updateError"));
      }
    });
  }

  /* ----------------------------------------------------------------
   * 5️⃣  UI
   * --------------------------------------------------------------*/
  const editableFieldCount = React.useMemo(() => columns.filter(isFieldEditable).length, [columns, isFieldEditable]);

  return (
    <Sheet open={open} onOpenChange={onOpenChange} {...props}>
      <SheetContent className="sm:max-w-xl md:max-w-3xl lg:max-w-4xl xl:max-w-5xl flex flex-col">
        <SheetHeader className="text-left">
          <SheetTitle>
            {t("updateTagSheet.title")} – {rowData?.TAG_NO || t("updateTagSheet.unknownTag")}
          </SheetTitle>
          <SheetDescription>
            {t("updateTagSheet.description")}
            <LockIcon className="inline h-3 w-3 mx-1" />
            {t("updateTagSheet.readOnlyIndicator")}
            <br />
            <span className="text-sm text-green-600">
              {t("updateTagSheet.editableFieldsCount", { 
                editableCount: editableFieldCount, 
                totalCount: columns.length 
              })}
            </span>
          </SheetDescription>
        </SheetHeader>

        {/* ────────────────────────────────────────────── */}
        <Form {...form}>
          <form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col gap-4">
            {/* Scroll wrapper */}
            <div className="overflow-y-auto max-h-[80vh] flex-1 pr-4 -mr-4">
              {/* ------------------------------------------------------------------
               * Render groups
               * ----------------------------------------------------------------*/}
              {groupedColumns.map(({ head, cols }) => (
                <div key={head ?? cols[0].key} className="flex flex-col gap-4 pt-2">
                  {head && (
                    <h3 className="text-sm font-semibold text-gray-700 uppercase tracking-wide pl-1">
                      {head}
                    </h3>
                  )}

                  {/* Fields inside the group */}
                  {cols.map((col) => {
                    const isReadOnly = isFieldReadOnly(col);
                    const readOnlyReason = isReadOnly ? getReadOnlyReason(col) : "";
                    return (
                      <FormField
                        key={col.key}
                        control={form.control}
                        name={col.key}
                        render={({ field }) => {
                          // ——————————————— Number ————————————————
                          if (col.type === "NUMBER") {
                            return (
                              <FormItem>
                                <FormLabel className="flex items-center">
                                  {col.displayLabel || col.label}
                                  {isReadOnly && (
                                    <LockIcon className="ml-1 h-3 w-3 text-gray-400" />
                                  )}
                                </FormLabel>
                                <FormControl>
                                  <Input
                                    type="number"
                                    readOnly={isReadOnly}
                                    onChange={(e) => {
                                      const num = parseFloat(e.target.value);
                                      field.onChange(isNaN(num) ? "" : num);
                                    }}
                                    value={field.value ?? ""}
                                    className={cn(
                                      isReadOnly &&
                                      "bg-gray-100 text-gray-600 cursor-not-allowed border-gray-300",
                                    )}
                                  />
                                </FormControl>
                                {isReadOnly && (
                                  <FormDescription className="text-xs text-gray-500">
                                    {readOnlyReason}
                                  </FormDescription>
                                )}
                                <FormMessage />
                              </FormItem>
                            );
                          }

                          // ——————————————— List ————————————————
                          if (col.type === "LIST") {
                            return (
                              <FormItem>
                                <FormLabel className="flex items-center">
                                  {col.label}
                                  {isReadOnly && (
                                    <LockIcon className="ml-1 h-3 w-3 text-gray-400" />
                                  )}
                                </FormLabel>
                                <Popover>
                                  <PopoverTrigger asChild>
                                    <Button
                                      variant="outline"
                                      role="combobox"
                                      disabled={isReadOnly}
                                      className={cn(
                                        "w-full justify-between",
                                        !field.value && "text-muted-foreground",
                                        isReadOnly &&
                                        "bg-gray-100 text-gray-600 cursor-not-allowed border-gray-300",
                                      )}
                                    >
                                      {field.value ? 
                                        col.options?.find((o) => o === field.value) : 
                                        t("updateTagSheet.selectOption")
                                      }
                                      <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
                                    </Button>
                                  </PopoverTrigger>
                                  <PopoverContent className="w-full p-0">
                                    <Command>
                                      <CommandInput placeholder={t("updateTagSheet.searchOptions")} />
                                      <CommandEmpty>{t("updateTagSheet.noOptionFound")}</CommandEmpty>
                                      <CommandList>
                                        <CommandGroup>
                                          {col.options?.map((opt) => (
                                            <CommandItem key={opt} value={opt} onSelect={() => field.onChange(opt)}>
                                              <Check
                                                className={cn(
                                                  "mr-2 h-4 w-4",
                                                  field.value === opt ? "opacity-100" : "opacity-0",
                                                )}
                                              />
                                              {opt}
                                            </CommandItem>
                                          ))}
                                        </CommandGroup>
                                      </CommandList>
                                    </Command>
                                  </PopoverContent>
                                </Popover>
                                {isReadOnly && (
                                  <FormDescription className="text-xs text-gray-500">
                                    {readOnlyReason}
                                  </FormDescription>
                                )}
                                <FormMessage />
                              </FormItem>
                            );
                          }

                          // ——————————————— String / default ————————————
                          return (
                            <FormItem>
                              <FormLabel className="flex items-center">
                                {col.label}
                                {isReadOnly && (
                                  <LockIcon className="ml-1 h-3 w-3 text-gray-400" />
                                )}
                              </FormLabel>
                              <FormControl>
                                <Input
                                  readOnly={isReadOnly}
                                  {...field}
                                  className={cn(
                                    isReadOnly &&
                                    "bg-gray-100 text-gray-600 cursor-not-allowed border-gray-300",
                                  )}
                                />
                              </FormControl>
                              {isReadOnly && (
                                <FormDescription className="text-xs text-gray-500">
                                  {readOnlyReason}
                                </FormDescription>
                              )}
                              <FormMessage />
                            </FormItem>
                          );
                        }}
                      />
                    );
                  })}
                </div>
              ))}
            </div>

            {/* Footer */}
            <SheetFooter className="gap-2 pt-2">
              <SheetClose asChild>
                <Button type="button" variant="outline">
                  {t("buttons.cancel")}
                </Button>
              </SheetClose>
              <Button type="submit" disabled={isPending}>
                {isPending && <Loader className="mr-2 h-4 w-4 animate-spin" />}
                {t("buttons.save")}
              </Button>
            </SheetFooter>
          </form>
        </Form>
      </SheetContent>
    </Sheet>
  );
}