import { fetchAllCursorPages } from "../../../common/core/pagination";
import apiClient from "./apiClient";
import { userManager } from "./auth";

export type AuditLog = {
  event_id: string;
  timestamp: string;
  user_id: string;
  event_type: string;
  status: string;
  ip_address: string;
  user_agent: string;
  device_id?: string;
  details?: string;
};

export type AuditLogListResponse = {
  items: AuditLog[];
  limit: number;
  cursor?: string;
  next_cursor?: string;
};

export type TenantSummary = {
  id: string;
  type: string; // 허용 타입: PERSONAL, COMPANY, COMPANY_GROUP, ORGANIZATION, USER_GROUP
  name: string;
  slug: string;
  description: string;
  status: string;
  domains?: string[];
  parentId?: string;
  config?: Record<string, unknown>;
  memberCount: number; // Added member count
  totalMemberCount?: number;
  createdAt: string;
  updatedAt: string;
};

export type TenantCreateRequest = {
  name: string;
  type?: string;
  slug?: string;
  parentId?: string;
  description?: string;
  status?: string;
  domains?: string[];
  config?: Record<string, unknown>;
};

export type TenantListResponse = {
  items: TenantSummary[];
  limit: number;
  offset: number;
  total: number;
  cursor?: string;
  nextCursor?: string;
  next_cursor?: string;
};

export type TenantUpdateRequest = {
  name?: string;
  type?: string;
  slug?: string;
  parentId?: string;
  description?: string;
  status?: string;
  domains?: string[];
  config?: Record<string, unknown>;
};

export type ApiKeySummary = {
  id: string;
  name: string;
  client_id: string;
  scopes: string[];
  status: string;
  lastUsedAt?: string;
  createdAt: string;
};

export type ApiKeyListResponse = {
  items: ApiKeySummary[];
  total: number;
};

export type RoleSummary = {
  id: string;
  name: string;
  description: string;
  permissions: string[];
  createdAt: string;
  updatedAt: string;
};

export type RoleListResponse = {
  items: RoleSummary[];
  total: number;
};

export async function fetchAuditLogs(limit = 50, cursor?: string) {
  const { data } = await apiClient.get<AuditLogListResponse>("/v1/audit", {
    params: { limit, cursor },
  });
  return data;
}

export async function fetchTenants(
  limit = 50,
  offset = 0,
  parentId?: string,
  cursor?: string,
) {
  const { data } = await apiClient.get<TenantListResponse>(
    "/v1/admin/tenants",
    {
      params: { limit, offset, parentId, cursor },
    },
  );
  return data;
}

function getOrgApiBaseUrl() {
  return (
    import.meta.env.VITE_DEV_API_BASE ??
    import.meta.env.VITE_ADMIN_API_BASE ??
    "/api"
  );
}

async function buildOrgRequestHeaders() {
  const headers: Record<string, string> = {};
  const user = await userManager.getUser();

  if (user?.access_token) {
    headers.Authorization = `Bearer ${user.access_token}`;
  }

  const tenantId = window.localStorage.getItem("dev_tenant_id");
  if (tenantId) {
    headers["X-Tenant-ID"] = tenantId;
  }

  return headers;
}

export async function fetchAllTenants({
  pageSize = 100,
  parentId,
}: {
  pageSize?: number;
  parentId?: string;
} = {}) {
  return fetchAllCursorPages<TenantSummary>({
    baseUrl: getOrgApiBaseUrl(),
    path: "/v1/admin/tenants",
    pageSize,
    params: { parentId },
    headers: await buildOrgRequestHeaders(),
  }) as Promise<TenantListResponse>;
}

export type OrgChartSnapshotResponse = {
  tenants: TenantSummary[];
  users: UserSummary[];
  cache?: {
    source: "redis" | "database";
    hit: boolean;
    ttlSeconds?: number;
  };
};

export async function fetchOrgChartSnapshot() {
  const { data } = await apiClient.get<OrgChartSnapshotResponse>(
    "/v1/admin/orgchart/snapshot",
    {
      params: { cache: "redis" },
    },
  );
  return data;
}

export async function fetchTenant(tenantId: string) {
  const { data } = await apiClient.get<TenantSummary>(
    `/v1/admin/tenants/${tenantId}`,
  );
  return data;
}

export async function createTenant(payload: TenantCreateRequest) {
  const { data } = await apiClient.post<TenantSummary>(
    "/v1/admin/tenants",
    payload,
  );
  return data;
}

export async function updateTenant(
  tenantId: string,
  payload: TenantUpdateRequest,
) {
  const { data } = await apiClient.put<TenantSummary>(
    `/v1/admin/tenants/${tenantId}`,
    payload,
  );
  return data;
}

