import { type Ref, ref, watch } from 'vue';
import type { ServiceRequestResult } from '@/service/api/shared';

export interface BoardColumnState {
  statusCode: string;
  title: string;
  sort: number;
  terminal: boolean;
  /** 服务端权威总数（每次接口回来都用最新 total 覆盖，与已加载多少条无关） */
  total: number;
  tasks: Api.Project.ProjectTask[];
  /** 已加载到第几页 */
  pageNo: number;
  loading: boolean;
  hasMore: boolean;
}

export type BoardBaseParams = Pick<
  Api.Project.ProjectTaskSearchParams,
  'keyword' | 'parentTaskId' | 'ownerId' | 'priority' | 'updateTime'
>;

const DEFAULT_PAGE_SIZE = 20;

/** 看板 fetcher 入参（每列的分页与 statusCode 由 composable 内部带入） */
export interface BoardFetcherParams {
  pageNo: number;
  pageSize: number;
  /** 首屏不传 → 后端返全部列；列加载更多传 [statusCode] → 仅返该列 */
  statusCode?: string[];
}

export interface UseTaskBoardColumnsOptions {
  /** 是否具备加载条件（projectId / executionId 等校验由调用方做完）；false 时清空列表 */
  canLoad: Ref<boolean>;
  /**
   * 刷新触发器：workspace 的 statusBoard ref。
   *
   * 这里只把它当"事件源"用：搜索/重置/创建/编辑/删除/状态推进后 workspace 都会重新拉它 → ref 引用变 →
   * 触发本 composable 重新拉看板首屏。**composable 不读它的内容**，列结构以 board-page 响应为准。
   */
  refreshSignal: Ref<unknown>;
  /**
   * 调用方提供的 fetcher，屏蔽"单执行 / 跨执行"两套接口的差异：
   * - 单执行视角 → 调 fetchGetProjectTaskBoardPage(projectId, executionId, { ...baseParams, ...params })
   * - 跨执行视角 → 调 fetchGetProjectTaskBoardPageCross(projectId, { ...baseParamsCross, ...params })
   */
  fetcher: (params: BoardFetcherParams) => Promise<
    ServiceRequestResult<{
      items: Array<{
        statusCode: string;
        statusName: string;
        sort: number;
        terminal?: boolean;
        list: Api.Project.ProjectTask[];
        total: number;
      }>;
    }>
  >;
  pageSize?: number;
}

/**
 * 看板按状态分列、每列独立分页（无限下拉）。
 *
 * 节奏：
 * - 进入看板 / 任何刷新事件：1 次 fetcher（不带 statusCode）→ 拿到所有列骨架 + 各列首页 + 各列总数。
 * - 用户滚某列到底：1 次 fetcher（`statusCode=[X]`, `pageNo=N+1`）→ 取 `items[0].list` 追加到本列。
 */
export function useTaskBoardColumns(options: UseTaskBoardColumnsOptions) {
  const pageSize = options.pageSize ?? DEFAULT_PAGE_SIZE;
  const columns = ref<BoardColumnState[]>([]);

  async function refresh() {
    if (!options.canLoad.value) {
      columns.value = [];
      return;
    }

    const result = await options.fetcher({ pageNo: 1, pageSize });

    if (result.error || !result.data) {
      columns.value = [];
      return;
    }

    // 后端按 sort 升序返回，前端不再排
    columns.value = result.data.items.map(item => ({
      statusCode: item.statusCode,
      title: item.statusName,
      sort: item.sort,
      terminal: Boolean(item.terminal),
      total: item.total,
      tasks: item.list,
      pageNo: 1,
      loading: false,
      hasMore: item.list.length < item.total
    }));
  }

  async function loadMore(statusCode: string) {
    if (!options.canLoad.value) return;

    const col = columns.value.find(item => item.statusCode === statusCode);
    if (!col || col.loading || !col.hasMore) return;

    col.loading = true;
    const nextPage = col.pageNo + 1;
    const result = await options.fetcher({
      pageNo: nextPage,
      pageSize,
      statusCode: [statusCode]
    });

    if (result.error || !result.data) {
      col.loading = false;
      return;
    }

    const colData = result.data.items[0];
    if (!colData) {
      // 后端没回该列（理论上不该发生）—— 兜底标记加载完毕，避免死循环
      col.loading = false;
      col.hasMore = false;
      return;
    }

    col.tasks = [...col.tasks, ...colData.list];
    col.pageNo = nextPage;
    col.total = colData.total;
    col.hasMore = col.tasks.length < colData.total;
    col.loading = false;
  }

  watch(
    () => options.refreshSignal.value,
    () => refresh(),
    { immediate: true }
  );

  return { columns, loadMore, refresh };
}
