import { Page } from "@playwright/test";
import { test, expect, ACCOUNT } from "../../src/fixture/base-test";
import { PW } from "../../src/utils/PW";
import {
  PREFIX_BAN_SAO,
  createBoHoSo,
  createTaiLieu,
  createThuMuc,
  nhanBanTaiLieu,
  openBoHoSo,
  openTabCauTrucHoSo,
} from "../../src/screen-instructions/KHO-TAI-LIEU.functions";
import {
  expectItemChuaItemCon,
  layDongCauTrucCuaBoHoSo,
  nhanBanThuMucVaXacNhan,
} from "./1.4.9.steps";

/**
 * UC?? — 1.4.9.720
 * **Kiểm tra Nhân bản Thư mục thành công** (thư mục có **tài liệu** bên trong + nhân bản tài liệu)
 *
 * Thao tác (nguyên văn):
 * 1. Tạo 1 bộ hồ sơ mới.
 * 2. Tạo thư mục 1, bên trong có tài liệu 1. Tạo thêm 1 tài liệu 2.
 * 3. Nhân bản thư mục 1, bên trong thư mục copy cũng có tài liệu 1. Copy tài liệu 2, tên cũng sẽ có
 *    cấu trúc tên "Copy of " + tên gốc.
 *
 * **Tiền điều kiện chung của mục** (tiền điều kiện QA + bảng vai → cách dựng dữ liệu):
 * [`1.4.9.md`](./1.4.9.md). File đó **chỉ** chứa tiền điều kiện chung; toàn bộ logic / kỳ vọng /
 * giả định của case này nằm trong khối comment dưới đây.
 *
 * ---
 *
 * ## Cách case này được viết
 *
 * - **Hai điểm mơ hồ trong mô tả đã chốt với người dùng (2026-08-14)**:
 *   1. **Tài liệu 2 nằm ở gốc BHS**, ngang cấp thư mục 1 (không nằm trong thư mục 1) → thao tác 3
 *      gồm **2 phần độc lập**: nhân bản *thư mục 1*, rồi nhân bản *tài liệu 2*.
 *   2. **Tài liệu 1 bên trong thư mục bản sao giữ nguyên tên gốc** — tiền tố `"Copy of "` chỉ áp
 *      dụng cho **item được nhân bản trực tiếp** (thư mục 1 ở phần đầu, tài liệu 2 ở phần sau),
 *      không lan xuống item con. Giống case [`710`](./1.4.9.710.spec.ts) với thư mục con.
 * - **Dựng dữ liệu thẳng trong case** (không tách file setup): mỗi case của mục dựng một cây khác
 *   nhau nên tách ra chỉ thêm tầng gián tiếp. Tài liệu tạo bằng `createTaiLieu` nên **không có file
 *   mềm đính kèm** — case này kiểm hành vi nhân bản, không kiểm file.
 * - **Giữ nguyên trạng thái "Khai báo"**: vai thao tác chính là người tạo BHS nên vẫn mở lại được
 *   (`PHAN-QUYEN-THEO-VAI.md` mục 1); QA không nêu bước chuyển hoạt động.
 * - **Phần A — nhân bản thư mục 1** (dùng lại nguyên bộ bước của case 710):
 *   toast `"Nhân bản hoàn thành"` → màn cập nhật bản sao có tên `"Copy of " + <tên gốc>` → Xác nhận
 *   → mở lại BHS và kiểm **bên trong bản sao có tài liệu 1, tên giữ nguyên**.
 *   Thêm assert **bản gốc vẫn còn tài liệu 1** — bắt lỗi app *chuyển* thay vì *sao chép* item con,
 *   lỗi này chỉ nhìn bản sao thì không thấy.
 * - **Phần B — nhân bản tài liệu 2**: kỳ vọng duy nhất QA nêu là **tên bản sao** =
 *   `"Copy of " + <tên gốc>`. Assert bằng cách **đọc bảng Cấu trúc hồ sơ sau khi mở lại BHS** chứ
 *   không đọc từ form: khác thư mục, QA **không** mô tả app có mở màn cập nhật cho tài liệu bản sao
 *   hay không → `nhanBanTaiLieu` xử lý mềm (có modal thì lưu lại, không có thì thôi) và case chốt
 *   kết quả ở bảng — chỗ chắc chắn phản ánh dữ liệu đã ghi.
 * - **Vị trí bản sao của tài liệu 2**: kỳ vọng tự nhiên là **cùng chỗ bản gốc** (gốc BHS → mã prefix
 *   không có dấu chấm). QA không nêu nên assert bằng **`expect.soft`**: lệch thì báo cảnh báo,
 *   không đánh trượt case vì một điều QA chưa chốt.
 * - **Xác định "bên trong"** bằng **mã prefix**, không bằng tên: tên bản sao chứa nguyên tên gốc nên
 *   mọi cách lọc dòng theo chuỗi con đều dính nhầm (`expectItemChuaItemCon`).
 * - **Không kiểm tra** thuộc tính khác của tài liệu bản sao (mã tài liệu mới, số hiệu, loại tài
 *   liệu, phân quyền, file đính kèm) — QA không nêu; đó là **case riêng**, chưa viết.
 * - **2 test (Thủ thư + Admin)** theo quy ước `tests/README.md` mục 6.4; mỗi vai tự dựng BHS riêng.
 *
 * ## Điểm cần QA/DEV chốt
 *
 * 1. 🚨 **Chức năng "Nhân bản" chưa được khảo sát bằng MCP** (yêu cầu "không dùng MCP khảo sát màn
 *    hình", 2026-08-14). Đã khảo sát thật: mục `mni-nhan-ban` trong menu hành động của **dòng thư
 *    mục** và **dòng tài liệu** (`KHO-TAI-LIEU.md` mục 4.4). Chưa khảo sát: nội dung toast, việc app
 *    mở màn cập nhật cho bản sao, tiền tố `"Copy of "`. Chạy thật hỏng ở bước nào → khảo sát lại
 *    bằng `/khao-sat-man-hinh`, đừng vá thêm selector đoán.
 * 2. **Nhân bản TÀI LIỆU: app có mở màn cập nhật như với thư mục không?** Chưa có mô tả.
 *    `nhanBanTaiLieu` đang xử lý mềm: **thấy** modal chi tiết TL (`tab-digitizedATM`) thì đọc tên +
 *    bấm `btn-save` (lưu chứ không đóng — nếu bản sao là bản nháp chờ xác nhận thì đóng modal sẽ
 *    **mất** nó); **không thấy** thì bỏ qua. Chốt được hành vi thật thì bỏ nhánh còn lại đi.
 * 3. **Tài liệu 1 trong bản sao có thật sự giữ nguyên tên không** — hiện theo xác nhận của người
 *    dùng. Nếu app thêm `"Copy of "` cho cả item con thì case này fail ở phần A, và **cả case 710
 *    cũng phải sửa** theo (chỗ đó cũng đang assert "giữ nguyên tên").
 * 4. **Chưa rõ tiền tố `"Copy of "` có phụ thuộc ngôn ngữ giao diện hay không** — đang hard-code
 *    trong hằng `PREFIX_BAN_SAO`, đổi thì sửa đúng 1 chỗ.
 * 5. **Không kiểm tra file mềm** có được nhân bản theo tài liệu hay không (tài liệu tiền điều kiện
 *    không có file). Cần kiểm thì upload file ở tab "Tài liệu số" trước khi nhân bản — **case riêng**.
 */

