// src/client/shared/api/repositories/EquipmentRepository.ts
// Equipment Repository for local IT, security, and other equipment management with Zod validation

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

/**
 * Access Port interface
 */
export const accessPortSchema = z.object({
  serviceName: z.string().min(1, 'Service name is required'),
  port: z.number().int().min(1).max(65535).optional(),
  username: z.string().optional(),
  password: z.string().optional(),
});

export type AccessPort = z.infer<typeof accessPortSchema>;

/**
 * Helper to transform empty strings and undefined to null
 */
const emptyToNull = z.union([
  z.string().optional(),
  z.literal(''),
  z.null(),
]).transform(val => val === '' || val === undefined || val === null ? null : val);

/**
 * Local IT Response (DTO) - синхронизировано с бэкендом
 */
export const localITResponseSchema = z.object({
  id: z.string(),
  description: z.string(),
  manufacturer: z.string().nullable(),
  model: z.string().nullable(),
  networkAddress: z.string().nullable(),
  macAddress: z.string().nullable(),
  accessPorts: z.array(accessPortSchema).nullable(),
  username: z.string().nullable(),
  password: z.string().nullable(),
  location: z.string(),
  comment: z.string().nullable(),
  createdAt: z.string(),
  updatedAt: z.string(),
  archivedAt: z.string().nullable(),
});

export type LocalITResponse = z.infer<typeof localITResponseSchema>;

export const localITListResponseSchema = z.array(localITResponseSchema);

// Create Local IT Request
export const createLocalITRequestSchema = z.object({
  description: z.string().min(1, 'Description is required'),
  manufacturer: z.string().min(1, 'Manufacturer is required'),
  model: z.string().min(1, 'Model is required'),
  networkAddress: z.string().optional(),
  macAddress: z.string().optional(),
  accessPorts: z.array(accessPortSchema).optional(),
  username: z.string().optional(),
  password: z.string().optional(),
  location: z.string().min(1, 'Location is required'),
  comment: z.string().optional(),
});

export type CreateLocalITRequest = z.infer<typeof createLocalITRequestSchema>;

// Update Local IT Request
export const updateLocalITRequestSchema = z.object({
  description: z.string().min(1).optional(),
  manufacturer: z.string().min(1).optional(),
  model: z.string().min(1).optional(),
  networkAddress: z.string().optional(),
  macAddress: z.string().optional(),
  accessPorts: z.array(accessPortSchema).optional(),
  username: z.string().optional(),
  password: z.string().optional(),
  location: z.string().min(1).optional(),
  comment: z.string().optional(),
});

export type UpdateLocalITRequest = z.infer<typeof updateLocalITRequestSchema>;

/**
 * Local Security Response (DTO) - синхронизировано с бэкендом
 */
export const localSecurityResponseSchema = z.object({
  id: z.string(),
  type: z.string(),
  manufacturer: z.string().nullable(),
  model: z.string().nullable(),
  location: z.string(),
  comment: z.string().nullable(),
  createdAt: z.string(),
  updatedAt: z.string(),
  archivedAt: z.string().nullable(),
});

export type LocalSecurityResponse = z.infer<typeof localSecurityResponseSchema>;

export const localSecurityListResponseSchema = z.array(localSecurityResponseSchema);

// Create Local Security Request
export const createLocalSecurityRequestSchema = z.object({
  type: z.string().min(1, 'Type is required'),
  manufacturer: z.string().min(1, 'Manufacturer is required'),
  model: z.string().min(1, 'Model is required'),
  location: z.string().min(1, 'Location is required'),
  comment: z.string().optional(),
});

export type CreateLocalSecurityRequest = z.infer<typeof createLocalSecurityRequestSchema>;

// Update Local Security Request
export const updateLocalSecurityRequestSchema = z.object({
  type: z.string().min(1).optional(),
  manufacturer: z.string().min(1).optional(),
  model: z.string().min(1).optional(),
  location: z.string().min(1).optional(),
  comment: z.string().optional(),
});

export type UpdateLocalSecurityRequest = z.infer<typeof updateLocalSecurityRequestSchema>;

/**
 * Other Equipment Response (DTO) - синхронизировано с бэкендом
 */
export const otherEquipmentResponseSchema = z.object({
  id: z.string(),
  description: z.string(),
  type: z.string().nullable(),
  manufacturer: z.string().nullable(),
  model: z.string().nullable(),
  location: z.string(),
  comment: z.string().nullable(),
  createdAt: z.string(),
  updatedAt: z.string(),
  archivedAt: z.string().nullable(),
});

export type OtherEquipmentResponse = z.infer<typeof otherEquipmentResponseSchema>;

export const otherEquipmentListResponseSchema = z.array(otherEquipmentResponseSchema);

// Create Other Equipment Request
export const createOtherEquipmentRequestSchema = z.object({
  description: z.string().min(1, 'Description is required'),
  type: z.string().optional(),
  manufacturer: z.string().optional(),
  model: z.string().optional(),
  location: z.string().min(1, 'Location is required'),
  comment: z.string().optional(),
});

export type CreateOtherEquipmentRequest = z.infer<typeof createOtherEquipmentRequestSchema>;

// Update Other Equipment Request
export const updateOtherEquipmentRequestSchema = z.object({
  description: z.string().min(1).optional(),
  type: z.string().optional(),
  manufacturer: z.string().optional(),
  model: z.string().optional(),
  location: z.string().min(1).optional(),
  comment: z.string().optional(),
});

