const API_BASE = '/api';

interface ApiResponse<T> {
  data: T;
  error: string | null;
}

function getToken(): string | null {
  if (typeof localStorage === 'undefined') return null;
  return localStorage.getItem('token');
}

async function request<T>(
  endpoint: string,
  options: RequestInit = {}
): Promise<T> {
  const token = getToken();
  
  const res = await fetch(`${API_BASE}${endpoint}`, {
    headers: {
      'Content-Type': 'application/json',
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
      ...options.headers,
    },
    ...options,
  });

  if (res.status === 401) {
    localStorage.removeItem('token');
    window.location.href = '/auth/login';
    throw new Error('Unauthorized');
  }

  if (!res.ok) {
    const error = await res.json().catch(() => ({ error: 'Request failed' }));
    throw new Error(error.error || `HTTP ${res.status}`);
  }

  if (res.status === 204) {
    return {} as T;
  }

  const json: ApiResponse<T> = await res.json();
  if (json.error) {
    throw new Error(json.error);
  }
  return json.data;
}

export const api = {
  auth: {
    login: async (identifier: string, password: string) => {
      const res = await fetch(`${API_BASE}/auth/login`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ username: identifier, password }),
      });
      const json = await res.json();
      if (!res.ok) throw new Error(json.error || 'Login failed');
      localStorage.setItem('token', json.data.token);
      return json.data;
    },
    logout: () => {
      localStorage.removeItem('token');
    },
    me: () => request<UserInfo>('/auth/me'),
    forgot: async (identifier: string) => {
      const res = await fetch(`${API_BASE}/auth/forgot`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ identifier }),
      });
      const json = await res.json();
      if (!res.ok) throw new Error(json.error || 'Request failed');
      return json.data;
    },
    changePassword: async (oldPassword: string, newPassword: string) => {
      const res = await fetch(`${API_BASE}/auth/change-password`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${localStorage.getItem('token')}`,
        },
        body: JSON.stringify({ oldPassword, newPassword }),
      });
      const json = await res.json();
      if (!res.ok) throw new Error(json.error || 'Failed to change password');
      return json.data;
    },
    isLoggedIn: () => {
      return typeof localStorage !== 'undefined' && !!localStorage.getItem('token');
    },
  },

  domains: {
    list: () => request<Domain[]>('/domains'),
    get: (id: number) => request<Domain>(`/domains/${id}`),
    create: (data: { name: string }) => request<Domain>('/domains', { method: 'POST', body: JSON.stringify(data) }),
    delete: (id: number) => request<void>(`/domains/${id}`, { method: 'DELETE' }),
  },

  users: {
    listByDomain: (domainName: string) => request<User[]>(`/domains/${domainName}/users`),
    get: (domainName: string, id: number) => request<User>(`/domains/${domainName}/users/${id}`),
    create: (domainName: string, data: CreateUser) => request<User>(`/domains/${domainName}/users`, { method: 'POST', body: JSON.stringify(data) }),
    update: (domainName: string, id: number, data: Partial<User>) => request<void>(`/domains/${domainName}/users/${id}`, { method: 'PUT', body: JSON.stringify(data) }),
    delete: (domainName: string, id: number) => request<void>(`/domains/${domainName}/users/${id}`, { method: 'DELETE' }),
  },

  aliases: {
    listByDomain: (domainName: string) => request<Alias[]>(`/domains/${domainName}/aliases`),
    create: (domainName: string, data: CreateAlias) => request<Alias>(`/domains/${domainName}/aliases`, { method: 'POST', body: JSON.stringify(data) }),
    delete: (domainName: string, id: number) => request<void>(`/domains/${domainName}/aliases/${id}`, { method: 'DELETE' }),
  },

  queue: {
    list: () => request<QueueEntry[]>('/queue'),
    requeue: (id: string) => request<void>(`/queue/${id}/requeue`, { method: 'POST' }),
    delete: (id: string) => request<void>(`/queue/${id}`, { method: 'DELETE' }),
  },

  logs: {
    list: (hours = 1, filter = '') => request<LogEntry[]>(`/logs?hours=${hours}&filter=${encodeURIComponent(filter)}`),
  },
};

export interface UserInfo {
  id: number;
  username?: string;
  email?: string;
  role: string;
  domainId?: number;
  quota?: number;
}

export interface AuthUser {
  id: number;
  username: string;
  role: string;
  domainId?: number;
}

export interface Domain {
  id: number;
  name: string;
  userCount?: number;
  aliasCount?: number;
}

export interface User {
  id: number;
  email: string;
  domainId: number;
  quota: number;
  domain?: Domain;
}

export interface CreateUser {
  email: string;
  password: string;
  quota?: number;
}

export interface Alias {
  id: number;
  source: string;
  destination: string;
  domainId: number;
  domainName?: string;
}

export interface CreateAlias {
  source: string;
  destination: string;
}

export interface QueueEntry {
  id: string;
  sender: string;
  recipients: string[];
  size: number;
  time: string;
  reason: string;
}

export interface LogEntry {
  timestamp: string;
  priority: string;
  message: string;
}
