"use client";

import { useEffect, useMemo, useState } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { LoadingSpinner } from "@/components/common/LoadingSpinner";
import { ValidationMessage } from "@/components/common/ValidationMessage";
import { useCreateCodeDetail, useUpdateCodeDetail } from "@/hooks/queries/useCodeDetail";
import { useCheckCodeDetailDuplicate } from "@/hooks/queries/useValidation";
import {
  createCodeDetailSchema,
  updateCodeDetailSchema,
  type CreateCodeDetailData,
  type UpdateCodeDetailData,
} from "@/lib/schemas/commonCode";
import type { CodeDetail } from "@/types/commonCode";

interface CodeFormModalProps {
  isOpen: boolean;
  onClose: () => void;
  codeInfo: string;
  editingRow?: CodeDetail | null;
  allRows: CodeDetail[];
  defaultParentDetailId?: number | null;
}

const PARENT_NONE = "__NONE__";

/** code_value 자동 생성 (timestamp+random) */
const generateCodeValue = (): string => {
  const timestamp = Date.now().toString(36).toUpperCase();
  const random = Math.random().toString(36).substring(2, 6).toUpperCase();
  return `${timestamp}${random}`;
};

export function CodeFormModal({
  isOpen,
  onClose,
  codeInfo,
  editingRow,
  allRows,
  defaultParentDetailId,
}: CodeFormModalProps) {
  const createMutation = useCreateCodeDetail();
  const updateMutation = useUpdateCodeDetail();

  const isEditing = !!editingRow;
  const schema = isEditing ? updateCodeDetailSchema : createCodeDetailSchema;

  const form = useForm({
    resolver: zodResolver(schema),
    mode: "onChange",
    defaultValues: {
      code_info: codeInfo,
      parent_detail_id: null as number | null,
      code_value: "",
      code_name: "",
      code_name_eng: "",
      description: "",
      sort_order: 10,
      ...(isEditing && { is_active: "Y" as const }),
    },
  });

  // 부모 후보: 자기 자신 + 자기 자손은 제외
  const parentOptions = useMemo(() => {
    if (!isEditing) return allRows;
    if (!editingRow) return allRows;
    const selfId = String(editingRow.code_detail_id);

    const descendants = new Set<string>([selfId]);
    let changed = true;
    while (changed) {
      changed = false;
      for (const row of allRows) {
        const parentKey =
          row.parent_detail_id == null ? "" : String(row.parent_detail_id);
        if (
          descendants.has(parentKey) &&
          !descendants.has(String(row.code_detail_id))
        ) {
          descendants.add(String(row.code_detail_id));
          changed = true;
        }
      }
    }
    return allRows.filter((r) => !descendants.has(String(r.code_detail_id)));
  }, [allRows, editingRow, isEditing]);

  // 중복 검사 (code_name)
  const [duplicateState, setDuplicateState] = useState<{ enabled: boolean; value: string }>({
    enabled: false,
    value: "",
  });
  const nameCheck = useCheckCodeDetailDuplicate(
    codeInfo,
    "code_name",
    duplicateState.value,
    isEditing ? editingRow?.code_detail_id : undefined,
    duplicateState.enabled,
  );
  const hasDuplicateErrors = !!nameCheck.data?.isDuplicate && duplicateState.enabled;
  const isDuplicateChecking = nameCheck.isLoading;

  useEffect(() => {
    if (!isOpen) return;
    if (isEditing && editingRow) {
      form.reset({
        code_info: editingRow.code_info || codeInfo,
        parent_detail_id: editingRow.parent_detail_id ?? null,
        code_value: editingRow.code_value || "",
        code_name: editingRow.code_name || "",
        code_name_eng: editingRow.code_name_eng || "",
        description: editingRow.description || "",
        sort_order: editingRow.sort_order ?? 10,
        is_active: ((editingRow.is_active as "Y" | "N") || "Y") as any,
      } as any);
    } else {
      // 형제 중 최대 sort_order + 10
      const siblings = allRows.filter((r) => {
        const pid = r.parent_detail_id ?? null;
        return pid === (defaultParentDetailId ?? null);
      });
      const maxSort =
        siblings.length > 0
          ? Math.max(...siblings.map((r) => r.sort_order ?? 0))
          : 0;
      form.reset({
        code_info: codeInfo,
        parent_detail_id: defaultParentDetailId ?? null,
        code_value: generateCodeValue(),
        code_name: "",
        code_name_eng: "",
        description: "",
        sort_order: maxSort + 10,
      });
    }
    setDuplicateState({ enabled: false, value: "" });
  }, [isOpen, isEditing, editingRow, codeInfo, defaultParentDetailId]); // eslint-disable-line react-hooks/exhaustive-deps

  const handleSubmit = form.handleSubmit(async (data) => {
    try {
      if (isEditing && editingRow) {
        await updateMutation.mutateAsync({
          codeDetailId: editingRow.code_detail_id,
          data: data as UpdateCodeDetailData,
        });
      } else {
        await createMutation.mutateAsync(data as CreateCodeDetailData);
      }
      onClose();
      form.reset();
    } catch (error) {
      console.error("디테일 저장 실패:", error);
    }
  });

  const isLoading = createMutation.isPending || updateMutation.isPending;

  const watchedParent = form.watch("parent_detail_id");
  const parentSelectValue =
    watchedParent == null || watchedParent === undefined
      ? PARENT_NONE
      : String(watchedParent);

  return (
    <Dialog open={isOpen} onOpenChange={onClose}>
      <DialogContent className="max-w-[95vw] sm:max-w-[500px]">
        <DialogHeader>
          <DialogTitle className="text-base sm:text-lg">
            {isEditing
              ? "디테일 수정"
              : defaultParentDetailId != null
                ? "하위 코드 추가"
                : "새 코드"}
          </DialogTitle>
        </DialogHeader>

        <form onSubmit={handleSubmit} className="space-y-3 sm:space-y-4">
          {/* code_value */}
          <div className="space-y-2">
            <Label htmlFor="code_value" className="text-xs sm:text-sm">
              코드값 *
            </Label>
            <Input
              id="code_value"
              {...form.register("code_value")}
              disabled={isLoading || isEditing}
              placeholder="코드값"
              className="h-8 text-xs sm:h-10 sm:text-sm"
            />
            {isEditing && (
              <p className="text-[10px] sm:text-xs text-muted-foreground">
                코드값은 변경할 수 없습니다
              </p>
            )}
            {form.formState.errors.code_value && (
              <p className="text-[10px] sm:text-xs text-destructive">
                {form.formState.errors.code_value.message as string}
              </p>
            )}
          </div>

          {/* 부모 선택 */}
          <div className="space-y-2">
            <Label htmlFor="parent_detail_id" className="text-xs sm:text-sm">
              상위 코드
            </Label>
            <Select
              value={parentSelectValue}
              onValueChange={(v) =>
                form.setValue("parent_detail_id", v === PARENT_NONE ? null : Number(v), {
                  shouldValidate: true,
                  shouldDirty: true,
                })
              }
              disabled={isLoading}
            >
              <SelectTrigger className="h-8 text-xs sm:h-10 sm:text-sm">
                <SelectValue placeholder="상위 코드를 선택하세요" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value={PARENT_NONE}>그룹 직속 (2 레벨)</SelectItem>
                {parentOptions.map((opt) => (
                  <SelectItem
                    key={String(opt.code_detail_id)}
                    value={String(opt.code_detail_id)}
                  >
                    {"  ".repeat(Math.max(0, (opt.depth ?? 2) - 2))}
                    {opt.code_name || opt.code_value}{" "}
                    <span className="ml-1 text-muted-foreground">({opt.code_value})</span>
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
            <p className="text-[10px] sm:text-xs text-muted-foreground">
              비워두면 그룹 직속(2 레벨)으로 등록됩니다
            </p>
          </div>

          {/* 코드명 */}
          <div className="space-y-2">
            <Label htmlFor="code_name" className="text-xs sm:text-sm">
              코드명 *
            </Label>
            <Input
              id="code_name"
              {...form.register("code_name")}
              disabled={isLoading}
              placeholder="코드명"
              className={
                form.formState.errors.code_name
                  ? "h-8 border-destructive text-xs sm:h-10 sm:text-sm"
                  : "h-8 text-xs sm:h-10 sm:text-sm"
              }
              onBlur={(e) => {
                const value = e.target.value.trim();
                if (value) setDuplicateState({ enabled: true, value });
              }}
            />
            {form.formState.errors.code_name && (
              <p className="text-[10px] sm:text-xs text-destructive">
                {form.formState.errors.code_name.message as string}
              </p>
            )}
            {!form.formState.errors.code_name && (
              <ValidationMessage
                message={nameCheck.data?.message}
                isValid={!nameCheck.data?.isDuplicate}
                isLoading={nameCheck.isLoading}
              />
            )}
          </div>

          {/* 영문명 */}
          <div className="space-y-2">
            <Label htmlFor="code_name_eng" className="text-xs sm:text-sm">
              코드 영문명
            </Label>
            <Input
              id="code_name_eng"
              {...form.register("code_name_eng")}
              disabled={isLoading}
              placeholder="영문명 (선택)"
              className="h-8 text-xs sm:h-10 sm:text-sm"
            />
          </div>

          {/* 설명 */}
          <div className="space-y-2">
            <Label htmlFor="description" className="text-xs sm:text-sm">
              설명
            </Label>
            <Textarea
              id="description"
              {...form.register("description")}
              disabled={isLoading}
              placeholder="설명 (선택)"
              rows={2}
              className="text-xs sm:text-sm"
            />
          </div>

          {/* 정렬 */}
          <div className="space-y-2">
            <Label htmlFor="sort_order" className="text-xs sm:text-sm">
              정렬 순서
            </Label>
            <Input
              id="sort_order"
              type="number"
              {...form.register("sort_order", { valueAsNumber: true })}
              disabled={isLoading}
              min={0}
              className="h-8 text-xs sm:h-10 sm:text-sm"
            />
          </div>

          {/* 활성 (수정) */}
          {isEditing && (
            <div className="flex items-center gap-2">
              <Switch
                id="is_active"
                checked={form.watch("is_active" as any) === "Y"}
                onCheckedChange={(checked) =>
                  form.setValue("is_active" as any, checked ? "Y" : "N")
                }
                disabled={isLoading}
                aria-label="활성 상태"
              />
              <Label htmlFor="is_active" className="text-xs sm:text-sm">
                {form.watch("is_active" as any) === "Y" ? "활성" : "비활성"}
              </Label>
            </div>
          )}

          {/* 버튼 */}
          <div className="flex gap-2 pt-4 sm:justify-end sm:gap-0">
            <Button
              type="button"
              variant="outline"
              onClick={onClose}
              disabled={isLoading}
              className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
            >
              취소
            </Button>
            <Button
              type="submit"
              disabled={
                isLoading ||
                !form.formState.isValid ||
                hasDuplicateErrors ||
                isDuplicateChecking
              }
              className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
            >
              {isLoading ? (
                <>
                  <LoadingSpinner size="sm" className="mr-2" />
                  {isEditing ? "수정 중..." : "저장 중..."}
                </>
              ) : isEditing ? (
                "디테일 수정"
              ) : (
                "디테일 저장"
              )}
            </Button>
          </div>
        </form>
      </DialogContent>
    </Dialog>
  );
}
