import type {
  PageSection,
  SectionBreakpointKey,
  SectionBreakpointSettings,
  SectionSpacing,
  SectionStyleSettings,
  SectionWidth,
} from "@/admin/types";

export type EditorPreviewBreakpoint = SectionBreakpointKey;

export type SpacingSide = keyof SectionSpacing;

const BP_KEYS: SectionBreakpointKey[] = ["desktop", "tablet", "mobile"];

export const EMPTY_SPACING: SectionSpacing = { top: "", right: "", bottom: "", left: "" };

export const EMPTY_BREAKPOINT: SectionBreakpointSettings = {
  padding: { ...EMPTY_SPACING },
  margin: { ...EMPTY_SPACING },
  maxWidth: "",
  containerPaddingX: "",
  textAlign: "",
  fontSize: "",
  width: undefined,
};

export const DEFAULT_SECTION_STYLE: SectionStyleSettings = {
  backgroundColor: "",
  backgroundImage: "",
  backgroundSize: "cover",
  backgroundPosition: "center",
  borderRadius: "",
  borderColor: "",
  borderWidth: "",
  boxShadow: "",
  breakpoints: {
    desktop: { ...EMPTY_BREAKPOINT, padding: { ...EMPTY_SPACING }, margin: { ...EMPTY_SPACING } },
    tablet: { ...EMPTY_BREAKPOINT, padding: { ...EMPTY_SPACING }, margin: { ...EMPTY_SPACING } },
    mobile: { ...EMPTY_BREAKPOINT, padding: { ...EMPTY_SPACING }, margin: { ...EMPTY_SPACING } },
  },
};

function str(v: unknown): string {
  return typeof v === "string" ? v : "";
}

function spacing(raw: unknown): SectionSpacing {
  if (!raw || typeof raw !== "object") return { ...EMPTY_SPACING };
  const o = raw as Record<string, unknown>;
  return {
    top: str(o.top),
    right: str(o.right),
    bottom: str(o.bottom),
    left: str(o.left),
  };
}

function normalizeBreakpoint(raw: unknown): SectionBreakpointSettings {
  if (!raw || typeof raw !== "object") return { ...EMPTY_BREAKPOINT, padding: { ...EMPTY_SPACING }, margin: { ...EMPTY_SPACING } };
  const o = raw as Record<string, unknown>;
  const w = o.width;
  return {
    padding: spacing(o.padding),
    margin: spacing(o.margin),
    maxWidth: str(o.maxWidth),
    containerPaddingX: str(o.containerPaddingX),
    textAlign: str(o.textAlign),
    fontSize: str(o.fontSize),
    width: w === "full" || w === "container" ? w : undefined,
  };
}

/** Migrate legacy flat + responsivePadding fields into breakpoints. */
function buildBreakpoints(o: Record<string, unknown>): SectionStyleSettings["breakpoints"] {
  const raw = o.breakpoints;
  if (raw && typeof raw === "object") {
    const b = raw as Record<string, unknown>;
    return {
      desktop: normalizeBreakpoint(b.desktop),
      tablet: normalizeBreakpoint(b.tablet),
      mobile: normalizeBreakpoint(b.mobile),
    };
  }

  const legacyPad = spacing(o.padding);
  const legacyMar = spacing(o.margin);
  const respPad = o.responsivePadding as Record<string, unknown> | undefined;
  const respMar = o.responsiveMargin as Record<string, unknown> | undefined;

  return {
    desktop: {
      padding: legacyPad,
      margin: legacyMar,
      maxWidth: str(o.maxWidth),
      containerPaddingX: str(o.containerPaddingX),
      textAlign: "",
      fontSize: "",
      width: undefined,
    },
    tablet: {
      ...EMPTY_BREAKPOINT,
      padding: spacing(respPad?.tablet),
      margin: spacing(respMar?.tablet),
    },
    mobile: {
      ...EMPTY_BREAKPOINT,
      padding: spacing(respPad?.mobile),
      margin: spacing(respMar?.mobile),
    },
  };
}

export function normalizeSectionStyle(raw: unknown): SectionStyleSettings {
  if (!raw || typeof raw !== "object") {
    return JSON.parse(JSON.stringify(DEFAULT_SECTION_STYLE)) as SectionStyleSettings;
  }
  const o = raw as Record<string, unknown>;
  const d = DEFAULT_SECTION_STYLE;
  return {
    backgroundColor: str(o.backgroundColor),
    backgroundImage: str(o.backgroundImage),
    backgroundSize: str(o.backgroundSize) || "cover",
    backgroundPosition: str(o.backgroundPosition) || "center",
    borderRadius: str(o.borderRadius),
    borderColor: str(o.borderColor),
    borderWidth: str(o.borderWidth),
    boxShadow: str(o.boxShadow),
    breakpoints: buildBreakpoints(o),
  };
}

export function getBreakpointSettings(
  style: SectionStyleSettings,
  bp: SectionBreakpointKey
): SectionBreakpointSettings {
  return style.breakpoints?.[bp] ?? EMPTY_BREAKPOINT;
}

