import { withPageBlockInstanceId } from "@/lib/pageBlockInstance";
import { ensureSectionMeta } from "@/lib/sectionStyle";
import type { PageBlock, PageSection, SectionLayout } from "../types";

export type LayoutOption = {
  id: SectionLayout;
  label: string;
  columns: number[];
};

export const SECTION_LAYOUTS: LayoutOption[] = [
  { id: "100", label: "Full width", columns: [100] },
  { id: "50-50", label: "50% / 50%", columns: [50, 50] },
  { id: "33-33-33", label: "33% / 33% / 33%", columns: [33.33, 33.33, 33.34] },
  { id: "25-25-25-25", label: "25% / 25% / 25% / 25%", columns: [25, 25, 25, 25] },
  { id: "66-33", label: "66% / 33%", columns: [66.67, 33.33] },
  { id: "33-66", label: "33% / 66%", columns: [33.33, 66.67] },
  { id: "25-75", label: "25% / 75%", columns: [25, 75] },
  { id: "75-25", label: "75% / 25%", columns: [75, 25] },
  { id: "25-25-50", label: "25% / 25% / 50%", columns: [25, 25, 50] },
  { id: "50-25-25", label: "50% / 25% / 25%", columns: [50, 25, 25] },
  { id: "25-50-25", label: "25% / 50% / 25%", columns: [25, 50, 25] },
];

export function isSection(x: unknown): x is PageSection {
  return (
    typeof x === "object" &&
    x !== null &&
    "width" in x &&
    "layout" in x &&
    "blocks" in x &&
    Array.isArray((x as PageSection).blocks)
  );
}

export function isPageBlock(block: unknown): block is PageBlock {
  return (
    typeof block === "object" &&
    block !== null &&
    typeof (block as PageBlock).componentId === "number" &&
    typeof (block as PageBlock).componentName === "string"
  );
}

function ensureBlockInstanceIds(blocks: unknown[]): PageBlock[] {
  return blocks.map((block) => {
    if (!isPageBlock(block)) return block as PageBlock;
    return withPageBlockInstanceId(block);
  });
}

export function normalizeContent(content: unknown): PageSection[] {
  if (!Array.isArray(content) || content.length === 0) return [];
  if (isSection(content[0])) {
    return (content as PageSection[]).map((s, i) =>
      ensureSectionMeta({
        ...s,
        blocks: Array.isArray(s.blocks) ? ensureBlockInstanceIds(s.blocks) : [],
      }, i)
    );
  }
  return [
    ensureSectionMeta(
      { width: "full", layout: "100", blocks: ensureBlockInstanceIds(content as PageBlock[]) },
      0
    ),
  ];
}

/** Number of column slots for a layout (e.g. 25-25-25-25 => 4). */
export function getColumnCount(layout: SectionLayout): number {
  const opt = SECTION_LAYOUTS.find((l) => l.id === layout);
  return opt ? opt.columns.length : 1;
}

/** First empty column slot for a section layout, or null when every slot is filled. */
export function findFirstEmptySlotIndex(section: {
  layout: SectionLayout;
  blocks: (PageBlock | null | undefined)[];
}): number | null {
  const slotCount = getColumnCount(section.layout);
  for (let i = 0; i < slotCount; i++) {
    if (!isPageBlock(section.blocks[i])) return i;
  }
  return null;
}

/** Align stored blocks with layout slots (null = empty slot) for the page editor grid. */
export function sectionBlocksForEditor(section: PageSection): (PageBlock | null)[] {
  const slotCount = getColumnCount(section.layout);
  const raw = section.blocks ?? [];
  const blocks: (PageBlock | null)[] = [];
  for (let i = 0; i < slotCount; i++) {
    blocks[i] = isPageBlock(raw[i]) ? raw[i] : null;
  }
  return blocks;
}

/**
 * Blocks visible for a section layout (slot 0..n-1). Matches the page editor grid.
 * Prevents orphan blocks past the column count from rendering on preview/live pages.
 */
export function getRenderableSectionBlocks(section: PageSection): PageBlock[] {
  const slotCount = getColumnCount(section.layout);
  const raw = section.blocks ?? [];
  const result: PageBlock[] = [];
  for (let i = 0; i < slotCount; i++) {
    const block = raw[i];
    if (isPageBlock(block)) result.push(block);
  }
  return result;
}

/** Persist only blocks assigned to layout slots (drops hidden orphans on save). */
export function serializeSectionBlocks(section: PageSection): PageBlock[] {
  return getRenderableSectionBlocks(section);
}

export function layoutToGridColumns(layout: string): string {
  const map: Record<string, string> = {
    "100": "1fr",
    "50-50": "1fr 1fr",
    "33-33-33": "repeat(3, 1fr)",
    "25-25-25-25": "repeat(4, 1fr)",
    "66-33": "2fr 1fr",
    "33-66": "1fr 2fr",
    "25-75": "1fr 3fr",
    "75-25": "3fr 1fr",
    "25-25-50": "1fr 1fr 2fr",
    "50-25-25": "2fr 1fr 1fr",
    "25-50-25": "1fr 2fr 1fr",
  };
  return map[layout] ?? "1fr";
}
