// src/client/shared/api/repositories/RoomsRepository.ts
// Rooms Repository for room management operations with Zod validation

import { z } from 'zod';
import { BaseRepository, type RepositoryConfig } from '../BaseRepository';
import type { RequestConfig } from '../api.client';

/**
 * Схемы для валидации запросов/ответов (синхронизированы с бэкендом)
 */

// Room type enum
export const roomTypeEnum = z.enum(['апарт', 'номер']);

// Room ID validation: буква A-Z и число 1-99
export const roomIdSchema = z.string()
  .regex(/^[A-Z][1-9][0-9]?$/, 'Invalid room ID. Format: буква A-Z + число 1-99 (например, A1, B12)');

// Room Response (DTO)
export const roomResponseSchema = z.object({
  id: z.string(),
  type: roomTypeEnum,
  hasHood: z.boolean(),
  beds: z.number(),
  armchair: z.boolean(),
  airCond: z.boolean(),
  isRepairing: z.boolean(),
  repairReason: z.string().nullable(),
  comment: z.string().nullable(),
  createdAt: z.string(),
  updatedAt: z.string(),
});

export type RoomResponse = z.infer<typeof roomResponseSchema>;

// Room List Response
export const roomListResponseSchema = z.array(roomResponseSchema);

// Create Room Request
export const createRoomRequestSchema = z.object({
  id: roomIdSchema,
  type: roomTypeEnum,
  hasHood: z.boolean().optional().default(false),
  beds: z.number().int().min(1).max(10).optional().default(2),
  armchair: z.boolean().optional().default(false),
  airCond: z.boolean().optional().default(false),
  isRepairing: z.boolean().optional().default(false),
  repairReason: z.string().optional(),
  comment: z.string().optional(),
}).refine((data) => {
  // Если тип не 'апарт', то hasHood должен быть false
  if (data.type !== 'апарт' && data.hasHood) {
    return false;
  }
  return true;
}, {
  message: 'Вытяжка доступна только для типа "апарт"',
  path: ['hasHood'],
});

export type CreateRoomRequest = z.infer<typeof createRoomRequestSchema>;

// Update Room Request
export const updateRoomRequestSchema = z.object({
  id: roomIdSchema.optional(),
  type: roomTypeEnum.optional(),
  hasHood: z.boolean().optional(),
  beds: z.number().int().min(1).max(10).optional(),
  armchair: z.boolean().optional(),
  airCond: z.boolean().optional(),
  isRepairing: z.boolean().optional(),
  repairReason: z.string().optional(),
  comment: z.string().optional(),
}).refine((data) => {
  // Если тип меняется на не 'апарт', то hasHood должен быть false
  if (data.type && data.type !== 'апарт' && data.hasHood) {
    return false;
  }
  // Если тип не 'апарт' (новый или старый), то hasHood должен быть false
  if (data.hasHood && data.type === undefined) {
    // В этом случае нужно проверить текущий тип в сервисе
    return true; // Валидация пройдет, но сервис проверит
  }
  return true;
}, {
  message: 'Вытяжка доступна только для типа "апарт"',
  path: ['hasHood'],
});

export type UpdateRoomRequest = z.infer<typeof updateRoomRequestSchema>;

// Delete Room Response
export const deleteRoomResponseSchema = z.object({
  success: z.boolean(),
  message: z.string(),
});

export type DeleteRoomResponse = z.infer<typeof deleteRoomResponseSchema>;

/**
 * Rooms Repository
 */
export class RoomsRepository extends BaseRepository {
  protected basePath = '/rooms';

  /**
   * Получает все комнаты (с кэшированием)
   */
  async getAll(): Promise<RoomResponse[]> {
    const config: RequestConfig<RoomResponse[]> = {
      schema: roomListResponseSchema,
    };

    return this.get<RoomResponse[]>('', config);
  }

  /**
   * Получает комнату по ID (с кэшированием)
   */
  async getById(id: string): Promise<RoomResponse> {
    const config: RequestConfig<RoomResponse> = {
      schema: roomResponseSchema,
    };

    return this.get<RoomResponse>(`/${id}`, config);
  }

  /**
   * Создает новую комнату
   */
  async create(data: CreateRoomRequest): Promise<RoomResponse> {
    const config: RequestConfig<RoomResponse> = {
      schema: roomResponseSchema,
    };

    // Инвалидируем кэш после создания
    const result = await this.post<CreateRoomRequest, RoomResponse>('', data, config);
    this.invalidateCache();
    return result;
  }

  /**
   * Обновляет комнату
   */
  async update(id: string, data: UpdateRoomRequest): Promise<RoomResponse> {
    const config: RequestConfig<RoomResponse> = {
      schema: roomResponseSchema,
    };

    // Инвалидируем кэш после обновления
    const result = await this.put<UpdateRoomRequest, RoomResponse>(`/${id}`, data, config);
    this.invalidateCache();
    return result;
  }

  /**
   * Удаляет комнату
   */
  async deleteRoom(id: string): Promise<DeleteRoomResponse> {
    const config: RequestConfig<DeleteRoomResponse> = {
      schema: deleteRoomResponseSchema,
    };

    // Инвалидируем кэш после удаления
    const result = await super.delete<DeleteRoomResponse>(`/${id}`, config);
    this.invalidateCache();
    return result;
  }
}

/**
 * Синглтон экземпляр RoomsRepository
 */
export const roomsRepository = new RoomsRepository();