export function setBreakpointSettings(
  style: SectionStyleSettings,
  bp: SectionBreakpointKey,
  patch: Partial<SectionBreakpointSettings>
): SectionStyleSettings {
  const breakpoints = { ...style.breakpoints! };
  const current = getBreakpointSettings(style, bp);
  breakpoints[bp] = {
    ...current,
    ...patch,
    padding: patch.padding ? { ...current.padding, ...patch.padding } : current.padding,
    margin: patch.margin ? { ...current.margin, ...patch.margin } : current.margin,
  };
  return { ...style, breakpoints: { ...breakpoints } };
}

export function ensureSectionMeta(section: PageSection, index: number): PageSection {
  return {
    ...section,
    id: section.id ?? `section-${index}`,
    style: normalizeSectionStyle(section.style),
  };
}

function padVar(side: SpacingSide, prefix: string): string {
  const map: Record<SpacingSide, string> = {
    top: `${prefix}-t`,
    right: `${prefix}-r`,
    bottom: `${prefix}-b`,
    left: `${prefix}-l`,
  };
  return map[side];
}

function applySpacingVars(
  vars: Record<string, string>,
  spacing: SectionSpacing,
  prefix: "--sec-pad" | "--sec-mar",
  suffix: "d" | "t" | "m",
  allowEmpty: boolean
) {
  (["top", "right", "bottom", "left"] as SpacingSide[]).forEach((side) => {
    const val = (spacing[side] ?? "").trim();
    if (!val && !allowEmpty) return;
    vars[`${padVar(side, prefix)}-${suffix}`] = val || "0";
  });
}

function applyBreakpointVars(
  vars: Record<string, string>,
  bp: SectionBreakpointSettings,
  suffix: "d" | "t" | "m"
) {
  const allowEmpty = suffix === "d";
  applySpacingVars(vars, bp.padding ?? {}, "--sec-pad", suffix, allowEmpty);
  applySpacingVars(vars, bp.margin ?? {}, "--sec-mar", suffix, allowEmpty);

  const maxW = (bp.maxWidth ?? "").trim();
  if (maxW) vars[`--sec-max-width-${suffix}`] = maxW;

  const cpx = (bp.containerPaddingX ?? "").trim();
  if (cpx) vars[`--sec-container-px-${suffix}`] = cpx;

  const align = (bp.textAlign ?? "").trim();
  if (align) vars[`--sec-text-align-${suffix}`] = align;

  const fontSize = (bp.fontSize ?? "").trim();
  if (fontSize) vars[`--sec-font-size-${suffix}`] = fontSize;

  if (bp.width) vars[`--sec-layout-${suffix}`] = bp.width;
}

/** CSS custom properties for section-page.css responsive rules. */
export function sectionStyleToCssVars(style: SectionStyleSettings): Record<string, string> {
  const vars: Record<string, string> = {};
  const bps = style.breakpoints ?? DEFAULT_SECTION_STYLE.breakpoints!;

  if (style.backgroundColor) vars["--sec-bg"] = style.backgroundColor;
  if (style.backgroundImage) {
    const url = style.backgroundImage.trim();
    vars["--sec-bg-image"] = url.startsWith("url(") ? url : `url("${url.replace(/"/g, "")}")`;
  }
  vars["--sec-bg-size"] = style.backgroundSize || "cover";
  vars["--sec-bg-position"] = style.backgroundPosition || "center";

  applyBreakpointVars(vars, bps.desktop, "d");
  applyBreakpointVars(vars, bps.tablet, "t");
  applyBreakpointVars(vars, bps.mobile, "m");

  if (style.borderRadius) vars["--sec-radius"] = style.borderRadius;
  if (style.borderColor) vars["--sec-border-color"] = style.borderColor;
  if (style.borderWidth) vars["--sec-border-width"] = style.borderWidth;
  if (style.boxShadow) vars["--sec-shadow"] = style.boxShadow;

  return vars;
}

/** Layout classes for full vs container per breakpoint (desktop / tablet / mobile). */
export function getSectionLayoutClasses(
  sectionWidth: SectionWidth,
  style: SectionStyleSettings
): string {
  const bps = style.breakpoints ?? DEFAULT_SECTION_STYLE.breakpoints!;
  const resolve = (bp: SectionBreakpointKey, fallback: SectionWidth) => bps[bp]?.width ?? fallback;
  const d = resolve("desktop", sectionWidth);
  const t = resolve("tablet", d);
  const m = resolve("mobile", t);
  return [
    `page-sec-layout-d-${d}`,
    `page-sec-layout-t-${t}`,
    `page-sec-layout-m-${m}`,
  ].join(" ");
}

export function getSectionWidthClass(width: SectionWidth): string {
  return width === "container" ? "page-sec-outer--container" : "page-sec-outer--full";
}

export function getEditorPreviewClass(bp?: EditorPreviewBreakpoint): string {
  if (!bp || bp === "desktop") return "";
  return `page-sec-preview--${bp}`;
}

/** Effective section width for a breakpoint (editor preview / logic). */
export function resolveSectionWidth(
  sectionWidth: SectionWidth,
  style: SectionStyleSettings,
  bp: SectionBreakpointKey = "desktop"
): SectionWidth {
  const bps = style.breakpoints;
  if (!bps) return sectionWidth;
  if (bp === "mobile") return bps.mobile?.width ?? bps.tablet?.width ?? bps.desktop?.width ?? sectionWidth;
  if (bp === "tablet") return bps.tablet?.width ?? bps.desktop?.width ?? sectionWidth;
  return bps.desktop?.width ?? sectionWidth;
}

export { BP_KEYS };
