import { expect, test } from "@playwright/test";

test.describe("Users Bulk Upload", () => {
  test.beforeEach(async ({ page }) => {
    await page.addInitScript(() => {
      window.localStorage.setItem("locale", "ko");
      window.localStorage.setItem("admin_session", "fake-token");
      (
        window as Window & typeof globalThis & { _IS_TEST_MODE?: boolean }
      )._IS_TEST_MODE = true;

      const authority = "http://localhost:5000/oidc";
      const client_id = "adminfront";
      const key = `oidc.user:${authority}:${client_id}`;
      const authData = {
        access_token: "fake-token",
        token_type: "Bearer",
        profile: { sub: "admin-user", name: "Admin", role: "super_admin" },
        expires_at: Math.floor(Date.now() / 1000) + 36000,
      };
      window.localStorage.setItem(key, JSON.stringify(authData));
    });

    await page.route("**/api/v1/**", async (route) => {
      const url = route.request().url();
      const headers = { "Access-Control-Allow-Origin": "*" };

      if (url.includes("/user/me")) {
        return route.fulfill({
          json: {
            id: "admin-user",
            name: "Admin",
            role: "super_admin",
            manageableTenants: [],
          },
          headers,
        });
      }
      if (url.includes("/admin/users")) {
        if (!url.includes("/bulk")) {
          return route.fulfill({
            json: { items: [], total: 0, limit: 50, offset: 0 },
            headers,
          });
        }
      }
      if (url.includes("/admin/tenants")) {
        return route.fulfill({
          json: { items: [], total: 0, limit: 100, offset: 0 },
          headers,
        });
      }
      return route.fulfill({ json: { items: [], total: 0 }, headers });
    });

    await page.route("**/oidc/**", async (route) => {
      await route.fulfill({ json: { issuer: "http://localhost:5000/oidc" } });
    });
  });

  test("should open bulk upload modal and show preview", async ({ page }) => {
    await page.goto("/users");
    // 헤더 타이틀이 뜰 때까지 대기
    await expect(page.getByTestId("page-title")).toContainText(
      /사용자|Users/i,
      { timeout: 20000 },
    );

    await page.getByTestId("user-data-mgmt-btn").click();
    await page
      .getByRole("menuitem", { name: /일괄 임포트|일괄 등록|Bulk Import/i })
      .click();

    await expect(page.getByTestId("bulk-upload-title")).toBeVisible({
      timeout: 10000,
    });
    const downloadBtn = page
      .locator("button")
      .filter({ hasText: /템플릿 다운로드|템플릿 받기|Download Template/ })
      .first();
    await expect(downloadBtn).toBeVisible();
  });

  test("should show success results after mock upload", async ({ page }) => {
    await page.route("**/api/v1/admin/users/bulk", async (route) => {
      if (route.request().method() === "POST") {
        await route.fulfill({
          json: {
            results: [
              { email: "success@test.com", success: true, userId: "u-1" },
              {
                email: "fail@test.com",
                success: false,
                message: "Invalid format",
              },
            ],
          },
          headers: { "Access-Control-Allow-Origin": "*" },
        });
      } else {
        await route.continue();
      }
    });

    await page.goto("/users");
    await expect(page.getByTestId("page-title")).toContainText(
      /사용자|Users/i,
      { timeout: 20000 },
    );

    await page.getByTestId("user-data-mgmt-btn").click();
    await page
      .getByRole("menuitem", { name: /일괄 임포트|일괄 등록|Bulk Import/i })
      .click();

    const uploadBtn = page.getByTestId("bulk-start-btn");
    await expect(uploadBtn).toBeDisabled();
  });

  test("should create missing tenant before user bulk import", async ({
    page,
  }) => {
    const requests: string[] = [];
    let bulkPayload = "";

    await page.route("**/api/v1/admin/tenants**", async (route) => {
      const method = route.request().method();
      requests.push(`${method} ${route.request().url()}`);

      if (method === "GET") {
        return route.fulfill({
          json: { items: [], total: 0, limit: 100, offset: 0 },
          headers: { "Access-Control-Allow-Origin": "*" },
        });
      }

      if (method === "POST") {
        return route.fulfill({
          status: 201,
          json: {
            id: "staging-missing-tenant-id",
            name: "Missing Tenant",
            slug: "missing-slug",
            type: "COMPANY",
            description: "Imported memo",
            status: "active",
            domains: ["missing.example.com"],
            memberCount: 0,
            createdAt: new Date().toISOString(),
            updatedAt: new Date().toISOString(),
          },
          headers: { "Access-Control-Allow-Origin": "*" },
        });
      }

      return route.continue();
    });

    await page.route("**/api/v1/admin/users/bulk", async (route) => {
      bulkPayload = route.request().postData() ?? "";
      return route.fulfill({
        json: {
          results: [{ email: "new@test.com", success: true, userId: "u-1" }],
        },
        headers: { "Access-Control-Allow-Origin": "*" },
      });
    });

    await page.goto("/users");
    await expect(page.getByTestId("page-title")).toContainText(
      /사용자|Users/i,
      { timeout: 20000 },
    );

    await page.getByTestId("user-data-mgmt-btn").click();
    await page
      .getByRole("menuitem", { name: /일괄 임포트|일괄 등록|Bulk Import/i })
      .click();
    await page.locator('input[type="file"]').setInputFiles({
      name: "users.csv",
      mimeType: "text/csv",
      buffer: Buffer.from(
        "email,name,tenant_id,tenant_slug,tenant_name,tenant_type,tenant_memo,email_domain\nnew@test.com,New User,local-tenant-id,missing-slug,Missing Tenant,COMPANY,Imported memo,missing.example.com\n",
      ),
    });

    await expect(
      page.getByTestId("user-import-tenant-resolution"),
    ).toContainText(/신규 생성|Create new/i);
    await page.getByTestId("bulk-start-btn").click();

    await expect(page.getByText("new@test.com")).toBeVisible();
    expect(requests.some((request) => request.startsWith("POST "))).toBe(true);
    expect(bulkPayload).toContain('"tenantId":"staging-missing-tenant-id"');
    expect(bulkPayload).toContain('"tenantSlug":"missing-slug"');
    expect(bulkPayload).toContain('"emailDomain":"missing.example.com"');
  });

  test("should include one nullable additional appointment from numbered CSV columns", async ({
    page,
  }) => {
    let bulkPayload = "";

    await page.unroute("**/api/v1/**");
    await page.route("**/api/v1/user/me", async (route) => {
      return route.fulfill({
        json: {
          id: "admin-user",
          name: "Admin",
          role: "super_admin",
          manageableTenants: [],
        },
        headers: { "Access-Control-Allow-Origin": "*" },
      });
    });
    await page.route(/\/api\/v1\/admin\/users(?:\?|$)/, async (route) => {
      return route.fulfill({
        json: { items: [], total: 0, limit: 50, offset: 0 },
        headers: { "Access-Control-Allow-Origin": "*" },
      });
    });
    await page.route(/\/api\/v1\/admin\/tenants(?:\?|$)/, async (route) => {
      if (route.request().method() === "GET") {
        return route.fulfill({
          json: {
            items: [
              {
                id: "tenant-primary-id",
                name: "Primary Tenant",
                slug: "primary-tenant",
                status: "active",
                type: "COMPANY",
                memberCount: 0,
                updatedAt: new Date().toISOString(),
              },
              {
                id: "tenant-second-id",
                name: "Second Tenant",
                slug: "second-tenant",
                status: "active",
                type: "COMPANY",
                memberCount: 0,
                updatedAt: new Date().toISOString(),
              },
            ],
            total: 2,
            limit: 1000,
            offset: 0,
          },
          headers: { "Access-Control-Allow-Origin": "*" },
        });
      }
      return route.fulfill({
        status: 201,
        json: {
          id: "tenant-created-id",
          name: "Primary Tenant",
          slug: "primary-tenant",
          status: "active",
          type: "COMPANY",
          memberCount: 0,
          updatedAt: new Date().toISOString(),
        },
        headers: { "Access-Control-Allow-Origin": "*" },
      });
    });

    await page.route("**/api/v1/admin/users/bulk", async (route) => {
      bulkPayload = route.request().postData() ?? "";
      return route.fulfill({
        json: {
          results: [{ email: "dual@test.com", success: true, userId: "u-1" }],
        },
        headers: { "Access-Control-Allow-Origin": "*" },
      });
    });

    await page.goto("/users");
    await expect(page.getByTestId("page-title")).toContainText(
      /사용자|Users/i,
      { timeout: 20000 },
    );

    await page.getByTestId("user-data-mgmt-btn").click();
    await page
      .getByRole("menuitem", { name: /일괄 임포트|일괄 등록|Bulk Import/i })
      .click();
    await page.locator('input[type="file"]').setInputFiles({
      name: "users.csv",
      mimeType: "text/csv",
      buffer: Buffer.from(
        [
          "email,name,phone,role,tenant_slug,department,grade,position,jobTitle,employee_id,tenant_slug1,department1,grade1,position1,jobTitle1,employee_id1,sub_email",
          "dual@test.com,Dual User,010-0000-0000,user,primary-tenant,개발팀,책임,팀장,Backend,EMP001,second-tenant,센터,수석,,Architecture,EMP002,dual.alias@hanmaceng.co.kr",
        ].join("\n"),
      ),
    });

    await page.getByTestId("bulk-start-btn").click();
    await expect(page.getByText("dual@test.com")).toBeVisible();

    const payload = JSON.parse(bulkPayload);
    expect(payload.users[0].tenantSlug).toBe("primary-tenant");
    expect(payload.users[0].metadata.employee_id).toBe("EMP001");
    expect(payload.users[0].metadata.sub_email).toEqual([
      "dual.alias@hanmaceng.co.kr",
    ]);
    expect(payload.users[0].metadata.secondary_emails).toEqual([
      "dual.alias@hanmaceng.co.kr",
    ]);
    expect(payload.users[0].metadata.aliasEmails).toEqual([
      "dual.alias@hanmaceng.co.kr",
    ]);
    expect(payload.users[0].additionalAppointments).toEqual([
      {
        tenantSlug: "second-tenant",
        department: "센터",
        grade: "수석",
        jobTitle: "Architecture",
        metadata: {
          employee_id: "EMP002",
        },
      },
    ]);
  });

  test("should show GPDTDC as Baron representative without changing WorksMobile primary affiliation", async ({
    page,
  }) => {
    let bulkPayload = "";

    await page.unroute("**/api/v1/**");
    await page.route("**/api/v1/user/me", async (route) => {
      return route.fulfill({
        json: {
          id: "admin-user",
          name: "Admin",
          role: "super_admin",
          manageableTenants: [],
        },
        headers: { "Access-Control-Allow-Origin": "*" },
      });
    });
    await page.route(/\/api\/v1\/admin\/users(?:\?|$)/, async (route) => {
      return route.fulfill({
        json: { items: [], total: 0, limit: 50, offset: 0 },
        headers: { "Access-Control-Allow-Origin": "*" },
      });
    });
    await page.route(/\/api\/v1\/admin\/tenants(?:\?|$)/, async (route) => {
      return route.fulfill({
        json: {
          items: [
            {
              id: "family-id",
              name: "한맥가족사",
              slug: "hanmac-family",
              status: "active",
              type: "COMPANY",
              memberCount: 0,
              updatedAt: new Date().toISOString(),
            },
            {
              id: "gpdtdc-id",
              name: "총괄기획&기술개발센터",
              slug: "gpdtdc",
              parentId: "family-id",
              status: "active",
              type: "COMPANY",
              memberCount: 0,
              updatedAt: new Date().toISOString(),
            },
            {
              id: "tdc-id",
              name: "기술개발센터",
              slug: "tdc",
              parentId: "gpdtdc-id",
              status: "active",
              type: "ORGANIZATION",
              memberCount: 0,
              updatedAt: new Date().toISOString(),
            },
            {
              id: "rnd-saman-id",
              name: "삼안기술개발센터",
              slug: "rnd-saman",
              status: "active",
              type: "ORGANIZATION",
              memberCount: 0,
              updatedAt: new Date().toISOString(),
            },
          ],
          total: 4,
          limit: 1000,
          offset: 0,
        },
        headers: { "Access-Control-Allow-Origin": "*" },
      });
    });

    await page.route("**/api/v1/admin/users/bulk", async (route) => {
      bulkPayload = route.request().postData() ?? "";
      return route.fulfill({
        json: {
          results: [
            { email: "gpdtdc-dual@test.com", success: true, userId: "u-1" },
          ],
        },
        headers: { "Access-Control-Allow-Origin": "*" },
      });
    });

    await page.goto("/users");
    await expect(page.getByTestId("page-title")).toContainText(
      /사용자|Users/i,
      { timeout: 20000 },
    );

    await page.getByTestId("user-data-mgmt-btn").click();
    await page
      .getByRole("menuitem", { name: /일괄 임포트|일괄 등록|Bulk Import/i })
      .click();
    await page.locator('input[type="file"]').setInputFiles({
      name: "users.csv",
      mimeType: "text/csv",
      buffer: Buffer.from(
        [
          "email,name,phone,role,tenant_slug,department,grade,position,jobTitle,employee_id,tenant_slug1,department1,grade1,position1,jobTitle1,employee_id1",
          "gpdtdc-dual@test.com,GPDTDC Dual User,010-0000-0000,user,rnd-saman,삼안기술연구소,책임,,,SAMAN001,tdc,,책임연구원,,,B24051",
        ].join("\n"),
      ),
    });

    await page.getByTestId("bulk-start-btn").click();
    await expect(page.getByText("gpdtdc-dual@test.com")).toBeVisible();

    const payload = JSON.parse(bulkPayload);
    expect(payload.users[0].tenantSlug).toBe("gpdtdc");
    expect(payload.users[0].additionalAppointments).toEqual([
      expect.objectContaining({
        tenantSlug: "rnd-saman",
        isPrimary: true,
        department: "삼안기술연구소",
        grade: "책임",
        metadata: {
          employee_id: "SAMAN001",
        },
      }),
      expect.objectContaining({
        tenantSlug: "tdc",
        isPrimary: false,
        grade: "책임연구원",
        metadata: {
          employee_id: "B24051",
        },
      }),
    ]);
  });
});