export async function deleteTenant(tenantId: string) {
  await apiClient.delete(`/v1/admin/tenants/${tenantId}`);
}

export async function deleteTenantsBulk(ids: string[]) {
  await apiClient.delete("/v1/admin/tenants/bulk", {
    data: { ids },
  });
}

export async function approveTenant(tenantId: string) {
  const { data } = await apiClient.post<TenantSummary>(
    `/v1/admin/tenants/${tenantId}/approve`,
  );
  return data;
}

export type TenantAdmin = {
  id: string;
  name: string;
  email: string;
};

export async function fetchTenantAdmins(tenantId: string) {
  const { data } = await apiClient.get<TenantAdmin[]>(
    `/v1/admin/tenants/${tenantId}/admins`,
  );
  return data;
}

export async function addTenantAdmin(tenantId: string, userId: string) {
  await apiClient.post(`/v1/admin/tenants/${tenantId}/admins/${userId}`);
}

export async function removeTenantAdmin(tenantId: string, userId: string) {
  await apiClient.delete(`/v1/admin/tenants/${tenantId}/admins/${userId}`);
}

export async function fetchTenantOwners(tenantId: string) {
  const { data } = await apiClient.get<TenantAdmin[]>(
    `/v1/admin/tenants/${tenantId}/owners`,
  );
  return data;
}

export async function addTenantOwner(tenantId: string, userId: string) {
  await apiClient.post(`/v1/admin/tenants/${tenantId}/owners/${userId}`);
}

export async function removeTenantOwner(tenantId: string, userId: string) {
  await apiClient.delete(`/v1/admin/tenants/${tenantId}/owners/${userId}`);
}

// Group Management
export type GroupMember = {
  id: string;
  name: string;
  email: string;
};

export type GroupSummary = {
  id: string;
  tenantId: string;
  parentId?: string;
  name: string;
  description?: string;
  unitType?: string;
  members?: GroupMember[];
  createdAt?: string;
  updatedAt?: string;
};

export type GroupCreateRequest = {
  name: string;
  parentId?: string;
  description?: string;
  unitType?: string;
};

export async function fetchGroups(tenantId: string) {
  const { data } = await apiClient.get<GroupSummary[]>(
    `/v1/admin/tenants/${tenantId}/organization`,
  );
  return data;
}

export async function fetchGroup(tenantId: string, groupId: string) {
  const { data } = await apiClient.get<GroupSummary>(
    `/v1/admin/tenants/${tenantId}/organization/${groupId}`,
  );
  return data;
}

export async function createGroup(
  tenantId: string,
  payload: GroupCreateRequest,
) {
  const { data } = await apiClient.post<GroupSummary>(
    `/v1/admin/tenants/${tenantId}/organization`,
    payload,
  );
  return data;
}

export async function deleteGroup(tenantId: string, groupId: string) {
  await apiClient.delete(
    `/v1/admin/tenants/${tenantId}/organization/${groupId}`,
  );
}

export async function addGroupMember(
  tenantId: string,
  groupId: string,
  userId: string,
) {
  await apiClient.post(
    `/v1/admin/tenants/${tenantId}/organization/${groupId}/members`,
    { userId },
  );
}

export async function removeGroupMember(
  tenantId: string,
  groupId: string,
  userId: string,
) {
  await apiClient.delete(
    `/v1/admin/tenants/${tenantId}/organization/${groupId}/members/${userId}`,
  );
}

export interface ImportResult {
  totalRows: number;
  processed: number;
  userCreated: number;
  userUpdated: number;
  tenantCreated: number;
  errors: string[];
}

export async function fetchImportProgress(
  tenantId: string,
  progressId: string,
) {
  const { data } = await apiClient.get<{ current: number; total: number }>(
    `/v1/admin/tenants/${tenantId}/organization/import/progress/${progressId}`,
  );
  return data;
}

export async function importOrgChart(
  tenantId: string,
  file: File,
  progressId?: string,
) {
  const formData = new FormData();
  formData.append("file", file);
  const url = progressId
    ? `/v1/admin/tenants/${tenantId}/organization/import?progressId=${progressId}`
    : `/v1/admin/tenants/${tenantId}/organization/import`;

  const { data } = await apiClient.post<{ data: ImportResult }>(url, formData, {
    headers: {
      "Content-Type": "multipart/form-data",
    },
  });
  return data.data;
}

export type GroupRole = {
  tenantId: string;
  tenantName: string;
  relation: string;
};

export async function fetchGroupRoles(tenantId: string, groupId: string) {
  const { data } = await apiClient.get<GroupRole[]>(
    `/v1/admin/tenants/${tenantId}/organization/${groupId}/roles`,
  );
  return data;
}

