/**
 * Webhook Entity
 *
 * Represents a webhook subscription for external integrations
 */

export enum WebhookEvent {
  BOOKING_CREATED = 'booking.created',
  BOOKING_UPDATED = 'booking.updated',
  BOOKING_CANCELLED = 'booking.cancelled',
  BOOKING_CONFIRMED = 'booking.confirmed',
  RATE_QUOTE_CREATED = 'rate_quote.created',
  DOCUMENT_UPLOADED = 'document.uploaded',
  ORGANIZATION_UPDATED = 'organization.updated',
  USER_CREATED = 'user.created',
}

export enum WebhookStatus {
  ACTIVE = 'active',
  INACTIVE = 'inactive',
  FAILED = 'failed',
}

interface WebhookProps {
  id: string;
  organizationId: string;
  url: string;
  events: WebhookEvent[];
  secret: string;
  status: WebhookStatus;
  description?: string;
  headers?: Record<string, string>;
  retryCount: number;
  lastTriggeredAt?: Date;
  failureCount: number;
  createdAt: Date;
  updatedAt: Date;
}

export class Webhook {
  private constructor(private readonly props: WebhookProps) {}

  static create(
    props: Omit<
      WebhookProps,
      'id' | 'status' | 'retryCount' | 'failureCount' | 'createdAt' | 'updatedAt'
    > & { id: string }
  ): Webhook {
    return new Webhook({
      ...props,
      status: WebhookStatus.ACTIVE,
      retryCount: 0,
      failureCount: 0,
      createdAt: new Date(),
      updatedAt: new Date(),
    });
  }

  static fromPersistence(props: WebhookProps): Webhook {
    return new Webhook(props);
  }

  get id(): string {
    return this.props.id;
  }

  get organizationId(): string {
    return this.props.organizationId;
  }

  get url(): string {
    return this.props.url;
  }

  get events(): WebhookEvent[] {
    return this.props.events;
  }

  get secret(): string {
    return this.props.secret;
  }

  get status(): WebhookStatus {
    return this.props.status;
  }

  get description(): string | undefined {
    return this.props.description;
  }

  get headers(): Record<string, string> | undefined {
    return this.props.headers;
  }

  get retryCount(): number {
    return this.props.retryCount;
  }

  get lastTriggeredAt(): Date | undefined {
    return this.props.lastTriggeredAt;
  }

  get failureCount(): number {
    return this.props.failureCount;
  }

  get createdAt(): Date {
    return this.props.createdAt;
  }

  get updatedAt(): Date {
    return this.props.updatedAt;
  }

  /**
   * Check if webhook is active
   */
  isActive(): boolean {
    return this.props.status === WebhookStatus.ACTIVE;
  }

  /**
   * Check if webhook subscribes to an event
   */
  subscribesToEvent(event: WebhookEvent): boolean {
    return this.props.events.includes(event);
  }

  /**
   * Activate webhook
   */
  activate(): Webhook {
    return new Webhook({
      ...this.props,
      status: WebhookStatus.ACTIVE,
      updatedAt: new Date(),
    });
  }

  /**
   * Deactivate webhook
   */
  deactivate(): Webhook {
    return new Webhook({
      ...this.props,
      status: WebhookStatus.INACTIVE,
      updatedAt: new Date(),
    });
  }

  /**
   * Mark webhook as failed
   */
  markAsFailed(): Webhook {
    return new Webhook({
      ...this.props,
      status: WebhookStatus.FAILED,
      failureCount: this.props.failureCount + 1,
      updatedAt: new Date(),
    });
  }

  /**
   * Record successful trigger
   */
  recordTrigger(): Webhook {
    return new Webhook({
      ...this.props,
      lastTriggeredAt: new Date(),
      retryCount: this.props.retryCount + 1,
      failureCount: 0, // Reset failure count on success
      updatedAt: new Date(),
    });
  }

  /**
   * Update webhook
   */
  update(updates: {
    url?: string;
    events?: WebhookEvent[];
    description?: string;
    headers?: Record<string, string>;
  }): Webhook {
    return new Webhook({
      ...this.props,
      ...updates,
      updatedAt: new Date(),
    });
  }

  /**
   * Convert to plain object
   */
  toObject(): WebhookProps {
    return { ...this.props };
  }
}
