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

function seedAuthStorage(page: import("@playwright/test").Page) {
  return page.addInitScript(() => {
    localStorage.setItem("token", "test-token");
    localStorage.setItem("userId", "1");
    localStorage.setItem("role", "admin");
    localStorage.setItem("username", "toast-user");
  });
}

async function mockConfig(page: import("@playwright/test").Page) {
  await page.route("**/config", async (route) => {
    await route.fulfill({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify({
        maxFileSizeMB: 20,
        maxImageDimension: 800,
        imageQuality: 85,
      }),
    });
  });
}

test("login failure shows inline error and error toast", async ({ page }) => {
  await mockConfig(page);
  await page.route("**/auth/login", async (route) => {
    await route.fulfill({
      status: 401,
      contentType: "application/json",
      body: JSON.stringify({ message: "Invalid credentials" }),
    });
  });

  await page.goto("/login");
  await page.getByPlaceholder("Username").fill("bad-user");
  await page.getByPlaceholder("Password").fill("bad-password");
  await page.getByRole("button", { name: "Login" }).click();

  await expect(page.getByText("Invalid credentials")).toBeVisible();
  await expect(page.locator(".action-toast.action-toast-error")).toContainText("Login failed");
  await expect(page.locator(".action-toast.action-toast-error")).toContainText("Invalid credentials");
});

test("manage stores add success shows success toast", async ({ page }) => {
  await seedAuthStorage(page);
  await mockConfig(page);

  let linkedStoreIds = [10];
  const allStores = [
    { id: 10, name: "Costco North", location: "North", is_default: true },
    { id: 11, name: "Costco South", location: "South", is_default: false },
  ];

  await page.route("**/households", async (route) => {
    await route.fulfill({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify([{ id: 1, name: "Toast Home", role: "admin", invite_code: "ABCD1234" }]),
    });
  });

  await page.route("**/stores/household/1", async (route) => {
    const request = route.request();
    if (request.method() === "GET") {
      const payload = linkedStoreIds.map((id, index) => {
        const store = allStores.find((candidate) => candidate.id === id);
        return {
          ...store,
          is_default: index === 0,
        };
      });
      await route.fulfill({
        status: 200,
        contentType: "application/json",
        body: JSON.stringify(payload),
      });
      return;
    }

    if (request.method() === "POST") {
      const body = request.postDataJSON() as { storeId?: number };
      if (body.storeId && !linkedStoreIds.includes(body.storeId)) {
        linkedStoreIds = [...linkedStoreIds, body.storeId];
      }
      await route.fulfill({
        status: 200,
        contentType: "application/json",
        body: JSON.stringify({ ok: true }),
      });
      return;
    }

    await route.fallback();
  });

  await page.route("**/stores", async (route) => {
    await route.fulfill({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify(allStores),
    });
  });

  await page.goto("/manage?tab=stores");
  await page.getByRole("button", { name: "+ Add Store" }).click();
  await page.locator(".available-store-card").filter({ hasText: "Costco South" }).getByRole("button", { name: "Add" }).click();

  await expect(page.locator(".action-toast.action-toast-success")).toContainText("Added store");
  await expect(page.locator(".action-toast.action-toast-success")).toContainText("Costco South");
});

test("manage stores add failure shows normalized error toast", async ({ page }) => {
  await seedAuthStorage(page);
  await mockConfig(page);

  const allStores = [
    { id: 10, name: "Costco North", location: "North", is_default: true },
    { id: 11, name: "Costco South", location: "South", is_default: false },
  ];

  await page.route("**/households", async (route) => {
    await route.fulfill({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify([{ id: 1, name: "Toast Home", role: "admin", invite_code: "ABCD1234" }]),
    });
  });

  await page.route("**/stores/household/1", async (route) => {
    const request = route.request();
    if (request.method() === "GET") {
      await route.fulfill({
        status: 200,
        contentType: "application/json",
        body: JSON.stringify([{ id: 10, name: "Costco North", location: "North", is_default: true }]),
      });
      return;
    }

    if (request.method() === "POST") {
      await route.fulfill({
        status: 400,
        contentType: "application/json",
        body: JSON.stringify({
          error: { message: "Store already linked to household" },
        }),
      });
      return;
    }

    await route.fallback();
  });

  await page.route("**/stores", async (route) => {
    await route.fulfill({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify(allStores),
    });
  });

  await page.goto("/manage?tab=stores");
  await page.getByRole("button", { name: "+ Add Store" }).click();
  await page.locator(".available-store-card").filter({ hasText: "Costco South" }).getByRole("button", { name: "Add" }).click();

  await expect(page.locator(".action-toast.action-toast-error")).toContainText("Add store failed");
  await expect(page.locator(".action-toast.action-toast-error")).toContainText("Store already linked to household");
});

test("invite accept JOINED shows success toast", async ({ page }) => {
  await seedAuthStorage(page);
  await mockConfig(page);

  await page.route("**/api/invite-links/toast-token", async (route) => {
    const request = route.request();

    if (request.method() === "GET") {
      await route.fulfill({
        status: 200,
        contentType: "application/json",
        body: JSON.stringify({
          link: {
            token: "toast-token",
            status: "ACTIVE",
            viewerStatus: null,
            active_policy: "AUTO_ACCEPT",
            group_name: "Toast Group",
          },
        }),
      });
      return;
    }

    await route.fulfill({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify({
        result: {
          status: "JOINED",
          group: { name: "Toast Group" },
        },
      }),
    });
  });

  await page.route("**/households", async (route) => {
    await route.fulfill({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify([{ id: 1, name: "Toast Home", role: "member", invite_code: "ABCD1234" }]),
    });
  });

  await page.goto("/invite/toast-token");
  await page.getByRole("button", { name: "Join Group" }).click();

  await expect(page.locator(".action-toast.action-toast-success")).toContainText("Joined group");
  await expect(page.locator(".action-toast.action-toast-success")).toContainText("Toast Group");
});

test("invite accept PENDING shows info toast", async ({ page }) => {
  await seedAuthStorage(page);
  await mockConfig(page);

  await page.route("**/api/invite-links/pending-token", async (route) => {
    const request = route.request();

    if (request.method() === "GET") {
      await route.fulfill({
        status: 200,
        contentType: "application/json",
        body: JSON.stringify({
          link: {
            token: "pending-token",
            status: "ACTIVE",
            viewerStatus: null,
            active_policy: "APPROVAL_REQUIRED",
            group_name: "Pending Group",
          },
        }),
      });
      return;
    }

    await route.fulfill({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify({
        result: {
          status: "PENDING",
          group: { name: "Pending Group" },
        },
      }),
    });
  });

  await page.route("**/households", async (route) => {
    await route.fulfill({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify([{ id: 1, name: "Toast Home", role: "member", invite_code: "ABCD1234" }]),
    });
  });

  await page.goto("/invite/pending-token");
  await page.getByRole("button", { name: "Join Group" }).click();

  await expect(page.locator(".action-toast.action-toast-info")).toContainText("Join request sent");
  await expect(page.locator(".action-toast.action-toast-info")).toContainText("Pending Group");
});
