"use client";

import type { ListBlockProps } from "@/features/editor/state/editorStore";
import {
  buildItemsTreeFromItems,
  itemsTreeToLines,
  linesToItemsTree,
  parseTextareaToLines,
  stringifyLinesToTextarea,
} from "@/features/editor/state/editorStore";
import { NumericPropertyControl } from "@/features/editor/components/NumericPropertyControl";
import { ColorPickerField, TEXT_COLOR_PALETTE } from "@/features/editor/components/ColorPickerField";

export type ListPropertiesPanelProps = {
  listProps: ListBlockProps;
  selectedBlockId: string;
  selectedListItemId: string | null;
  updateBlock: (id: string, partial: Partial<ListBlockProps>) => void;
};

export function ListPropertiesPanel({
  listProps,
  selectedBlockId,
  selectedListItemId,
  updateBlock,
}: ListPropertiesPanelProps) {
  return (
    <>
      <div className="space-y-1">
        <label className="flex flex-col gap-1 text-xs text-slate-400">
          <span>리스트 아이템 (줄바꿈으로 구분)</span>
          <textarea
            className="w-full min-h-[80px] 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="리스트 아이템들"
            value={(() => {
              const tree = (listProps as any).itemsTree as any[] | undefined;

              if (tree && tree.length > 0) {
                // 중첩 리스트가 존재하는 경우, itemsTree → ListLine → textarea 문자열 순으로 직렬화한다.
                const lines = itemsTreeToLines(tree as any);
                return stringifyLinesToTextarea(lines as any);
              }

              // 기존 하위호환: items 배열이 있다면 그대로 줄바꿈으로 이어 붙여 사용한다.
              return (listProps.items ?? []).join("\n");
            })()}
            onChange={(e) => {
              const textValue = e.target.value;

              // textarea 내용을 ListLine 배열로 파싱한다.
              const parsedLines = parseTextareaToLines(textValue);

              // 전체 입력이 완전히 비어 있는 경우에는 빈 리스트 상태를 유지한다.
              const hasAnyContent = parsedLines.some((line) => line.text.length > 0);

              if (!hasAnyContent) {
                updateBlock(
                  selectedBlockId,
                  {
                    items: [],
                    itemsTree: [],
                  } as any,
                );
                return;
              }

              // depth 기반 라인 모델에서 중첩 리스트 트리를 생성한다.
              const nextTree = linesToItemsTree(selectedBlockId, parsedLines as any);

              // 플랫 items 배열은 기존 하위호환을 위해 text 만 뽑아서 유지한다.
              const flatItems = parsedLines.map((line) => line.text);

              updateBlock(
                selectedBlockId,
                {
                  items: flatItems,
                  itemsTree: nextTree,
                } as any,
              );
            }}
          />
        </label>
      </div>
      <div className="flex items-center justify-between text-xs text-slate-400">
        <label className="flex items-center gap-2">
          <span>정렬</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="리스트 정렬"
            value={listProps.align}
            onChange={(e) => {
              const value = e.target.value as ListBlockProps["align"];
              updateBlock(selectedBlockId, { align: value } as any);
            }}
          >
            <option value="left">왼쪽</option>
            <option value="center">가운데</option>
            <option value="right">오른쪽</option>
          </select>
        </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">리스트 스타일</h4>

        {/* 글자 크기 */}
        <NumericPropertyControl
          label="글자 크기 (px)"
          unitLabel="(px)"
          value={(() => {
            const raw = listProps.fontSizeCustom ?? "";
            const match = raw.match(/([0-9]+(?:\.[0-9]+)?)/);
            if (match) return Number(match[1]);
            return 14;
          })()}
          min={10}
          max={32}
          step={1}
          presets={[
            { id: "sm", label: "작게", value: 12 },
            { id: "md", label: "보통", value: 14 },
            { id: "lg", label: "크게", value: 18 },
          ]}
          onChangeValue={(px) => {
            updateBlock(selectedBlockId, { fontSizeCustom: `${px}px` } as any);
          }}
        />

        {/* 줄 간격 */}
        <NumericPropertyControl
          label="줄 간격"
          value={(() => {
            const raw = listProps.lineHeightCustom ?? "";
            const match = raw.match(/(-?[0-9]+(?:\.[0-9]+)?)/);
            if (match) return Number(match[1]);
            return 1.5;
          })()}
          min={1}
          max={3}
          step={0.05}
          presets={[
            { id: "tight", label: "좁게", value: 1.2 },
            { id: "normal", label: "보통", value: 1.5 },
            { id: "relaxed", label: "넓게", value: 1.8 },
          ]}
          onChangeValue={(v) => {
            updateBlock(selectedBlockId, { lineHeightCustom: v.toString() } as any);
          }}
        />

        {/* 텍스트 색상 */}
        <ColorPickerField
          label="텍스트 색상"
          ariaLabelColorInput="리스트 텍스트 색상 피커"
          ariaLabelHexInput="리스트 텍스트 색상 HEX"
          // textColorCustom 이 비어 있으면 커스텀 색상을 사용하지 않고, "없음" 상태로 취급한다.
          // 이 경우 HEX 인풋은 빈 문자열을 유지하고, 팔레트 라벨은 "없음"으로 표시된다.
          value={
            listProps.textColorCustom && listProps.textColorCustom.trim() !== ""
              ? listProps.textColorCustom
              : ""
          }
          onChange={(hex) => {
            updateBlock(selectedBlockId, { textColorCustom: hex } as any);
          }}
          palette={TEXT_COLOR_PALETTE}
          onPaletteSelect={(item) => {
            updateBlock(selectedBlockId, { textColorCustom: item.color } as any);
          }}
        />

        <ColorPickerField
          label="블록 배경색"
          ariaLabelColorInput="리스트 배경색 피커"
          ariaLabelHexInput="리스트 배경색 HEX"
          value={listProps.backgroundColorCustom ?? ""}
          onChange={(hex) => {
            updateBlock(selectedBlockId, { backgroundColorCustom: hex } as any);
          }}
          palette={TEXT_COLOR_PALETTE}
        />

        {/* 불릿 스타일 (● / ○ / ■ / 숫자형 / 없음) */}
        <label className="flex flex-col gap-1">
          <span>불릿 스타일</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="리스트 불릿 스타일"
            value={listProps.bulletStyle ?? "disc"}
            onChange={(e) => {
              const value = e.target.value as NonNullable<ListBlockProps["bulletStyle"]>;

              // 순서형 스타일(decimal / alpha / roman)은 ordered=true, 나머지는 false 로 설정한다.
              const orderedStyles: Array<NonNullable<ListBlockProps["bulletStyle"]>> = [
                "decimal",
                "lower-alpha",
                "upper-alpha",
                "lower-roman",
                "upper-roman",
              ];
              const ordered = orderedStyles.includes(value);

              updateBlock(selectedBlockId, { bulletStyle: value, ordered } as any);
            }}
          >
            <option value="disc">기본 (●)</option>
            <option value="circle">원 (○)</option>
            <option value="square">사각 (■)</option>
            <option value="decimal">숫자 (1.)</option>
            <option value="lower-alpha">알파벳 소문자 (a.)</option>
            <option value="upper-alpha">알파벳 대문자 (A.)</option>
            <option value="lower-roman">로마 숫자 소문자 (i.)</option>
            <option value="upper-roman">로마 숫자 대문자 (I.)</option>
            <option value="none">없음</option>
          </select>
        </label>

        {/* 아이템 간 여백 (슬라이더) */}
        <NumericPropertyControl
          label="아이템 간 여백 (px)"
          unitLabel="(px)"
          value={(() => {
            if (typeof listProps.gapYPx === "number") {
              return listProps.gapYPx;
            }
            const token = listProps.gapY ?? "md";
            return token === "sm" ? 4 : token === "lg" ? 16 : 8;
          })()}
          min={0}
          max={40}
          step={2}
          presets={[
            { id: "tight", label: "좁게", value: 4 },
            { id: "normal", label: "보통", value: 8 },
            { id: "relaxed", label: "넓게", value: 16 },
          ]}
          onChangeValue={(v) => {
            updateBlock(selectedBlockId, { gapYPx: v } as any);
          }}
        />
      </div>
    </>
  );
}
