const API_BASE = import.meta.env.VITE_API_BASE_URL ?? "/api/v1";
export const AUTH_EXPIRED_EVENT = "nexavpn-admin-auth-expired";

export type User = {
  id: string;
  username: string;
  display_name: string;
  email?: string;
  role: string;
  is_active: boolean;
};

export type Device = {
  id: string;
  name: string;
  user_id?: string;
  platform: string;
  status: string;
  assigned_ip?: string;
};

export type DeviceProfile = {
  device: Device;
  peer: {
    assigned_ip: string;
    dns_servers: string[];
    allowed_ips: string[];
    gateway: {
      id: string;
      name: string;
      endpoint: string;
      public_key: string;
    };
    profile_revision: number;
  };
  profile: {
    format: string;
    content: string;
  };
  resources: Array<{
    type: string;
    value: string;
    label: string;
  }>;
};

export type Policy = {
  id: string;
  name: string;
  description: string;
  priority: number;
  effect: string;
  full_tunnel: boolean;
  is_active: boolean;
  destinations?: string[];
  targets?: Array<{
    type: string;
    id: string;
    name?: string;
  }>;
};

export type Group = {
  id: string;
  name: string;
  description: string;
  members: Array<{
    id: string;
    username: string;
    display_name: string;
  }>;
  user_ids?: string[];
};

export type Gateway = {
  id: string;
  name: string;
  endpoint: string;
  public_key: string;
  listen_port: number;
  vpn_cidr: string;
  dns_servers: string[];
  is_active: boolean;
};

export type AuditEvent = {
  id: string;
  event_type: string;
  entity_type: string;
  status: string;
  message: string;
  created_at: string;
};

async function request<T>(path: string, init?: RequestInit): Promise<T> {
  const token = localStorage.getItem("nexavpn_admin_token");
  const response = await fetch(`${API_BASE}${path}`, {
    ...init,
    headers: {
      "Content-Type": "application/json",
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
      ...(init?.headers ?? {})
    }
  });

  if (!response.ok) {
    if (response.status === 401) {
      localStorage.removeItem("nexavpn_admin_token");
      window.dispatchEvent(new Event(AUTH_EXPIRED_EVENT));
    }
    throw new Error(`Request failed: ${response.status}`);
  }

  return response.json() as Promise<T>;
}

export const api = {
  users: () => request<User[]>("/admin/users"),
  createUser: (payload: {
    username: string;
    display_name: string;
    email: string;
    password: string;
    role: string;
  }) =>
    request<User>("/admin/users", {
      method: "POST",
      body: JSON.stringify(payload)
    }),
  updateUser: (userId: string, payload: {
    display_name?: string;
    email?: string;
    role?: string;
    password?: string;
    is_active?: boolean;
  }) =>
    request<User>(`/admin/users/${userId}`, {
      method: "PATCH",
      body: JSON.stringify(payload)
    }),
  deleteUser: (userId: string) =>
    request<{ ok: boolean }>(`/admin/users/${userId}`, {
      method: "DELETE"
    }),
  groups: () => request<Group[]>("/admin/groups"),
  createGroup: (payload: {
    name: string;
    description: string;
    user_ids: string[];
  }) =>
    request<Group>("/admin/groups", {
      method: "POST",
      body: JSON.stringify(payload)
    }),
  updateGroup: (groupId: string, payload: {
    name?: string;
    description?: string;
    user_ids?: string[];
  }) =>
    request<Group>(`/admin/groups/${groupId}`, {
      method: "PATCH",
      body: JSON.stringify(payload)
    }),
  deleteGroup: (groupId: string) =>
    request<{ ok: boolean }>(`/admin/groups/${groupId}`, {
      method: "DELETE"
    }),
  devices: () => request<Device[]>("/admin/devices"),
  deviceProfile: (deviceId: string) => request<DeviceProfile>(`/admin/devices/${deviceId}/profile`),
  revokeDevice: (deviceId: string) =>
    request<{ ok: boolean }>(`/admin/devices/${deviceId}/revoke`, {
      method: "POST",
      body: JSON.stringify({})
    }),
  rotateDevice: (deviceId: string) =>
    request<{ ok: boolean }>(`/admin/devices/${deviceId}/rotate`, {
      method: "POST",
      body: JSON.stringify({})
    }),
  policies: () => request<Policy[]>("/admin/policies"),
  createPolicy: (payload: {
    name: string;
    description: string;
    priority: number;
    effect: string;
    full_tunnel: boolean;
    destinations: string[];
    targets: Array<{ type: string; id: string }>;
  }) =>
    request<Policy>("/admin/policies", {
      method: "POST",
      body: JSON.stringify(payload)
    }),
  updatePolicy: (policyId: string, payload: {
    name?: string;
    description?: string;
    priority?: number;
    effect?: string;
    full_tunnel?: boolean;
    is_active?: boolean;
    destinations?: string[];
    targets?: Array<{ type: string; id: string }>;
  }) =>
    request<Policy>(`/admin/policies/${policyId}`, {
      method: "PATCH",
      body: JSON.stringify(payload)
    }),
  deletePolicy: (policyId: string) =>
    request<{ ok: boolean }>(`/admin/policies/${policyId}`, {
      method: "DELETE"
    }),
  gateways: () => request<Gateway[]>("/admin/gateways"),
  updateGateway: (gatewayId: string, payload: {
    endpoint: string;
    public_key: string;
    listen_port: number;
    vpn_cidr: string;
    dns_servers: string[];
    is_active: boolean;
  }) =>
    request<Gateway>(`/admin/gateways/${gatewayId}`, {
      method: "PATCH",
      body: JSON.stringify(payload)
    }),
  gatewaySync: (gatewayId: string) => request<unknown>(`/admin/gateways/${gatewayId}/sync`),
  audit: () => request<AuditEvent[]>("/admin/audit-logs")
};
