/**
 * End-to-end style test: admin eye button → staff review route → GET application + draft (mocked).
 */
import { describe, it, expect, beforeEach, vi, afterEach } from "vitest";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { MemoryRouter, Route, Routes } from "react-router-dom";
import type { ReactNode } from "react";
import { apiClient } from "@/shared/api/client";
import { getPermissionsForRoles, type Permission } from "@/lib/permissions";
import type { User } from "@/contexts/AuthContext";
import { ViewSubmittedApplicationButton } from "@/components/admin/ViewSubmittedApplicationButton";
import AdminApplicationReviewPage from "@/pages/AdminApplicationReviewPage";

const adminUser: User = {
  id: "admin-e2e-1",
  email: "admin@e2e.test",
  name: "Admin E2E",
  roles: ["admin"],
  availableRoles: ["admin"],
  permissions: getPermissionsForRoles(["admin"]),
};

function buildMockAuth() {
  return {
    user: adminUser,
    loading: false,
    isAuthenticated: true,
    isDemoMode: false,
    hasPermission: (permission: Permission) => adminUser.permissions.includes(permission),
    hasAnyPermission: (ps: Permission[]) => ps.some((p) => adminUser.permissions.includes(p)),
    hasRole: (r: "admin" | "editor" | "viewer") => r === "admin",
    login: vi.fn().mockResolvedValue({ success: true }),
    register: vi.fn().mockResolvedValue({ success: true }),
    logout: vi.fn().mockResolvedValue(undefined),
    setDemoUser: vi.fn(),
    clearDemoUser: vi.fn(),
    updateUserFields: vi.fn(),
    applyAuthUser: vi.fn().mockReturnValue({ success: true }),
  };
}

const mockUseAuth = vi.fn(() => buildMockAuth());

vi.mock("@/contexts/AuthContext", () => ({
  useAuth: () => mockUseAuth(),
  AuthProvider: ({ children }: { children: ReactNode }) => <>{children}</>,
}));

vi.mock("@/components/ChatAssistant", () => ({
  default: function MockChat() {
    return <div data-testid="chat-assistant-mock" />;
  },
}));

const SAMPLE_APP = {
  id: "admin-eye-app-1",
  name: "Hồ sơ admin E2E",
  submittedDate: "2026-04-22T10:00:00.000Z",
  author: { id: "CASE-ADMIN-E2E", name: "Tác giả phụ", email: "author@e2e.test" },
  status: "pending" as const,
  reviewStatus: "not_reviewed" as const,
  draftCaseId: "CASE-ADMIN-E2E",
  draft_case_id: "CASE-ADMIN-E2E",
};

const SAMPLE_DRAFT_BUNDLE = {
  caseId: "CASE-ADMIN-E2E",
  updatedAt: "2026-04-22T10:00:00.000Z",
  tabs: {
    report: { initiativeName: SAMPLE_APP.name, authorName: SAMPLE_APP.author.name },
    application: { initiativeName: SAMPLE_APP.name },
    contribution: { initiativeName: SAMPLE_APP.name, mainAuthor: SAMPLE_APP.author.name, participants: [] },
  },
};

function makeQueryClient() {
  return new QueryClient({
    defaultOptions: {
      queries: { retry: false },
      mutations: { retry: false },
    },
  });
}

function renderAdminEyeFlow() {
  const client = makeQueryClient();
  return render(
    <QueryClientProvider client={client}>
      <MemoryRouter initialEntries={["/dashboard/admin-applications"]}>
        <Routes>
          <Route
            path="/dashboard/admin-applications"
            element={
              <ViewSubmittedApplicationButton
                applicationId={SAMPLE_APP.id}
                returnTo="/dashboard/admin-applications"
              />
            }
          />
          <Route path="/dashboard/admin/applications/review" element={<AdminApplicationReviewPage />} />
        </Routes>
      </MemoryRouter>
    </QueryClientProvider>,
  );
}

describe("Admin ViewSubmittedApplicationButton (integration)", () => {
  const getSpy = vi.spyOn(apiClient, "get");

  beforeEach(() => {
    mockUseAuth.mockImplementation(() => buildMockAuth());
    getSpy.mockImplementation((url: unknown) => {
      const u = String(url);
      if (u.includes(`/api/applications/${encodeURIComponent(SAMPLE_APP.id)}`)) {
        return Promise.resolve(SAMPLE_APP);
      }
      if (u.includes("/api/v1/application-drafts/")) {
        return Promise.resolve(SAMPLE_DRAFT_BUNDLE);
      }
      return Promise.reject(new Error(`Unmocked GET: ${u}`));
    });
  });

  afterEach(() => {
    getSpy.mockReset();
    vi.clearAllMocks();
  });

  it("navigates to staff review URL and loads application detail plus draft bundle", async () => {
    const user = userEvent.setup();
    renderAdminEyeFlow();

    await user.click(screen.getByRole("button", { name: /Xem hồ sơ/i }));

    await waitFor(() => {
      expect(screen.getByRole("heading", { name: /Xem hồ sơ đã nộp/i })).toBeInTheDocument();
    });

    await waitFor(() => {
      expect(
        getSpy.mock.calls.some(
          (c) =>
            String(c[0]).includes("/api/applications/") &&
            String(c[0]).includes(SAMPLE_APP.id) &&
            !String(c[0]).includes("mine"),
        ),
      ).toBe(true);
    });

    await waitFor(() => {
      expect(getSpy.mock.calls.some((c) => String(c[0]).includes("/api/v1/application-drafts/"))).toBe(true);
    });
  });
});
