import { HttpClient, type HttpClientConfig, type QueryParams } from './http';
import type {
  PaginationParams,
  PaginatedResponse,
  LoginRequest,
  LoginResponse,
  RefreshRequest,
  RefreshResponse,
  User,
  Client,
  Department,
  CreateDepartmentRequest,
  UpdateDepartmentRequest,
  Room,
  CreateRoomRequest,
  UpdateRoomRequest,
  ServiceCategory,
  Service,
  Package,
  Club,
  CreateClubRequest,
  UpdateClubRequest,
  License,
  CreateLicenseRequest,
  UpdateLicenseRequest,
  Report,
  GenerateReportRequest,
  WebhookSubscription,
  WebhookLog,
  CreateWebhookRequest,
  UpdateWebhookRequest,
  IntegrationConfig,
  UpdateIntegrationConfigRequest,
  SyncLog,
  TriggerSyncRequest,
  Training,
  FunnelEntry,
  Sale,
  StatsSummary,
  FunnelStats,
  RatingEntry,
  Notification,
  NotificationSetting,
  SipCall,
  SipSettings,
  UsageRecord,
  LimitCheck,
} from './types';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function q(params?: any): QueryParams | undefined {
  if (!params) return undefined;
  const result: QueryParams = {};
  for (const [key, value] of Object.entries(params)) {
    if (value !== undefined && value !== null) {
      result[key] = typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'
        ? value
        : String(value);
    }
  }
  return result;
}

export class FitCrmApiClient {
  private http: HttpClient;

  auth: AuthApi;
  users: UsersApi;
  clients: ClientsApi;
  departments: DepartmentsApi;
  rooms: RoomsApi;
  catalog: CatalogApi;
  clubs: ClubsApi;
  licenses: LicensesApi;
  reports: ReportsApi;
  webhooks: WebhooksApi;
  integration: IntegrationApi;
  schedule: ScheduleApi;
  funnel: FunnelApi;
  sales: SalesApi;
  stats: StatsApi;
  notifications: NotificationsApi;
  sip: SipApi;
  metering: MeteringApi;

  constructor(config: HttpClientConfig) {
    this.http = new HttpClient(config);
    this.auth = new AuthApi(this.http);
    this.users = new UsersApi(this.http);
    this.clients = new ClientsApi(this.http);
    this.departments = new DepartmentsApi(this.http);
    this.rooms = new RoomsApi(this.http);
    this.catalog = new CatalogApi(this.http);
    this.clubs = new ClubsApi(this.http);
    this.licenses = new LicensesApi(this.http);
    this.reports = new ReportsApi(this.http);
    this.webhooks = new WebhooksApi(this.http);
    this.integration = new IntegrationApi(this.http);
    this.schedule = new ScheduleApi(this.http);
    this.funnel = new FunnelApi(this.http);
    this.sales = new SalesApi(this.http);
    this.stats = new StatsApi(this.http);
    this.notifications = new NotificationsApi(this.http);
    this.sip = new SipApi(this.http);
    this.metering = new MeteringApi(this.http);
  }
}

class AuthApi {
  constructor(private http: HttpClient) {}

  login(data: LoginRequest) {
    return this.http.post<LoginResponse>('/auth/login', data);
  }

  refresh(data: RefreshRequest) {
    return this.http.post<RefreshResponse>('/auth/refresh', data);
  }
}

class UsersApi {
  constructor(private http: HttpClient) {}

  list(params?: PaginationParams & { role?: string }) {
    return this.http.get<PaginatedResponse<User>>('/users', q(params));
  }

  getById(id: string) {
    return this.http.get<User>(`/users/${id}`);
  }

  trainers(params?: PaginationParams) {
    return this.http.get<PaginatedResponse<User>>('/users/trainers', q(params));
  }
}

class ClientsApi {
  constructor(private http: HttpClient) {}

  list(params?: PaginationParams & { search?: string; trainerId?: string }) {
    return this.http.get<PaginatedResponse<Client>>('/clients', q(params));
  }

  getById(id: string) {
    return this.http.get<Client>(`/clients/${id}`);
  }

  create(data: Partial<Client>) {
    return this.http.post<Client>('/clients', data);
  }

  update(id: string, data: Partial<Client>) {
    return this.http.patch<Client>(`/clients/${id}`, data);
  }

  delete(id: string) {
    return this.http.delete<void>(`/clients/${id}`);
  }

  sleeping(params?: PaginationParams) {
    return this.http.get<PaginatedResponse<Client>>('/clients/sleeping', q(params));
  }
}

class DepartmentsApi {
  constructor(private http: HttpClient) {}

  list(params?: PaginationParams & { search?: string }) {
    return this.http.get<PaginatedResponse<Department>>('/departments', q(params));
  }

  getById(id: string) {
    return this.http.get<Department>(`/departments/${id}`);
  }

  create(data: CreateDepartmentRequest) {
    return this.http.post<Department>('/departments', data);
  }

  update(id: string, data: UpdateDepartmentRequest) {
    return this.http.patch<Department>(`/departments/${id}`, data);
  }

