import { HttpClient, HttpParams } from '@angular/common/http'
import { Injectable, inject } from '@angular/core'
import { RestExtractor, RestPagination, RestService } from '@app/core'
import { Event } from '@peertube/peertube-models'
import { SortMeta } from 'primeng/api'
import { Observable } from 'rxjs'
import { catchError } from 'rxjs/operators'
import { environment } from 'src/environments/environment'

export interface EventCreate {
  title: string
  description?: string
  startTime: string
  endTime: string
  liveUrl?: string
  state?: 'active' | 'disabled'
}

export interface EventUpdate {
  title?: string
  description?: string
  startTime?: string
  endTime?: string
  liveUrl?: string
  state?: 'active' | 'disabled'
}

export interface EventState {
  state: 'active' | 'disabled'
}

@Injectable({
  providedIn: 'root'
})
export class EventApiService {
  private authHttp = inject(HttpClient)
  private restExtractor = inject(RestExtractor)
  private restService = inject(RestService)

  private static BASE_EVENTS_URL = environment.apiUrl + '/api/v1/events'

  // List public events (for public event listing)
  // Supports filtering by state via query params (e.g., ?state=active)
  listPublicEvents (options?: {
    pagination?: RestPagination
    sort?: SortMeta
    state?: 'active' | 'disabled'
  }): Observable<any> {
    let params = new HttpParams()

    if (options?.pagination) {
      params = this.restService.addRestGetParams(params, options.pagination)
    }

    if (options?.sort) {
      params = this.restService.addRestGetParams(params, undefined, options.sort)
    }

    if (options?.state) {
      params = params.set('state', options.state)
    }

    return this.authHttp
      .get<any>(EventApiService.BASE_EVENTS_URL, { params })
      .pipe(catchError(err => this.restExtractor.handleError(err)))
  }

  // Get a single public event
  getPublicEvent (eventId: number): Observable<Event> {
    return this.authHttp
      .get<Event>(`${EventApiService.BASE_EVENTS_URL}/${eventId}`)
      .pipe(catchError(err => this.restExtractor.handleError(err)))
  }

  // List events for a specific channel (admin/owner only)
  listChannelEvents (channelId: number, options?: {
    pagination?: RestPagination
    sort?: SortMeta
  }): Observable<any> {
    let params = new HttpParams()

    if (options?.pagination) {
      params = this.restService.addRestGetParams(params, options.pagination)
    }

    if (options?.sort) {
      params = this.restService.addRestGetParams(params, undefined, options.sort)
    }

    const url = `${EventApiService.BASE_EVENTS_URL}/${channelId}/events`
    return this.authHttp
      .get<any>(url, { params })
      .pipe(catchError(err => this.restExtractor.handleError(err)))
  }

  // Create a new event
  createEvent (channelId: number, event: EventCreate | FormData): Observable<Event> {
    const url = `${EventApiService.BASE_EVENTS_URL}/${channelId}/events`
    return this.authHttp
      .post<Event>(url, event)
      .pipe(catchError(err => this.restExtractor.handleError(err)))
  }

  // Update an existing event
  updateEvent (channelId: number, eventId: number, event: EventUpdate | FormData): Observable<Event> {
    const url = `${EventApiService.BASE_EVENTS_URL}/${channelId}/events/${eventId}`
    return this.authHttp
      .put<Event>(url, event)
      .pipe(catchError(err => this.restExtractor.handleError(err)))
  }

  // Delete an event
  deleteEvent (channelId: number, eventId: number): Observable<void> {
    const url = `${EventApiService.BASE_EVENTS_URL}/${channelId}/events/${eventId}`
    return this.authHttp
      .delete<void>(url)
      .pipe(catchError(err => this.restExtractor.handleError(err)))
  }

  // Update event state
  updateEventState (channelId: number, eventId: number, state: EventState): Observable<void> {
    const url = `${EventApiService.BASE_EVENTS_URL}/${channelId}/events/${eventId}/state`
    return this.authHttp
      .patch<void>(url, state)
      .pipe(catchError(err => this.restExtractor.handleError(err)))
  }
}
