import { Page } from "@playwright/test";
import { test, expect } from "../../src/fixture/base-test";
import {
  DongCauTruc,
  PREFIX_BAN_SAO,
  layTenCacDongCauTrucMoiTrang,
  luuModalThuMuc,
  moRongToanBoCayCauTruc,
  nhanBanThuMuc,
  openBoHoSo,
  openTabCauTrucHoSo,
  phanTichDongCauTruc,
} from "../../src/screen-instructions/KHO-TAI-LIEU.functions";

/**
 * Chỉ 2 bước **thật sự dùng chung cho nhiều case** của mục 1.4.9 (nhân bản thư mục + assert quan hệ
 * cha–con). Phần dựng dữ liệu tiền điều kiện **viết thẳng trong từng spec** — mỗi case dựng một cây
 * khác nhau nên tách ra file setup chỉ thêm một tầng gián tiếp mà không dùng lại được.
 *
 * Tiền điều kiện chung của mục: xem [`1.4.9.md`](./1.4.9.md).
 */

/**
 * **Thao tác**: mở BHS → tab "Cấu trúc hồ sơ" → menu dòng của `tenThuMuc` → "Nhân bản" → chờ toast
 * `"Nhân bản hoàn thành"` → app mở màn cập nhật của bản sao → **assert tên bản sao** =
 * `"Copy of " + <tên gốc>` → bấm "Xác nhận" để lưu.
 *
 * Trả về **tên bản sao đã lưu** để bước kiểm tra sau tra đúng dòng đó trong bảng.
 *
 * Vì sao assert tên **trước khi** xác nhận: đó là giá trị app tự sinh; bấm Xác nhận rồi mới đọc lại
 * từ bảng thì không phân biệt được "app đặt sai tên" với "người dùng sửa tên" — mà bước xác nhận
 * cũng chính là chỗ người dùng có thể sửa.
 *
 * 🚨 Sau bước này `page.url()` đã bị đổi sang `itemId` của bản sao (`nhanBanThuMuc`) → mọi bước sau
 * phải mở lại BHS bằng `recordUrl`.
 */
export const nhanBanThuMucVaXacNhan = async (
  page: Page,
  recordUrl: string,
  tenThuMuc: string,
): Promise<string> => {
  const tenMongDoi = `${PREFIX_BAN_SAO}${tenThuMuc}`;

  return test.step(`Thao tác: nhân bản thư mục "${tenThuMuc}"`, async () => {
    await openBoHoSo(page, recordUrl);
    await openTabCauTrucHoSo(page);

    const tenBanSao = await nhanBanThuMuc(page, tenThuMuc);

    expect(tenBanSao, {
      message:
        `Lỗi: tên thư mục được nhân bản không đúng quy tắc "${PREFIX_BAN_SAO}<tên gốc>".\n` +
        `  mong đợi: "${tenMongDoi}"\n  thực tế:  "${tenBanSao}"`,
    }).toBe(tenMongDoi);

    // Xác nhận màn cập nhật của bản sao (footer modal thư mục — MODAL-TAO-THU-MUC.md mục 5)
    await luuModalThuMuc(page, undefined, `Xác nhận bản sao ${tenBanSao}`);

    return tenBanSao;
  });
};

/**
 * **Mong muốn**: mở lại BHS → bảng "Cấu trúc hồ sơ" có dòng `tenCha`, và **bên trong nó** có item
 * con tên đúng `tenConMongDoi` (con là **thư mục hay tài liệu đều dùng chung hàm này** — bảng hiển
 * thị 2 loại như nhau, chỉ khác mã prefix).
 *
 * Cách xác định "bên trong": bảng Cấu trúc hồ sơ là **cây phẳng**, quan hệ cha–con chỉ đọc được qua
 * **mã prefix** hệ thống sinh (`KHO-TAI-LIEU.md` mục 4.4) — con của item mã `B` là các dòng có mã
 * bắt đầu bằng `"B."`. Vì vậy hàm tách mã bằng `phanTichDongCauTruc` thay vì lọc dòng theo
 * `hasText`: tên bản sao (`"Copy of X-TM1"`) **chứa nguyên tên gốc** (`"X-TM1"`) nên mọi cách khớp
 * theo chuỗi con đều dính nhầm dòng (xem `1.4.9.md` mục 1, ràng buộc 4).
 *
 * Bắt buộc `moRongToanBoCayCauTruc` trước khi đọc: cây chỉ mở sẵn tới cấp 1, item sâu hơn không có
 * trong DOM (đo trên DOM thật 2026-08-14 — `KHO-TAI-LIEU.md` mục 4.4).
 *
 * Đọc lại từ **BHS mở lại** chứ không dùng bảng ngay sau thao tác: tín hiệu đáng tin là dữ liệu đã
 * ghi xuống server, không phải bảng app vừa vẽ lại tại chỗ.
 */
export const expectItemChuaItemCon = async (
  page: Page,
  recordUrl: string,
  tenCha: string,
  tenConMongDoi: string,
) => {
  await test.step(`Mong muốn: "${tenCha}" chứa item con "${tenConMongDoi}"`, async () => {
    const dong = await layDongCauTrucCuaBoHoSo(page, recordUrl);
    const moTaBang = (ds: DongCauTruc[]) =>
      ds.map((d) => `"${d.hienThi}"`).join(" | ") || "không có dòng nào";

    const cha = dong.find((d) => d.ten === tenCha);
    expect(cha, {
      message:
        `Lỗi: không thấy "${tenCha}" trong bảng Cấu trúc hồ sơ. ` +
        `Các dòng đang có (${dong.length}): [${moTaBang(dong)}]`,
    }).toBeTruthy();

    expect(cha!.ma, {
      message:
        `Lỗi: không đọc được mã prefix của "${tenCha}" (dòng "${cha!.hienThi}") → ` +
        "không xác định được item nào nằm bên trong nó",
    }).not.toBe("");

    const con = dong.filter((d) => d.ma.startsWith(`${cha!.ma}.`));
    expect(
      con.some((d) => d.ten === tenConMongDoi),
      {
        message:
          `Lỗi: bên trong "${tenCha}" (mã "${cha!.ma}") không có item con tên ` +
          `"${tenConMongDoi}". Các item đang nằm bên trong: [${moTaBang(con)}]. ` +
          `Toàn bộ bảng (${dong.length} dòng): [${moTaBang(dong)}]`,
      },
    ).toBe(true);
  });
};

/**
 * Mở lại BHS → tab "Cấu trúc hồ sơ" → mở hết cây → đọc **mọi dòng (gộp cả các trang)**, đã tách
 * `{ ma, ten }`. Dùng chung cho các assert của mục về vị trí / tên item sau khi nhân bản.
 */
export const layDongCauTrucCuaBoHoSo = async (
  page: Page,
  recordUrl: string,
): Promise<DongCauTruc[]> => {
  await openBoHoSo(page, recordUrl);
  await openTabCauTrucHoSo(page);
  await moRongToanBoCayCauTruc(page);
  return phanTichDongCauTruc(await layTenCacDongCauTrucMoiTrang(page));
};