  delete(id: string) {
    return this.http.delete<void>(`/departments/${id}`);
  }
}

class RoomsApi {
  constructor(private http: HttpClient) {}

  list(params?: PaginationParams & { isActive?: boolean }) {
    return this.http.get<PaginatedResponse<Room>>('/rooms', q(params));
  }

  getById(id: string) {
    return this.http.get<Room>(`/rooms/${id}`);
  }

  create(data: CreateRoomRequest) {
    return this.http.post<Room>('/rooms', data);
  }

  update(id: string, data: UpdateRoomRequest) {
    return this.http.patch<Room>(`/rooms/${id}`, data);
  }

  delete(id: string) {
    return this.http.delete<void>(`/rooms/${id}`);
  }
}

class CatalogApi {
  categories: CategoriesApi;
  services: ServicesApi;
  packages: PackagesApi;

  constructor(http: HttpClient) {
    this.categories = new CategoriesApi(http);
    this.services = new ServicesApi(http);
    this.packages = new PackagesApi(http);
  }
}

class CategoriesApi {
  constructor(private http: HttpClient) {}

  list(params?: PaginationParams) {
    return this.http.get<PaginatedResponse<ServiceCategory>>('/catalog/categories', q(params));
  }

  getById(id: string) {
    return this.http.get<ServiceCategory>(`/catalog/categories/${id}`);
  }

  create(data: Partial<ServiceCategory>) {
    return this.http.post<ServiceCategory>('/catalog/categories', data);
  }

  update(id: string, data: Partial<ServiceCategory>) {
    return this.http.patch<ServiceCategory>(`/catalog/categories/${id}`, data);
  }

  delete(id: string) {
    return this.http.delete<void>(`/catalog/categories/${id}`);
  }
}

class ServicesApi {
  constructor(private http: HttpClient) {}

  list(params?: PaginationParams & { categoryId?: string }) {
    return this.http.get<PaginatedResponse<Service>>('/catalog/services', q(params));
  }

  getById(id: string) {
    return this.http.get<Service>(`/catalog/services/${id}`);
  }

  create(data: Partial<Service>) {
    return this.http.post<Service>('/catalog/services', data);
  }

  update(id: string, data: Partial<Service>) {
    return this.http.patch<Service>(`/catalog/services/${id}`, data);
  }

  delete(id: string) {
    return this.http.delete<void>(`/catalog/services/${id}`);
  }
}

class PackagesApi {
  constructor(private http: HttpClient) {}

  list(params?: PaginationParams & { serviceId?: string }) {
    return this.http.get<PaginatedResponse<Package>>('/catalog/packages', q(params));
  }

  getById(id: string) {
    return this.http.get<Package>(`/catalog/packages/${id}`);
  }

  create(data: Partial<Package>) {
    return this.http.post<Package>('/catalog/packages', data);
  }

  update(id: string, data: Partial<Package>) {
    return this.http.patch<Package>(`/catalog/packages/${id}`, data);
  }

  delete(id: string) {
    return this.http.delete<void>(`/catalog/packages/${id}`);
  }
}

class ClubsApi {
  constructor(private http: HttpClient) {}

  list(params?: PaginationParams & { search?: string; isActive?: boolean }) {
    return this.http.get<PaginatedResponse<Club>>('/clubs', q(params));
  }

  getById(id: string) {
    return this.http.get<Club>(`/clubs/${id}`);
  }

  create(data: CreateClubRequest) {
    return this.http.post<Club>('/clubs', data);
  }

  update(id: string, data: UpdateClubRequest) {
    return this.http.patch<Club>(`/clubs/${id}`, data);
  }

  delete(id: string) {
    return this.http.delete<void>(`/clubs/${id}`);
  }
}

class LicensesApi {
  constructor(private http: HttpClient) {}

  list(params?: PaginationParams) {
    return this.http.get<PaginatedResponse<License>>('/licenses', q(params));
  }

  getById(id: string) {
    return this.http.get<License>(`/licenses/${id}`);
  }

  getMy() {
    return this.http.get<License>('/licenses/my');
  }

  create(data: CreateLicenseRequest) {
    return this.http.post<License>('/licenses', data);
  }

  update(id: string, data: UpdateLicenseRequest) {
    return this.http.patch<License>(`/licenses/${id}`, data);
  }

  renew(id: string) {
    return this.http.post<License>(`/licenses/${id}/renew`);
  }
}

class ReportsApi {
  constructor(private http: HttpClient) {}

  list(params?: PaginationParams & { type?: string; status?: string }) {
    return this.http.get<PaginatedResponse<Report>>('/reports', q(params));
  }

  getById(id: string) {
    return this.http.get<Report>(`/reports/${id}`);
  }

  generate(data: GenerateReportRequest) {
    return this.http.post<Report>('/reports/generate', data);
  }

  download(id: string) {
    return this.http.get<{ url: string }>(`/reports/${id}/download`);
  }
}

class WebhooksApi {
  constructor(private http: HttpClient) {}

  list(params?: PaginationParams) {
    return this.http.get<PaginatedResponse<WebhookSubscription>>('/webhooks', q(params));
  }

