"use client";

import type { Block, FormCheckboxBlockProps } from "@/features/editor/state/editorStore";
import { ColorPickerField, TEXT_COLOR_PALETTE } from "@/features/editor/components/ColorPickerField";
import { NumericPropertyControl } from "@/features/editor/components/NumericPropertyControl";
import { useAppLocale } from "@/features/i18n/LocaleProvider";
import { getEditorFormCheckboxPanelMessages } from "@/features/i18n/messages/editorFormCheckboxPanel";

interface FormCheckboxPropertiesPanelProps {
  block: Block;
  selectedBlockId: string | null;
  updateBlock: (id: string, partial: any) => void;
}

export function FormCheckboxPropertiesPanel({ block, selectedBlockId, updateBlock }: FormCheckboxPropertiesPanelProps) {
  const locale = useAppLocale();
  const m = getEditorFormCheckboxPanelMessages(locale);
  if (!selectedBlockId || block.id !== selectedBlockId) return null;

  const checkboxProps = block.props as FormCheckboxBlockProps;
  const groupLabelDisplay = checkboxProps.groupLabelDisplay ?? "visible";

  return (
    <div className="space-y-3 text-xs">
      <h3 className="text-[11px] font-semibold text-slate-800 dark:text-slate-200">{m.sectionTitle}</h3>

      <label className="flex flex-col gap-1">
        <span className="text-slate-500 dark:text-slate-400">{m.groupTitleTypeLabel}</span>
        <select
          className="w-full rounded border border-slate-300 bg-white px-2 py-1 text-[11px] text-slate-900 outline-none focus:border-sky-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100"
          value={checkboxProps.groupLabelMode ?? "text"}
          onChange={(e) =>
            updateBlock(selectedBlockId, {
              groupLabelMode: e.target.value,
            } as any)
          }
        >
          <option value="text">{m.groupTitleTypeOptionText}</option>
          <option value="image">{m.groupTitleTypeOptionImage}</option>
        </select>
      </label>

      <label className="flex flex-col gap-1">
        <span className="text-slate-500 dark:text-slate-400">{m.groupTitleDisplayLabel}</span>
        <select
          className="w-full rounded border border-slate-300 bg-white px-2 py-1 text-[11px] text-slate-900 outline-none focus:border-sky-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100"
          value={groupLabelDisplay}
          onChange={(e) =>
            updateBlock(selectedBlockId, {
              groupLabelDisplay: e.target.value,
            } as any)
          }
        >
          <option value="visible">{m.groupTitleDisplayOptionVisible}</option>
          <option value="hidden">{m.groupTitleDisplayOptionHidden}</option>
        </select>
      </label>

      {groupLabelDisplay === "visible" && (
        <label className="flex flex-col gap-1 text-[11px] text-slate-500 dark:text-slate-400">
          <span>{m.layoutLabel}</span>
          <select
            className="w-full rounded border border-slate-300 bg-white px-2 py-1 text-[11px] text-slate-900 outline-none focus:border-sky-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100"
            value={checkboxProps.labelLayout ?? "stacked"}
            onChange={(e) =>
              updateBlock(selectedBlockId, {
                labelLayout: e.target.value,
              } as any)
            }
          >
            <option value="stacked">{m.layoutOptionStacked}</option>
            <option value="inline">{m.layoutOptionInline}</option>
          </select>
        </label>
      )}

      <label className="flex flex-col gap-1 text-[11px] text-slate-500 dark:text-slate-400">
        <span>{m.optionLayoutLabel}</span>
        <select
          className="w-full rounded border border-slate-300 bg-white px-2 py-1 text-[11px] text-slate-900 outline-none focus:border-sky-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100"
          value={checkboxProps.optionLayout ?? "stacked"}
          onChange={(e) =>
            updateBlock(selectedBlockId, {
              optionLayout: e.target.value,
            } as any)
          }
        >
          <option value="stacked">{m.layoutOptionStacked}</option>
          <option value="inline">{m.layoutOptionInline}</option>
        </select>
      </label>

      {groupLabelDisplay === "visible" && (checkboxProps.labelLayout ?? "stacked") === "inline" && (
        <NumericPropertyControl
          label={m.labelGapLabel}
          unitLabel="(px)"
          value={typeof checkboxProps.labelGapPx === "number" ? checkboxProps.labelGapPx : 8}
          min={0}
          max={80}
          step={2}
          presets={[
            { id: "tight", label: "Tight", value: 4 },
            { id: "normal", label: "Normal", value: 8 },
            { id: "relaxed", label: "Relaxed", value: 12 },
            { id: "extra", label: "Extra", value: 16 },
          ]}
          onChangeValue={(v) =>
            updateBlock(selectedBlockId, {
              labelGapPx: v,
            } as any)
          }
        />
      )}

      <label className="flex flex-col gap-1">
        <span className="text-slate-500 dark:text-slate-400">{m.groupTitleLabel}</span>
        <input
          className="w-full rounded border border-slate-300 bg-white px-2 py-1 text-xs text-slate-900 outline-none focus:border-sky-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100"
          value={checkboxProps.groupLabel ?? ""}
          onChange={(e) =>
            updateBlock(selectedBlockId, {
              groupLabel: e.target.value,
            } as any)
          }
        />
      </label>

      {checkboxProps.groupLabelMode === "image" && (() => {
        const source: "url" | "upload" =
          checkboxProps.groupLabelImageSource ??
          (checkboxProps.groupLabelImageUrl && checkboxProps.groupLabelImageUrl.startsWith("/api/image/")
            ? "upload"
            : "url");

        return (
          <div className="space-y-1">
            <label className="flex flex-col gap-1">
              <span className="text-slate-400">{m.groupTitleImageSourceLabel}</span>
              <select
                className="w-full rounded border border-slate-300 bg-white px-2 py-1 text-[11px] text-slate-900 outline-none focus:border-sky-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100"
                value={source}
                onChange={(e) =>
                  updateBlock(selectedBlockId, {
                    groupLabelImageSource: e.target.value,
                  } as any)
                }
              >
                <option value="url">{m.groupTitleImageSourceOptionUrl}</option>
                <option value="upload">{m.groupTitleImageSourceOptionUpload}</option>
              </select>
            </label>

            {source === "url" && (
              <label className="flex flex-col gap-1">
                <span className="text-slate-400">{m.groupTitleImageUrlLabel}</span>
                <input
                  className="w-full rounded border border-slate-300 bg-white px-2 py-1 text-xs text-slate-900 outline-none focus:border-sky-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100"
                  value={checkboxProps.groupLabelImageUrl ?? ""}
                  onChange={(e) =>
                    updateBlock(selectedBlockId, {
                      groupLabelImageUrl: e.target.value,
                    } as any)
                  }
                />
              </label>
            )}

            {source === "upload" && (
              <label className="flex flex-col gap-1">
                <span className="text-slate-400">{m.groupTitleImageUploadLabel}</span>
                <input
                  type="file"
                  accept="image/*"
                  className="w-full text-[11px] text-slate-300 file:mr-2 file:rounded file:border file:border-slate-700 file:bg-slate-800 file:px-2 file:py-1 file:text-[11px] file:text-slate-100 hover:file:bg-slate-700"
                  aria-label={m.groupTitleImageUploadAria}
                  onChange={async (event) => {
                    const file = event.target.files?.[0];
                    if (!file) return;

                    try {
                      const formData = new FormData();
                      formData.append("file", file);

                      const response = await fetch("/api/image", {
                        method: "POST",
                        body: formData,
                      });

                      if (!response.ok) {
                        console.error("체크박스 그룹 라벨 이미지 업로드 실패", await response.text());
                        return;
                      }

                      const data = (await response.json()) as { id: string; servedUrl?: string | null };
                      const servedUrl = data.servedUrl ?? `/api/image/${data.id}`;

                      updateBlock(selectedBlockId, {
                        groupLabelImageUrl: servedUrl,
                        groupLabelImageSource: "upload",
                      } as any);
                    } catch (error) {
                      console.error("체크박스 그룹 라벨 이미지 업로드 중 오류", error);
                    } finally {
                      event.target.value = "";
                    }
                  }}
                />
              </label>
            )}
          </div>
        );
      })()}

      <label className="flex flex-col gap-1">
        <span className="text-slate-500 dark:text-slate-400">{m.submitKeyLabel}</span>
        <input
          className="w-full rounded border border-slate-300 bg-white px-2 py-1 text-xs text-slate-900 outline-none focus:border-sky-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100"
          value={checkboxProps.formFieldName ?? ""}
          onChange={(e) =>
            updateBlock(selectedBlockId, {
              formFieldName: e.target.value,
            } as any)
          }
        />
      </label>

      <div className="space-y-2">
        <div className="flex items-center justify-between">
          <span className="text-slate-500 dark:text-slate-400">{m.optionsLabel}</span>
          <button
            type="button"
            className="rounded border border-slate-300 bg-white px-2 py-0.5 text-[10px] text-slate-900 hover:bg-slate-100 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100 dark:hover:bg-slate-800"
            onClick={() => {
              const next = Array.isArray((checkboxProps as any).options)
                ? [...(checkboxProps as any).options]
                : [];
              next.push({
                label: "New option",
                value: `option_${next.length + 1}`,
              });
              updateBlock(selectedBlockId, {
                options: next,
              } as any);
            }}
          >
            {m.addOptionButtonLabel}
          </button>
        </div>
        <div className="space-y-2">
          <label className="flex flex-col gap-1">
            <span className="text-slate-500 dark:text-slate-400">{m.optionImageSourceLabel}</span>
            <select
              className="w-full rounded border border-slate-300 bg-white px-2 py-1 text-[11px] text-slate-900 outline-none focus:border-sky-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100"
              value={(() => {
                if (checkboxProps.optionImageSource) return checkboxProps.optionImageSource;
                const first = (((checkboxProps as any).options ?? []) as any[])[0];
                if (first?.labelImageUrl && first.labelImageUrl.startsWith("/api/image/")) return "upload";
                return "url";
              })()}
              onChange={(e) =>
                updateBlock(selectedBlockId, {
                  optionImageSource: e.target.value,
                } as any)
              }
            >
              <option value="url">{m.optionImageSourceOptionUrl}</option>
              <option value="upload">{m.optionImageSourceOptionUpload}</option>
            </select>
          </label>

          {(((checkboxProps as any).options ?? []) as any[]).map((opt, index) => (
            <div key={opt.value ?? index} className="space-y-1 rounded border border-slate-800 p-2">
              <div className="grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_auto] items-center gap-1">
                <input
                  className="flex-1 rounded border border-slate-300 bg-white px-2 py-1 text-[11px] text-slate-900 outline-none focus:border-sky-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100"
                  placeholder={m.optionLabelPlaceholder}
                  value={opt.label ?? ""}
                  onChange={(e) => {
                    const next = [...(((checkboxProps as any).options ?? []) as any[])];
                    next[index] = {
                      ...next[index],
                      label: e.target.value,
                    };
                    updateBlock(selectedBlockId, {
                      options: next,
                    } as any);
                  }}
                />
                <input
                  className="flex-1 rounded border border-slate-300 bg-white px-2 py-1 text-[11px] text-slate-900 outline-none focus:border-sky-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100"
                  placeholder={m.optionValuePlaceholder}
                  value={opt.value ?? ""}
                  onChange={(e) => {
                    const next = [...(((checkboxProps as any).options ?? []) as any[])];
                    next[index] = {
                      ...next[index],
                      value: e.target.value,
                    };
                    updateBlock(selectedBlockId, {
                      options: next,
                    } as any);
                  }}
                />
                <button
                  type="button"
                  className="h-7 w-7 rounded border border-slate-300 bg-white text-[10px] text-slate-900 hover:bg-slate-100 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100 dark:hover:bg-red-900/60 dark:hover:border-red-700"
                  onClick={() => {
                    const next = (((checkboxProps as any).options ?? []) as any[]).filter((_, i) => i !== index);
                    updateBlock(selectedBlockId, {
                      options: next,
                    } as any);
                  }}
                >
                  ×
                </button>
              </div>
              <div className="flex flex-col gap-1">
                {(() => {
                  const source: "url" | "upload" =
                    checkboxProps.optionImageSource ??
                    (opt.labelImageUrl && opt.labelImageUrl.startsWith("/api/image/") ? "upload" : "url");

                  return (
                    <>
                      {source === "url" && (
                        <input
                          className="w-full rounded border border-slate-300 bg-white px-2 py-1 text-[11px] text-slate-900 outline-none focus:border-sky-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100"
                          placeholder={m.optionImageUrlPlaceholder}
                          value={opt.labelImageUrl ?? ""}
                          onChange={(e) => {
                            const next = [...(((checkboxProps as any).options ?? []) as any[])];
                            next[index] = {
                              ...next[index],
                              labelImageUrl: e.target.value,
                            };
                            updateBlock(selectedBlockId, {
                              options: next,
                            } as any);
                          }}
                        />
                      )}
                      {source === "upload" && (
                        <label className="flex flex-col gap-1">
                          <span className="text-slate-500 dark:text-slate-400">{m.optionImageUploadLabel}</span>
                          <input
                            type="file"
                            accept="image/*"
                            className="w-full text-[11px] text-slate-300 file:mr-2 file:rounded file:border file:border-slate-700 file:bg-slate-800 file:px-2 file:py-1 file:text-[11px] file:text-slate-100 hover:file:bg-slate-700"
                            aria-label={m.optionImageUploadAria}
                            onChange={async (event) => {
                              const file = event.target.files?.[0];
                              if (!file) return;

                              try {
                                const formData = new FormData();
                                formData.append("file", file);

                                const response = await fetch("/api/image", {
                                  method: "POST",
                                  body: formData,
                                });

                                if (!response.ok) {
                                  console.error("체크박스 옵션 라벨 이미지 업로드 실패", await response.text());
                                  return;
                                }

                                const data = (await response.json()) as { id: string; servedUrl?: string | null };
                                const servedUrl = data.servedUrl ?? `/api/image/${data.id}`;

                                const next = [...(((checkboxProps as any).options ?? []) as any[])];
                                next[index] = {
                                  ...next[index],
                                  labelImageUrl: servedUrl,
                                };

                                updateBlock(selectedBlockId, {
                                  options: next,
                                  optionImageSource: "upload",
                                } as any);
                              } catch (error) {
                                console.error("체크박스 옵션 라벨 이미지 업로드 중 오류", error);
                              } finally {
                                event.target.value = "";
                              }
                            }}
                          />
                        </label>
                      )}
                    </>
                  );
                })()}
              </div>
            </div>
          ))}
        </div>
      </div>

      <label className="inline-flex items-center gap-2">
        <span className="text-slate-500">{m.requiredNoticeText}</span>
      </label>

      <div className="mt-3 space-y-2 border-t border-slate-800 pt-3">
        <h4 className="text-[11px] font-semibold text-slate-800 dark:text-slate-200">{m.styleSectionTitle}</h4>
        {/* px 기반 체크박스 타이포 입력값을 노출하여 em 스케일 변환을 위한 근거를 남긴다 */}
        <NumericPropertyControl
          label={m.textSizeLabel}
          unitLabel={m.textSizeUnitLabel}
          value={(() => {
            const raw = checkboxProps.fontSizeCustom ?? "";
            const match = raw.match(/([0-9]+(?:\.[0-9]+)?)/);
            if (match) return Number(match[1]);
            return 14;
          })()}
          min={8}
          max={40}
          step={1}
          presets={[
            { id: "xs", label: "XS", value: 12 },
            { id: "sm", label: "S", value: 14 },
            { id: "md", label: "M", value: 16 },
            { id: "lg", label: "L", value: 18 },
            { id: "xl", label: "XL", value: 20 },
          ]}
          onChangeValue={(v) =>
            updateBlock(selectedBlockId, {
              fontSizeCustom: `${v}px`,
            } as any)
          }
        />
        {/* 줄간격 px 입력값을 노출해 preview em 변환과 TDD 케이스를 연동한다 */}
        <NumericPropertyControl
          label={m.lineHeightLabel}
          unitLabel={m.lineHeightUnitLabel}
          value={(() => {
            const raw = checkboxProps.lineHeightCustom ?? "";
            const match = raw.match(/([0-9]+(?:\.[0-9]+)?)/);
            if (match) return Number(match[1]);
            return 20;
          })()}
          min={8}
          max={60}
          step={1}
          presets={[
            { id: "tight", label: "Tight", value: 18 },
            { id: "normal", label: "Normal", value: 24 },
            { id: "loose", label: "Loose", value: 32 },
          ]}
          onChangeValue={(v) =>
            updateBlock(selectedBlockId, {
              lineHeightCustom: `${v}px`,
            } as any)
          }
        />
        {/* 자간 px 입력을 통한 폼 체크박스 미세 조정값을 노출 */}
        <NumericPropertyControl
          label={m.letterSpacingLabel}
          unitLabel={m.letterSpacingUnitLabel}
          value={(() => {
            const raw = checkboxProps.letterSpacingCustom ?? "";
            const match = raw.match(/(-?[0-9]+(?:\.[0-9]+)?)/);
            if (match) return Number(match[1]);
            return 0;
          })()}
          min={-10}
          max={20}
          step={0.5}
          presets={[
            { id: "tight", label: "Tight", value: -1 },
            { id: "normal", label: "Normal", value: 0 },
            { id: "wide", label: "Wide", value: 2 },
          ]}
          onChangeValue={(v) =>
            updateBlock(selectedBlockId, {
              letterSpacingCustom: `${v}px`,
            } as any)
          }
        />
        <label className="flex flex-col gap-1 text-[11px] text-slate-400">
          <span>{m.widthModeLabel}</span>
          <select
            className="w-full rounded border border-slate-300 bg-white px-2 py-1 text-[11px] text-slate-900 outline-none focus:border-sky-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100"
            value={checkboxProps.widthMode ?? "full"}
            onChange={(e) =>
              updateBlock(selectedBlockId, {
                widthMode: e.target.value,
              } as any)
            }
          >
            <option value="auto">{m.widthModeOptionAuto}</option>
            <option value="full">{m.widthModeOptionFull}</option>
            <option value="fixed">{m.widthModeOptionFixed}</option>
          </select>
        </label>
        {(checkboxProps.widthMode ?? "full") === "fixed" && (
          <NumericPropertyControl
            label={m.fixedWidthLabel}
            unitLabel={m.fixedWidthUnitLabel}
            value={checkboxProps.widthPx ?? 240}
            min={80}
            max={800}
            step={10}
            presets={[
              { id: "sm", label: "Small", value: 200 },
              { id: "md", label: "Medium", value: 280 },
              { id: "lg", label: "Large", value: 360 },
            ]}
            onChangeValue={(v) =>
              updateBlock(selectedBlockId, {
                widthPx: v,
              } as any)
            }
          />
        )}
        <NumericPropertyControl
          label={m.paddingXLabel}
          unitLabel={m.paddingXUnitLabel}
          value={typeof checkboxProps.paddingX === "number" ? checkboxProps.paddingX : 12}
          min={0}
          max={60}
          step={2}
          presets={[
            { id: "xs", label: "Extra thin", value: 6 },
            { id: "sm", label: "Thin", value: 10 },
            { id: "md", label: "Normal", value: 12 },
            { id: "lg", label: "Wide", value: 16 },
            { id: "xl", label: "Extra wide", value: 20 },
          ]}
          onChangeValue={(v) =>
            updateBlock(selectedBlockId, {
              paddingX: v,
            } as any)
          }
        />
        <NumericPropertyControl
          label={m.paddingYLabel}
          unitLabel={m.paddingYUnitLabel}
          value={typeof checkboxProps.paddingY === "number" ? checkboxProps.paddingY : 10}
          min={0}
          max={40}
          step={1}
          presets={[
            { id: "xs", label: "Extra thin", value: 6 },
            { id: "sm", label: "Thin", value: 8 },
            { id: "md", label: "Normal", value: 10 },
            { id: "lg", label: "Wide", value: 12 },
            { id: "xl", label: "Extra wide", value: 16 },
          ]}
          onChangeValue={(v) =>
            updateBlock(selectedBlockId, {
              paddingY: v,
            } as any)
          }
        />
        <NumericPropertyControl
          label={m.optionGapLabel}
          unitLabel={m.optionGapUnitLabel}
          value={typeof checkboxProps.optionGapPx === "number" ? checkboxProps.optionGapPx : 4}
          min={0}
          max={40}
          step={1}
          presets={[
            { id: "tight", label: "Tight", value: 2 },
            { id: "normal", label: "Normal", value: 4 },
            { id: "relaxed", label: "Relaxed", value: 8 },
            { id: "extra", label: "Extra", value: 12 },
          ]}
          onChangeValue={(v) =>
            updateBlock(selectedBlockId, {
              optionGapPx: v,
            } as any)
          }
        />
        <ColorPickerField
          label={m.textColorLabel}
          ariaLabelColorInput={m.textColorPickerAria}
          ariaLabelHexInput={m.textColorHexAria}
          value={
            checkboxProps.textColorCustom && checkboxProps.textColorCustom.trim() !== ""
              ? checkboxProps.textColorCustom
              : ""
          }
          onChange={(hex) => {
            updateBlock(selectedBlockId, {
              textColorCustom: hex,
            } as any);
          }}
          palette={TEXT_COLOR_PALETTE}
          onPaletteSelect={(item) => {
            updateBlock(selectedBlockId, {
              textColorCustom: item.color,
            } as any);
          }}
        />
        <ColorPickerField
          label={m.fillColorLabel}
          ariaLabelColorInput={m.fillColorPickerAria}
          ariaLabelHexInput={m.fillColorHexAria}
          value={
            checkboxProps.fillColorCustom && checkboxProps.fillColorCustom.trim() !== ""
              ? checkboxProps.fillColorCustom
              : ""
          }
          onChange={(hex) => {
            updateBlock(selectedBlockId, {
              fillColorCustom: hex,
            } as any);
          }}
          palette={TEXT_COLOR_PALETTE}
          onPaletteSelect={(item) => {
            updateBlock(selectedBlockId, {
              fillColorCustom: item.color,
            } as any);
          }}
        />
        <ColorPickerField
          label={m.strokeColorLabel}
          ariaLabelColorInput={m.strokeColorPickerAria}
          ariaLabelHexInput={m.strokeColorHexAria}
          value={
            checkboxProps.strokeColorCustom && checkboxProps.strokeColorCustom.trim() !== ""
              ? checkboxProps.strokeColorCustom
              : ""
          }
          onChange={(hex) => {
            updateBlock(selectedBlockId, {
              strokeColorCustom: hex,
            } as any);
          }}
          palette={TEXT_COLOR_PALETTE}
          onPaletteSelect={(item) => {
            updateBlock(selectedBlockId, {
              strokeColorCustom: item.color,
            } as any);
          }}
        />
        <NumericPropertyControl
          label={m.borderRadiusLabel}
          value={(() => {
            const r = checkboxProps.borderRadius ?? "md";
            return r === "none" ? 0 : r === "sm" ? 2 : r === "lg" ? 6 : r === "full" ? 8 : 4;
          })()}
          min={0}
          max={8}
          step={1}
          presets={[
            { id: "none", label: m.borderRadiusPresetNone, value: 0 },
            { id: "sm", label: m.borderRadiusPresetSmall, value: 2 },
            { id: "md", label: m.borderRadiusPresetMedium, value: 4 },
            { id: "lg", label: m.borderRadiusPresetLarge, value: 6 },
            { id: "full", label: m.borderRadiusPresetFull, value: 8 },
          ]}
          onChangeValue={(v) => {
            const next =
              v <= 0 ? "none" : v <= 2 ? "sm" : v <= 5 ? "md" : v <= 7 ? "lg" : "full";
            updateBlock(selectedBlockId, {
              borderRadius: next,
            } as any);
          }}
        />
      </div>
    </div>
  );
}
