// ============================================================
// layout.ts — 画布布局算法
//
// 实现 Grid 模式和 Single 模式的坐标计算。
// ============================================================

import type { CatalogItem } from '../stores/useCanvasStore';
import {
    ITEM_W,
    ITEM_H,
    ITEM_SPACING,
    ROW_LABEL_WIDTH,
    MAX_ITEMS_PER_PAGE,
} from './constants';

// ---------- 通用类型 ----------

export interface Position {
    x: number;
    y: number;
}

export interface PageInfo {
    /** 总页数 */
    totalPages: number;
    /** 当前页的 item 索引范围 [start, end) */
    startIndex: number;
    endIndex: number;
}

// ---------- Grid 模式 ----------

/**
 * Grid 模式：计算 item 的绝对像素坐标。
 *
 * @param index   item 在当前页 items 数组中的局部索引（0-based）
 * @param cols    每行列数
 */
export function gridPosition(index: number, cols: number): Position {
    const row = Math.floor(index / cols);
    const col = index % cols;
    return {
        x: col * (ITEM_W + ITEM_SPACING),
        y: row * (ITEM_H + ITEM_SPACING),
    };
}

/**
 * Grid 模式：计算分页信息。
 *
 * @param totalItems    全量过滤后的 item 总数
 * @param cols          每行列数
 * @param rowsPerPage   每页行数
 * @param currentPage   当前页码（1-based）
 */
export function gridPageInfo(
    totalItems: number,
    cols: number,
    rowsPerPage: number,
    currentPage: number,
): PageInfo {
    const perPage = Math.min(cols * rowsPerPage, MAX_ITEMS_PER_PAGE);
    const totalPages = Math.max(1, Math.ceil(totalItems / perPage));
    const page = Math.max(1, Math.min(currentPage, totalPages));
    const startIndex = (page - 1) * perPage;
    const endIndex = Math.min(startIndex + perPage, totalItems);
    return { totalPages, startIndex, endIndex };
}

/**
 * Grid 模式：计算画布总尺寸（像素）。
 */
export function gridCanvasSize(
    itemsOnPage: number,
    cols: number,
): { width: number; height: number } {
    const rows = Math.ceil(itemsOnPage / cols);
    const width = cols * (ITEM_W + ITEM_SPACING) - ITEM_SPACING;
    const height = rows * (ITEM_H + ITEM_SPACING) - ITEM_SPACING;
    return { width, height };
}

// ---------- Single 模式 ----------

/**
 * Single 模式：按 groupKey 分组，每组一行横向排列。
 * 返回每个 item 的位置和画布尺寸。
 *
 * @param itemsOnPage  当前页的 item 列表
 */
export function singleLayout(
    itemsOnPage: CatalogItem[],
): { positions: Map<number, Position>; canvasWidth: number; canvasHeight: number } {
    // 按 groupKey 分组（保持插入顺序）
    const groups = new Map<string, CatalogItem[]>();
    for (const item of itemsOnPage) {
        const key = item.groupKey || 'unknown';
        if (!groups.has(key)) groups.set(key, []);
        groups.get(key)!.push(item);
    }

    const positions = new Map<number, Position>();
    let maxWidth = 0;
    let row = 0;

    for (const [, groupItems] of groups) {
        let col = 0;
        for (const item of groupItems) {
            positions.set(item.id, {
                x: ROW_LABEL_WIDTH + ITEM_SPACING + col * (ITEM_W + ITEM_SPACING),
                y: row * (ITEM_H + ITEM_SPACING),
            });
            col++;
        }
        const rowWidth =
            ROW_LABEL_WIDTH + ITEM_SPACING + col * (ITEM_W + ITEM_SPACING);
        if (rowWidth > maxWidth) maxWidth = rowWidth;
        row++;
    }

    const canvasHeight = row * (ITEM_H + ITEM_SPACING) - ITEM_SPACING;
    return { positions, canvasWidth: maxWidth, canvasHeight };
}

/**
 * Single 模式：计算分页信息。
 * 每页最多 singleRowsPerPage 个镜头组。
 */
export function singlePageInfo(
    items: CatalogItem[],
    singleRowsPerPage: number,
    currentPage: number,
): PageInfo {
    // 收集所有 groupKey（保持顺序、去重）
    const groupKeys: string[] = [];
    const seen = new Set<string>();
    for (const item of items) {
        const key = item.groupKey || 'unknown';
        if (!seen.has(key)) {
            seen.add(key);
            groupKeys.push(key);
        }
    }

    const totalPages = Math.max(1, Math.ceil(groupKeys.length / singleRowsPerPage));
    const page = Math.max(1, Math.min(currentPage, totalPages));
    const startGroupIdx = (page - 1) * singleRowsPerPage;
    const endGroupIdx = Math.min(startGroupIdx + singleRowsPerPage, groupKeys.length);

    // 将 group key 范围转换为 item 索引范围
    let startIndex = 0;
    let endIndex = items.length;
    let groupIdx = 0;
    let currentGroup = '';

    for (let i = 0; i < items.length; i++) {
        const key = items[i].groupKey || 'unknown';
        if (key !== currentGroup) {
            if (groupIdx === startGroupIdx) startIndex = i;
            if (groupIdx === endGroupIdx) {
                endIndex = i;
                break;
            }
            currentGroup = key;
            groupIdx++;
        }
    }

    return { totalPages, startIndex, endIndex };
}