  getById(id: string) {
    return this.http.get<WebhookSubscription>(`/webhooks/${id}`);
  }

  create(data: CreateWebhookRequest) {
    return this.http.post<WebhookSubscription>('/webhooks', data);
  }

  update(id: string, data: UpdateWebhookRequest) {
    return this.http.patch<WebhookSubscription>(`/webhooks/${id}`, data);
  }

  delete(id: string) {
    return this.http.delete<void>(`/webhooks/${id}`);
  }

  getLogs(id: string, params?: PaginationParams) {
    return this.http.get<PaginatedResponse<WebhookLog>>(`/webhooks/${id}/logs`, q(params));
  }

  test(id: string) {
    return this.http.post<{ success: boolean }>(`/webhooks/${id}/test`);
  }
}

class IntegrationApi {
  constructor(private http: HttpClient) {}

  getConfig() {
    return this.http.get<IntegrationConfig>('/integration/config');
  }

  upsertConfig(data: UpdateIntegrationConfigRequest) {
    return this.http.put<IntegrationConfig>('/integration/config', data);
  }

  triggerSync(data: TriggerSyncRequest) {
    return this.http.post<SyncLog>('/integration/sync', data);
  }

  getSyncLogs(params?: PaginationParams & { status?: string }) {
    return this.http.get<PaginatedResponse<SyncLog>>('/integration/sync', q(params));
  }
}

class ScheduleApi {
  constructor(private http: HttpClient) {}

  list(params?: PaginationParams & { trainerId?: string; date?: string; status?: string }) {
    return this.http.get<PaginatedResponse<Training>>('/schedule', q(params));
  }

  getById(id: string) {
    return this.http.get<Training>(`/schedule/${id}`);
  }

  create(data: Partial<Training>) {
    return this.http.post<Training>('/schedule', data);
  }

  cancel(id: string, reason?: string) {
    return this.http.post<Training>(`/schedule/${id}/cancel`, { reason });
  }

  reschedule(id: string, data: { startTime: string; endTime: string }) {
    return this.http.post<Training>(`/schedule/${id}/reschedule`, data);
  }
}

class FunnelApi {
  constructor(private http: HttpClient) {}

  list(params?: PaginationParams & { stage?: string; trainerId?: string }) {
    return this.http.get<PaginatedResponse<FunnelEntry>>('/funnel', q(params));
  }

  getById(id: string) {
    return this.http.get<FunnelEntry>(`/funnel/${id}`);
  }

  assign(id: string, trainerId: string) {
    return this.http.post<FunnelEntry>(`/funnel/${id}/assign`, { trainerId });
  }

  transfer(id: string, data: { trainerId: string; departmentId?: string }) {
    return this.http.post<FunnelEntry>(`/funnel/${id}/transfer`, data);
  }

  move(id: string, stage: string) {
    return this.http.post<FunnelEntry>(`/funnel/${id}/move`, { stage });
  }
}

class SalesApi {
  constructor(private http: HttpClient) {}

  list(params?: PaginationParams & { status?: string; clientId?: string }) {
    return this.http.get<PaginatedResponse<Sale>>('/sales', q(params));
  }

  create(data: Partial<Sale>) {
    return this.http.post<Sale>('/sales', data);
  }

  getDebts(params?: PaginationParams) {
    return this.http.get<PaginatedResponse<Sale>>('/sales/debts', q(params));
  }
}

class StatsApi {
  constructor(private http: HttpClient) {}

  summary() {
    return this.http.get<StatsSummary>('/stats/summary');
  }

  funnel() {
    return this.http.get<FunnelStats[]>('/stats/funnel');
  }

  rating(params?: PaginationParams) {
    return this.http.get<PaginatedResponse<RatingEntry>>('/stats/rating', q(params));
  }
}

class NotificationsApi {
  constructor(private http: HttpClient) {}

  list(params?: PaginationParams & { isRead?: boolean }) {
    return this.http.get<PaginatedResponse<Notification>>('/notifications', q(params));
  }

  markRead(id: string) {
    return this.http.patch<Notification>(`/notifications/${id}/read`);
  }

  getSettings() {
    return this.http.get<NotificationSetting[]>('/notifications/settings');
  }

  updateSetting(id: string, data: { enabled: boolean; customText?: string }) {
    return this.http.patch<NotificationSetting>(`/notifications/settings/${id}`, data);
  }
}

class SipApi {
  constructor(private http: HttpClient) {}

  getCalls(params?: PaginationParams) {
    return this.http.get<PaginatedResponse<SipCall>>('/sip/calls', q(params));
  }

  getSettings() {
    return this.http.get<SipSettings>('/sip/settings');
  }

  updateSettings(data: Partial<SipSettings>) {
    return this.http.patch<SipSettings>('/sip/settings', data);
  }
}

class MeteringApi {
  constructor(private http: HttpClient) {}

  getUsage(period?: string) {
    return this.http.get<UsageRecord>('/metering/usage', period ? { period } : undefined);
  }

  checkLimits() {
    return this.http.get<LimitCheck[]>('/metering/limits');
  }
}