export async function assignGroupRole(
  tenantId: string,
  groupId: string,
  targetTenantId: string,
  relation: string,
) {
  await apiClient.post(
    `/v1/admin/tenants/${tenantId}/organization/${groupId}/roles`,
    { tenantId: targetTenantId, relation },
  );
}

export async function removeGroupRole(
  tenantId: string,
  groupId: string,
  targetTenantId: string,
  relation: string,
) {
  await apiClient.delete(
    `/v1/admin/tenants/${tenantId}/organization/${groupId}/roles/${targetTenantId}/${relation}`,
  );
}

// API Key Management (M2M)
export type ApiKeyCreateRequest = {
  name: string;
  scopes: string[];
};

export type ApiKeyCreateResponse = {
  apiKey: ApiKeySummary;
  clientSecret: string;
};

export async function fetchApiKeys(limit = 50, offset = 0) {
  const { data } = await apiClient.get<ApiKeyListResponse>(
    "/v1/admin/api-keys",
    {
      params: { limit, offset },
    },
  );
  return data;
}

export async function createApiKey(payload: ApiKeyCreateRequest) {
  const { data } = await apiClient.post<ApiKeyCreateResponse>(
    "/v1/admin/api-keys",
    payload,
  );
  return data;
}

export async function deleteApiKey(apiKeyId: string) {
  await apiClient.delete(`/v1/admin/api-keys/${apiKeyId}`);
}

// User Management
export type UserSummary = {
  id: string;
  email: string;
  loginId?: string;
  name: string;
  phone?: string;
  role: string;
  status: string;
  tenantSlug?: string;
  companyCode?: string;
  tenant?: TenantSummary;
  joinedTenants?: TenantSummary[]; // [New] 다중 소속 테넌트 목록
  metadata?: Record<string, unknown>;
  department?: string;
  grade?: string;
  position?: string;
  jobTitle?: string;
  createdAt: string;
  updatedAt: string;
};

export type UserListResponse = {
  items: UserSummary[];
  limit: number;
  offset: number;
  total: number;
};

export type UserCreateRequest = {
  email: string;
  loginId?: string;
  password?: string;
  name: string;
  phone?: string;
  role?: string;
  tenantSlug?: string;
  department?: string;
  grade?: string;
  position?: string;
  jobTitle?: string;
  metadata?: Record<string, unknown>;
};

export type UserCreateResponse = UserSummary & {
  initialPassword?: string;
};

export type UserUpdateRequest = {
  loginId?: string;
  password?: string;
  name?: string;
  phone?: string;
  role?: string;
  status?: string;
  tenantSlug?: string;
  department?: string;
  grade?: string;
  position?: string;
  jobTitle?: string;
  metadata?: Record<string, unknown>;
};

export type BulkUserItem = {
  email: string;
  loginId?: string;
  name: string;
  phone?: string;
  role?: string;
  tenantSlug?: string;
  department?: string;
  grade?: string;
  position?: string;
  jobTitle?: string;
  metadata: Record<string, string>;
};

export type BulkUserResult = {
  email: string;
  success: boolean;
  message?: string;
  userId?: string;
};

export type BulkUserResponse = {
  results: BulkUserResult[];
};

export async function fetchUsers(
  limit = 50,
  offset = 0,
  search?: string,
  tenantSlug?: string,
) {
  const { data } = await apiClient.get<UserListResponse>("/v1/admin/users", {
    params: { limit, offset, search, tenantSlug },
  });
  return data;
}

export async function fetchUser(userId: string) {
  const { data } = await apiClient.get<UserSummary>(
    `/v1/admin/users/${userId}`,
  );
  return data;
}

export async function createUser(payload: UserCreateRequest) {
  const { data } = await apiClient.post<UserCreateResponse>(
    "/v1/admin/users",
    payload,
  );
  return data;
}

export function exportUsersCSVUrl(search?: string, tenantSlug?: string) {
  const params = new URLSearchParams();
  if (search) params.append("search", search);
  if (tenantSlug) params.append("tenantSlug", tenantSlug);

  // Get mock role from storage if exists for dev environment
  const isMockRoleEnabled =
    window.localStorage.getItem("X-Mock-Role-Enabled") === "true";
  const mockRole = window.localStorage.getItem("X-Mock-Role");
  if (isMockRoleEnabled && mockRole) params.append("x-test-role", mockRole);

  const baseUrl = import.meta.env.VITE_ADMIN_API_BASE ?? "/api/v1";
  return `${baseUrl}/admin/users/export?${params.toString()}`;
}

export async function bulkCreateUsers(users: BulkUserItem[]) {
  const { data } = await apiClient.post<BulkUserResponse>(
    "/v1/admin/users/bulk",
    { users },
  );
  return data;
}