const runTest = async (page: Page) => {
  const pw = new PW(page);
  const base = `AT-1.4.9-720-${Date.now()}`;
  // ⚠️ Không tên nào được là tiền tố của tên khác (`getCauTrucRow` khớp chuỗi con) — xem `1.4.9.md`
  const tenThuMuc1 = `${base}-TM1`;
  const tenTaiLieu1 = `${base}-TL1`;
  const tenTaiLieu2 = `${base}-TL2`;

  // --- Thao tác 1: tạo 1 bộ hồ sơ mới ---
  const recordUrl = await createBoHoSo(page, pw, base);

  // --- Thao tác 2: thư mục 1 (bên trong có tài liệu 1) + tài liệu 2 ở gốc BHS ---
  await createThuMuc(page, pw, recordUrl, tenThuMuc1);
  await createTaiLieu(page, pw, recordUrl, tenTaiLieu1, {
    folderName: tenThuMuc1,
  });
  await createTaiLieu(page, pw, recordUrl, tenTaiLieu2);

  // --- Thao tác 3A: nhân bản thư mục 1 → toast + màn cập nhật + tên "Copy of ..." + Xác nhận ---
  const tenThuMucBanSao = await nhanBanThuMucVaXacNhan(
    page,
    recordUrl,
    tenThuMuc1,
  );

  // Mong muốn: bên trong thư mục bản sao cũng có tài liệu 1, tên giữ nguyên
  await expectItemChuaItemCon(page, recordUrl, tenThuMucBanSao, tenTaiLieu1);

  // Mong muốn (bổ sung): bản gốc vẫn còn tài liệu 1 — nhân bản là SAO CHÉP, không phải CHUYỂN
  await expectItemChuaItemCon(page, recordUrl, tenThuMuc1, tenTaiLieu1);

  // --- Thao tác 3B: nhân bản tài liệu 2 → tên bản sao = "Copy of " + tên gốc ---
  const tenTaiLieuBanSao = `${PREFIX_BAN_SAO}${tenTaiLieu2}`;

  await test.step(`Thao tác: nhân bản tài liệu "${tenTaiLieu2}"`, async () => {
    await openBoHoSo(page, recordUrl);
    await openTabCauTrucHoSo(page);
    await nhanBanTaiLieu(page, tenTaiLieu2);
  });

  await test.step(`Mong muốn: BHS có tài liệu "${tenTaiLieuBanSao}"`, async () => {
    const dong = await layDongCauTrucCuaBoHoSo(page, recordUrl);
    const moTaBang = dong.map((d) => `"${d.hienThi}"`).join(" | ");

    const banSao = dong.find((d) => d.ten === tenTaiLieuBanSao);
    expect(banSao, {
      message:
        `Lỗi: nhân bản tài liệu "${tenTaiLieu2}" xong nhưng bảng Cấu trúc hồ sơ không có dòng nào ` +
        `tên "${tenTaiLieuBanSao}" (quy tắc "${PREFIX_BAN_SAO}<tên gốc>"). ` +
        `Các dòng đang có (${dong.length}): [${moTaBang}]`,
    }).toBeTruthy();

    // Bản gốc phải còn nguyên — nhân bản là sao chép, không phải đổi tên bản gốc
    expect(
      dong.some((d) => d.ten === tenTaiLieu2),
      {
        message:
          `Lỗi: sau khi nhân bản, tài liệu gốc "${tenTaiLieu2}" không còn trong bảng ` +
          `(app đổi tên bản gốc thay vì tạo bản sao?). Các dòng đang có: [${moTaBang}]`,
      },
    ).toBe(true);

    // QA chưa nêu vị trí của bản sao → chỉ cảnh báo: mã không có dấu chấm = nằm ở gốc BHS
    expect
      .soft(banSao!.ma.includes("."), {
        message:
          `Cảnh báo: bản sao "${tenTaiLieuBanSao}" có mã "${banSao!.ma}" → không nằm ở gốc BHS ` +
          `như bản gốc "${tenTaiLieu2}". Các dòng đang có: [${moTaBang}]`,
      })
      .toBe(false);
  });
};

test(
  "UC?? 1.4.9.720 - Nhân bản Thư mục có tài liệu + nhân bản Tài liệu - Thủ thư" +
    ACCOUNT.LIBRARIAN,
  async ({ librarian }) => {
    await runTest(librarian);
  },
);

test(
  "UC?? 1.4.9.720 - Nhân bản Thư mục có tài liệu + nhân bản Tài liệu - Admin" +
    ACCOUNT.ADMIN,
  async ({ admin }) => {
    await runTest(admin);
  },
);
