"use client";

import type { ButtonBlockProps } from "@/features/editor/state/editorStore";
import { NumericPropertyControl } from "@/features/editor/components/NumericPropertyControl";
import { ColorPickerField, TEXT_COLOR_PALETTE } from "@/features/editor/components/ColorPickerField";
import { useAppLocale } from "@/features/i18n/LocaleProvider";
import { getEditorButtonPanelMessages } from "@/features/i18n/messages/editorButtonPanel";

export type ButtonPropertiesPanelProps = {
  buttonProps: ButtonBlockProps;
  selectedBlockId: string;
  updateBlock: (id: string, partial: Partial<ButtonBlockProps>) => void;
};

export function ButtonPropertiesPanel({ buttonProps, selectedBlockId, updateBlock }: ButtonPropertiesPanelProps) {
  const locale = useAppLocale();
  const m = getEditorButtonPanelMessages(locale);
  const imageSource: "none" | "url" | "upload" = (() => {
    const hasSrc = (buttonProps.imageSrc ?? "").trim() !== "";
    if (!hasSrc) return "none";
    if (buttonProps.imageSourceType === "asset") return "upload";
    return "url";
  })();

  return (
    <>
      <div className="space-y-1">
        <label className="flex flex-col gap-1 text-xs text-slate-400">
          <span>{m.buttonTextLabel}</span>
          <textarea
            className="w-full min-h-[60px] 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"
            aria-label={m.buttonTextAria}
            value={buttonProps.label}
            onChange={(e) => {
              updateBlock(selectedBlockId, { label: e.target.value } as any);
            }}
          />
        </label>
      </div>
      <div className="mt-3 space-y-2 border-t border-slate-800 pt-3 text-xs text-slate-400">
        <h4 className="text-[11px] font-semibold text-slate-800 dark:text-slate-200">{m.imageSectionTitle}</h4>

        <div className="space-y-1">
          <label className="flex flex-col gap-1">
            <span>{m.imageSourceLabel}</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"
              aria-label={m.imageSourceAria}
              value={imageSource}
              onChange={(e) => {
                const next = e.target.value as "none" | "url" | "upload";
                if (next === "none") {
                  updateBlock(selectedBlockId, {
                    imageSrc: "",
                    imageAssetId: null,
                  } as any);
                } else if (next === "url") {
                  updateBlock(selectedBlockId, {
                    imageSourceType: "externalUrl",
                    imageAssetId: null,
                  } as any);
                } else {
                  updateBlock(selectedBlockId, {
                    imageSourceType: "asset",
                  } as any);
                }
              }}
            >
              <option value="none">{m.imageSourceOptionNone}</option>
              <option value="url">{m.imageSourceOptionUrl}</option>
              <option value="upload">{m.imageSourceOptionUpload}</option>
            </select>
          </label>
        </div>

        {imageSource === "url" && (
          <div className="space-y-1">
            <label className="flex flex-col gap-1">
              <span>{m.imageUrlLabel}</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"
                aria-label={m.imageUrlAria}
                value={buttonProps.imageSrc ?? ""}
                onChange={(e) => {
                  const value = e.target.value;
                  updateBlock(selectedBlockId, {
                    imageSrc: value,
                    imageSourceType: "externalUrl",
                    imageAssetId: null,
                  } as any);
                }}
              />
            </label>
          </div>
        )}

        {imageSource === "upload" && (
          <div className="space-y-1">
            <label className="flex flex-col gap-1">
              <span>{m.imageUploadLabel}</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.imageUploadAria}
                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("Button image upload failed", 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, {
                      imageSrc: servedUrl,
                      imageSourceType: "asset",
                      imageAssetId: data.id,
                    } as any);
                  } catch (error) {
                    console.error("Error while uploading button image", error);
                  } finally {
                    event.target.value = "";
                  }
                }}
              />
            </label>
          </div>
        )}

        {imageSource !== "none" && (
          <>
            <div className="space-y-1">
              <label className="flex flex-col gap-1">
                <span>{m.imageAltLabel}</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"
                  aria-label={m.imageAltAria}
                  value={buttonProps.imageAlt ?? ""}
                  onChange={(e) => {
                    updateBlock(selectedBlockId, { imageAlt: e.target.value } as any);
                  }}
                />
              </label>
            </div>

            <div className="space-y-1">
              <label className="flex flex-col gap-1">
                <span>{m.imagePlacementLabel}</span>
                <select
                  className="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"
                  aria-label={m.imagePlacementAria}
                  value={buttonProps.imagePlacement ?? "left"}
                  onChange={(e) => {
                    updateBlock(selectedBlockId, {
                      imagePlacement: e.target.value as any,
                    } as any);
                  }}
                >
                  <option value="left">{m.imagePlacementOptionLeft}</option>
                  <option value="right">{m.imagePlacementOptionRight}</option>
                  <option value="top">{m.imagePlacementOptionTop}</option>
                  <option value="bottom">{m.imagePlacementOptionBottom}</option>
                </select>
              </label>
            </div>
          </>
        )}
      </div>
      <div className="space-y-1">
        <NumericPropertyControl
          label={m.paddingXLabel}
          unitLabel="(px)"
          value={buttonProps.paddingX ?? 16}
          min={0}
          max={120}
          step={4}
          presets={[
            { id: "xs", label: "XS", value: 8 },
            { id: "sm", label: "S", value: 12 },
            { id: "md", label: "M", value: 16 },
            { id: "lg", label: "L", value: 24 },
            { id: "xl", label: "XL", value: 32 },
          ]}
          onChangeValue={(v) => {
            updateBlock(selectedBlockId, {
              paddingX: v,
            } as any);
          }}
        />
      </div>
      <div className="space-y-1">
        <NumericPropertyControl
          label={m.paddingYLabel}
          unitLabel="(px)"
          value={buttonProps.paddingY ?? 10}
          min={0}
          max={80}
          step={2}
          presets={[
            { id: "xs", label: "XS", value: 6 },
            { id: "sm", label: "S", value: 8 },
            { id: "md", label: "M", value: 10 },
            { id: "lg", label: "L", value: 14 },
            { id: "xl", label: "XL", value: 20 },
          ]}
          onChangeValue={(v) => {
            updateBlock(selectedBlockId, {
              paddingY: v,
            } as any);
          }}
        />
      </div>
      <div className="space-y-1">
        <label className="flex flex-col gap-1 text-xs text-slate-400">
          <span>{m.linkLabel}</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"
            aria-label={m.linkAria}
            value={buttonProps.href}
            onChange={(e) => {
              updateBlock(selectedBlockId, { href: e.target.value } as any);
            }}
          />
        </label>
      </div>
      <div className="space-y-1">
        <label className="flex flex-col gap-1 text-xs text-slate-400">
          <span>{m.alignLabel}</span>
          <select
            className="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"
            aria-label={m.alignAria}
            value={buttonProps.align ?? "left"}
            onChange={(e) => {
              const value = e.target.value as NonNullable<ButtonBlockProps["align"]>;
              updateBlock(selectedBlockId, { align: value } as any);
            }}
          >
            <option value="left">{m.alignOptionLeft}</option>
            <option value="center">{m.alignOptionCenter}</option>
            <option value="right">{m.alignOptionRight}</option>
          </select>
        </label>
      </div>
      <div className="space-y-1">
        {/* 버튼 크기 스케일 컨트롤은 paddingX/paddingY 및 폰트 크기(px) 컨트롤로 충분하므로 제거했다. */}
      </div>
      <div className="space-y-1">
        <ColorPickerField
          label={m.textColorLabel}
          ariaLabelColorInput={m.textColorPickerAria}
          ariaLabelHexInput={m.textColorHexAria}
          value={
            buttonProps.textColorCustom && buttonProps.textColorCustom.trim() !== ""
              ? buttonProps.textColorCustom
              : ""
          }
          onChange={(hex) => {
            updateBlock(selectedBlockId, {
              textColorCustom: hex,
            } as any);
          }}
          palette={TEXT_COLOR_PALETTE}
          onPaletteSelect={(item) => {
            updateBlock(selectedBlockId, {
              textColorCustom: item.color,
            } as any);
          }}
        />
      </div>
      <div className="space-y-1">
        <label className="flex flex-col gap-1 text-xs text-slate-400">
          <span>{m.styleLabel}</span>
          <select
            className="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"
            aria-label={m.styleAria}
            value={buttonProps.variant ?? "solid"}
            onChange={(e) => {
              const value = e.target.value as NonNullable<ButtonBlockProps["variant"]>;
              updateBlock(selectedBlockId, { variant: value } as any);
            }}
          >
            <option value="solid">{m.styleOptionSolid}</option>
            <option value="outline">{m.styleOptionOutline}</option>
            <option value="ghost">{m.styleOptionGhost}</option>
          </select>
        </label>
      </div>
      <div className="space-y-1">
        <ColorPickerField
          label={m.fillColorLabel}
          ariaLabelColorInput={m.fillColorPickerAria}
          ariaLabelHexInput={m.fillColorHexAria}
          value={
            buttonProps.fillColorCustom && buttonProps.fillColorCustom.trim() !== ""
              ? buttonProps.fillColorCustom
              : ""
          }
          onChange={(hex) => {
            updateBlock(selectedBlockId, {
              fillColorCustom: hex,
            } as any);
          }}
          palette={TEXT_COLOR_PALETTE}
          onPaletteSelect={(item) => {
            updateBlock(selectedBlockId, {
              fillColorCustom: item.color,
            } as any);
          }}
        />
      </div>
      <div className="space-y-1">
        <ColorPickerField
          label={m.strokeColorLabel}
          ariaLabelColorInput={m.strokeColorPickerAria}
          ariaLabelHexInput={m.strokeColorHexAria}
          value={
            buttonProps.strokeColorCustom && buttonProps.strokeColorCustom.trim() !== ""
              ? buttonProps.strokeColorCustom
              : ""
          }
          onChange={(hex) => {
            updateBlock(selectedBlockId, {
              strokeColorCustom: hex,
            } as any);
          }}
          palette={TEXT_COLOR_PALETTE}
          onPaletteSelect={(item) => {
            updateBlock(selectedBlockId, {
              strokeColorCustom: item.color,
            } as any);
          }}
        />
      </div>
      <div className="space-y-1">
        <NumericPropertyControl
          label={m.borderRadiusLabel}
          value={(() => {
            const r = buttonProps.borderRadius ?? "md";
            return r === "none" ? 0 : r === "sm" ? 1 : r === "lg" ? 3 : r === "full" ? 4 : 2;
          })()}
          min={0}
          max={4}
          step={1}
          presets={[
            { id: "none", label: m.borderRadiusPresetNone, value: 0 },
            { id: "sm", label: m.borderRadiusPresetSmall, value: 1 },
            { id: "md", label: m.borderRadiusPresetMedium, value: 2 },
            { id: "lg", label: m.borderRadiusPresetLarge, value: 3 },
            { id: "full", label: m.borderRadiusPresetFull, value: 4 },
          ]}
          onChangeValue={(v) => {
            const next =
              v <= 0 ? "none" : v === 1 ? "sm" : v === 3 ? "lg" : v >= 4 ? "full" : "md";
            updateBlock(selectedBlockId, { borderRadius: next } as any);
          }}
        />
      </div>
      <div className="space-y-1">
        <label className="flex flex-col gap-1 text-xs text-slate-400">
          <span>{m.widthModeLabel}</span>
          <select
            className="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"
            aria-label={m.widthModeAria}
            value={buttonProps.widthMode ?? (buttonProps.fullWidth ? "full" : "auto")}
            onChange={(e) => {
              updateBlock(selectedBlockId, {
                widthMode: e.target.value as NonNullable<ButtonBlockProps["widthMode"]>,
              } as any);
            }}
          >
            <option value="auto">{m.widthModeOptionAuto}</option>
            <option value="full">{m.widthModeOptionFull}</option>
            <option value="fixed">{m.widthModeOptionFixed}</option>
          </select>
        </label>
        {(buttonProps.widthMode ?? (buttonProps.fullWidth ? "full" : "auto")) === "fixed" && (
          <NumericPropertyControl
            label={m.fixedWidthLabel}
            unitLabel={m.fixedWidthUnitLabel}
            value={buttonProps.widthPx ?? 240}
            min={80}
            max={600}
            step={10}
            presets={[
              { id: "sm", label: m.fixedWidthPresetSmall, value: 180 },
              { id: "md", label: m.fixedWidthPresetMedium, value: 240 },
              { id: "lg", label: m.fixedWidthPresetLarge, value: 320 },
            ]}
            onChangeValue={(v) => {
              updateBlock(selectedBlockId, {
                widthPx: v,
              } as any);
            }}
          />
        )}
      </div>
      <div className="space-y-1">
        <NumericPropertyControl
          label={m.fontSizeLabel}
          unitLabel={m.fontSizeUnitLabel}
          value={(() => {
            const raw = buttonProps.fontSizeCustom ?? "";
            const match = raw.match(/([0-9]+(?:\.[0-9]+)?)/);
            if (match) return Number(match[1]);
            // 기본 버튼 텍스트 크기: md 스케일(16px) 기준
            return 16;
          })()}
          min={10}
          max={32}
          step={1}
          presets={[
            { id: "xs", label: "XS", value: 12 },
            { id: "sm", label: "S", value: 14 },
            { id: "base", label: "M", value: 16 },
            { id: "lg", label: "L", value: 18 },
            { id: "xl", label: "XL", value: 20 },
            { id: "2xl", label: "2XL", value: 24 },
            { id: "3xl", label: "3XL", value: 30 },
          ]}
          onChangeValue={(px) => {
            // 버튼은 텍스트 스케일 상태 없이 px만 저장하지만,
            // 프리셋 값은 TextPropertiesPanel과 동일한 테이블을 사용한다.
            updateBlock(selectedBlockId, {
              fontSizeCustom: `${px}px`,
            } as any);
          }}
        />
      </div>
      <div className="space-y-1">
        <NumericPropertyControl
          label={m.lineHeightLabel}
          value={(() => {
            const raw = buttonProps.lineHeightCustom ?? "";
            const match = raw.match(/(-?[0-9]+(?:\.[0-9]+)?)/);
            if (match) return Number(match[1]);
            return 1.4;
          })()}
          min={0.8}
          max={3}
          step={0.05}
          presets={[
            { id: "tight", label: m.lineHeightPresetTight, value: 1.1 },
            { id: "normal", label: m.lineHeightPresetNormal, value: 1.4 },
            { id: "relaxed", label: m.lineHeightPresetRelaxed, value: 1.8 },
          ]}
          onChangeValue={(v) => {
            updateBlock(selectedBlockId, {
              lineHeightCustom: v.toString(),
            } as any);
          }}
        />
      </div>
      <div className="space-y-1">
        <NumericPropertyControl
          label={m.letterSpacingLabel}
          unitLabel={m.letterSpacingUnitLabel}
          value={(() => {
            const raw = buttonProps.letterSpacingCustom ?? "";
            const match = raw.match(/(-?[0-9]+(?:\.[0-9]+)?)/);
            if (match) {
              const em = Number(match[1]);
              if (Number.isFinite(em)) return em * 16;
            }
            return 0;
          })()}
          min={-32}
          max={32}
          step={1}
          presets={[
            { id: "tighter", label: m.letterSpacingPresetTighter, value: -1.5 },
            { id: "tight", label: m.letterSpacingPresetTight, value: -0.5 },
            { id: "normal", label: m.letterSpacingPresetNormal, value: 0 },
            { id: "wide", label: m.letterSpacingPresetWide, value: 1 },
            { id: "wider", label: m.letterSpacingPresetWider, value: 2 },
          ]}
          onChangeValue={(px) => {
            const em = px / 16;
            updateBlock(selectedBlockId, {
              letterSpacingCustom: `${em}em`,
            } as any);
          }}
        />
      </div>
    </>
  );
}