export async function bulkUpdateUsers(payload: {
  userIds: string[];
  status?: string;
  role?: string;
  tenantSlug?: string;
  department?: string;
}) {
  const { data } = await apiClient.put("/v1/admin/users/bulk", payload);
  return data;
}

export async function bulkDeleteUsers(userIds: string[]) {
  const { data } = await apiClient.delete("/v1/admin/users/bulk", {
    data: { userIds },
  });
  return data;
}

export async function updateUser(userId: string, payload: UserUpdateRequest) {
  const { data } = await apiClient.put<UserSummary>(
    `/v1/admin/users/${userId}`,
    payload,
  );
  return data;
}

export type PasswordPolicyResponse = {
  minLength?: number;
  lowercase?: boolean;
  uppercase?: boolean;
  number?: boolean;
  nonAlphanumeric?: boolean;
  minCharacterTypes?: number;
};

export async function fetchPasswordPolicy() {
  const { data } = await apiClient.get<PasswordPolicyResponse>(
    "/v1/auth/password/policy",
  );
  return data;
}

export async function deleteUser(userId: string) {
  await apiClient.delete(`/v1/admin/users/${userId}`);
}

export type UserRpHistoryItem = {
  client_id: string;
  client_name: string;
  lastLoginAt: string;
  status: string;
};

export async function fetchUserRpHistory(userId: string) {
  const { data } = await apiClient.get<UserRpHistoryItem[]>(
    `/v1/admin/users/${userId}/rp-history`,
  );
  return data;
}

export type UserProfileResponse = {
  id: string;
  email: string;
  name: string;
  phone: string;
  role: string;
  department: string;
  affiliationType: string;
  tenantSlug?: string;
  tenantId?: string;
  metadata?: Record<string, unknown>;
  tenant?: TenantSummary;
  manageableTenants?: TenantSummary[];
};

export async function fetchMe() {
  const { data } = await apiClient.get<UserProfileResponse>("/v1/user/me");
  return data;
}

// Relying Party Management
export type RelyingParty = {
  clientId: string;
  tenantId: string;
  name: string;
  description: string;
  createdAt: string;
  updatedAt: string;
};

export type HydraClientReq = {
  client_id?: string;
  client_name: string;
  client_secret?: string;
  redirect_uris: string[];
  scope?: string;
  token_endpoint_auth_method?: string;
  grant_types?: string[];
  response_types?: string[];
  metadata?: Record<string, unknown>;
};

export async function fetchRelyingParties(tenantId: string) {
  const { data } = await apiClient.get<RelyingParty[]>(
    `/v1/admin/tenants/${tenantId}/relying-parties`,
  );
  return data;
}

export async function fetchAllRelyingParties() {
  const { data } = await apiClient.get<RelyingParty[]>(
    "/v1/admin/relying-parties",
  );
  return data;
}

export async function createRelyingParty(
  tenantId: string,
  payload: HydraClientReq,
) {
  const { data } = await apiClient.post<RelyingParty>(
    `/v1/admin/tenants/${tenantId}/relying-parties`,
    payload,
  );
  return data;
}

export async function fetchRelyingParty(id: string) {
  const { data } = await apiClient.get<{
    relyingParty: RelyingParty;
    oauth2Config: HydraClientReq;
  }>(`/v1/admin/relying-parties/${id}`);
  return data;
}

export async function updateRelyingParty(id: string, payload: HydraClientReq) {
  const { data } = await apiClient.put<RelyingParty>(
    `/v1/admin/relying-parties/${id}`,
    payload,
  );
  return data;
}

export async function deleteRelyingParty(id: string) {
  await apiClient.delete(`/v1/admin/relying-parties/${id}`);
}

export type RPOwner = {
  subject: string;

  name?: string;

  email?: string;

  type: string;
};

export async function fetchRPOwners(clientId: string) {
  const { data } = await apiClient.get<RPOwner[]>(
    `/v1/admin/relying-parties/${clientId}/owners`,
  );

  return data;
}

export async function addRPOwner(clientId: string, subject: string) {
  await apiClient.post(
    `/v1/admin/relying-parties/${clientId}/owners/${subject}`,
  );
}

export async function removeRPOwner(clientId: string, subject: string) {
  await apiClient.delete(
    `/v1/admin/relying-parties/${clientId}/owners/${subject}`,
  );
}

export async function fetchPublicOrgChart(token: string) {
  const { data } = await apiClient.get<{
    tenants: TenantSummary[];
    users: UserSummary[];
    sharedWith: string;
  }>("/v1/public/orgchart", {
    params: { token },
  });
  return data;
}