export type UpdateOtherEquipmentRequest = z.infer<typeof updateOtherEquipmentRequestSchema>;

// Simple success response schema for mutation operations
export const successResponseSchema = z.object({
  success: z.boolean(),
  message: z.string(),
});

export type SuccessResponse = z.infer<typeof successResponseSchema>;

/**
 * Local IT Repository
 */
export class LocalITRepository extends BaseRepository {
  protected basePath = '/local-it';

  async getAll(): Promise<LocalITResponse[]> {
    const config: RequestConfig<LocalITResponse[]> = {
      schema: localITListResponseSchema,
    };
    return this.get<LocalITResponse[]>('', config);
  }

  async getById(id: string): Promise<LocalITResponse> {
    const config: RequestConfig<LocalITResponse> = {
      schema: localITResponseSchema,
    };
    return this.get<LocalITResponse>(`/${id}`, config);
  }

  async create(data: CreateLocalITRequest): Promise<LocalITResponse> {
    const config: RequestConfig<LocalITResponse> = {
      schema: localITResponseSchema,
    };
    const result = await this.post<CreateLocalITRequest, LocalITResponse>('', data, config);
    this.invalidateCache();
    return result;
  }

  async update(id: string, data: UpdateLocalITRequest): Promise<LocalITResponse> {
    const config: RequestConfig<LocalITResponse> = {
      schema: localITResponseSchema,
    };
    const result = await this.put<UpdateLocalITRequest, LocalITResponse>(`/${id}`, data, config);
    this.invalidateCache();
    return result;
  }

  async archive(id: string): Promise<SuccessResponse> {
    const config: RequestConfig<SuccessResponse> = {
      schema: successResponseSchema,
    };
    const result = await super.delete<SuccessResponse>(`/${id}`, config);
    this.invalidateCache();
    return result;
  }
}

/**
 * Local Security Repository
 */
export class LocalSecurityRepository extends BaseRepository {
  protected basePath = '/local-security';

  async getAll(): Promise<LocalSecurityResponse[]> {
    const config: RequestConfig<LocalSecurityResponse[]> = {
      schema: localSecurityListResponseSchema,
    };
    return this.get<LocalSecurityResponse[]>('', config);
  }

  async getById(id: string): Promise<LocalSecurityResponse> {
    const config: RequestConfig<LocalSecurityResponse> = {
      schema: localSecurityResponseSchema,
    };
    return this.get<LocalSecurityResponse>(`/${id}`, config);
  }

  async create(data: CreateLocalSecurityRequest): Promise<LocalSecurityResponse> {
    const config: RequestConfig<LocalSecurityResponse> = {
      schema: localSecurityResponseSchema,
    };
    const result = await this.post<CreateLocalSecurityRequest, LocalSecurityResponse>('', data, config);
    this.invalidateCache();
    return result;
  }

  async update(id: string, data: UpdateLocalSecurityRequest): Promise<LocalSecurityResponse> {
    const config: RequestConfig<LocalSecurityResponse> = {
      schema: localSecurityResponseSchema,
    };
    const result = await this.put<UpdateLocalSecurityRequest, LocalSecurityResponse>(`/${id}`, data, config);
    this.invalidateCache();
    return result;
  }

  async archive(id: string): Promise<SuccessResponse> {
    const config: RequestConfig<SuccessResponse> = {
      schema: successResponseSchema,
    };
    const result = await super.delete<SuccessResponse>(`/${id}`, config);
    this.invalidateCache();
    return result;
  }
}

/**
 * Other Equipment Repository
 */
export class OtherEquipmentRepository extends BaseRepository {
  protected basePath = '/other-equipment';

  async getAll(): Promise<OtherEquipmentResponse[]> {
    const config: RequestConfig<OtherEquipmentResponse[]> = {
      schema: otherEquipmentListResponseSchema,
    };
    return this.get<OtherEquipmentResponse[]>('', config);
  }

  async getById(id: string): Promise<OtherEquipmentResponse> {
    const config: RequestConfig<OtherEquipmentResponse> = {
      schema: otherEquipmentResponseSchema,
    };
    return this.get<OtherEquipmentResponse>(`/${id}`, config);
  }

  async create(data: CreateOtherEquipmentRequest): Promise<OtherEquipmentResponse> {
    const config: RequestConfig<OtherEquipmentResponse> = {
      schema: otherEquipmentResponseSchema,
    };
    const result = await this.post<CreateOtherEquipmentRequest, OtherEquipmentResponse>('', data, config);
    this.invalidateCache();
    return result;
  }

  async update(id: string, data: UpdateOtherEquipmentRequest): Promise<OtherEquipmentResponse> {
    const config: RequestConfig<OtherEquipmentResponse> = {
      schema: otherEquipmentResponseSchema,
    };
    const result = await this.put<UpdateOtherEquipmentRequest, OtherEquipmentResponse>(`/${id}`, data, config);
    this.invalidateCache();
    return result;
  }

  async archive(id: string): Promise<SuccessResponse> {
    const config: RequestConfig<SuccessResponse> = {
      schema: successResponseSchema,
    };
    const result = await super.delete<SuccessResponse>(`/${id}`, config);
    this.invalidateCache();
    return result;
  }
}

/**
 * Синглтон экземпляры репозиториев
 */
export const localITRepository = new LocalITRepository();
export const localSecurityRepository = new LocalSecurityRepository();
export const otherEquipmentRepository = new OtherEquipmentRepository();
