import { Component, inject } from '@angular/core'
import { CommonModule } from '@angular/common'
import { FormsModule } from '@angular/forms'
import { ActivatedRoute, Router } from '@angular/router'
import { getCountryNames } from './country-list.util'
import { EventRegistrationPayload, EventRegistrationService } from './register-event.service'
import { Notifier } from '@app/core'
import { PeerTubeProblemDocument } from '@peertube/peertube-models'

type RegistrationField = 'firstName' | 'lastName' | 'email' | 'number' | 'companyName' | 'jobTitle' | 'country'
type InvalidParamError = { msg?: string, path?: string }
type ProblemDocumentWithInvalidParams = PeerTubeProblemDocument & {
  'invalid-params'?: Record<string, InvalidParamError>
  data?: {
    'invalid-params'?: Record<string, InvalidParamError>
  }
}

@Component({
  selector: 'app-register-event',
  standalone: true,
  imports: [CommonModule, FormsModule],
  templateUrl: './register-event.component.html',
  styleUrls: ['./register-event.component.scss']
})
export class RegisterEventComponent {
  private registrationService = inject(EventRegistrationService)
  private route = inject(ActivatedRoute)
  private router = inject(Router)
  private notifier = inject(Notifier)

  registerUser = {
    firstName: '',
    lastName: '',
    email: '',
    number: '',
    companyName: '',
    jobTitle: ''
  }

  dropdownOpen = false
  selectedCountry = ''
  countries = getCountryNames()

  isSubmitting = false
  fieldErrors: Partial<Record<RegistrationField, string>> = {}
  submitError = ''

  toggleDropdown () {
    this.dropdownOpen = !this.dropdownOpen
  }

  selectCountry (country: string, event: Event) {
    event.stopPropagation()
    this.selectedCountry = country
    this.dropdownOpen = false
    this.clearFieldError('country')
  }

  onRegistrationSubmit () {
    if (this.isSubmitting) return

    this.clearErrors()

    const eventId = Number(this.route.parent?.snapshot.params['eventId'])

    if (!eventId) {
      this.notifier.error('Invalid event ID')
      return
    }

    if (this.hasClientValidationErrors()) {
      return
    }

    const payload: EventRegistrationPayload = {
      firstName: this.registerUser.firstName,
      lastName: this.registerUser.lastName,
      email: this.registerUser.email,
      phone: this.registerUser.number,
      companyName: this.registerUser.companyName,
      jobTitle: this.registerUser.jobTitle,
      country: this.selectedCountry
    }

    this.isSubmitting = true

    this.registrationService.registerUser(eventId, payload).subscribe({
      next: () => {
        this.notifier.success('Successfully registered!')
        this.router.navigate(['/events-hub', eventId])
      },
      error: err => {
        console.error('Registration failed', err)
        this.handleSubmissionError(err)
        this.isSubmitting = false
      },
      complete: () => {
        this.isSubmitting = false
      }
    })
  }

  cancel () {
    this.router.navigate(['../'], {
      relativeTo: this.route,
      replaceUrl: true
    })
  }

  clearFieldError (field: RegistrationField) {
    delete this.fieldErrors[field]

    if (this.submitError && Object.keys(this.fieldErrors).length === 0) {
      this.submitError = ''
    }
  }

  private clearErrors () {
    this.fieldErrors = {}
    this.submitError = ''
  }

  private hasClientValidationErrors () {
    if (!this.registerUser.firstName) this.fieldErrors.firstName = 'First name is required'
    if (!this.registerUser.lastName) this.fieldErrors.lastName = 'Last name is required'
    if (!this.registerUser.email) this.fieldErrors.email = 'Email is required'
    if (!this.registerUser.number) this.fieldErrors.number = 'Phone is required'
    if (!this.registerUser.companyName) this.fieldErrors.companyName = 'Company name is required'
    if (!this.registerUser.jobTitle) this.fieldErrors.jobTitle = 'Job title is required'
    if (!this.selectedCountry) this.fieldErrors.country = 'Country is required'

    return Object.keys(this.fieldErrors).length !== 0
  }

  private handleSubmissionError (err: { body?: ProblemDocumentWithInvalidParams, message?: string }) {
    const invalidParams = this.extractInvalidParams(err.body)

    if (invalidParams) {
      const fieldMap: Record<string, RegistrationField> = {
        firstName: 'firstName',
        lastName: 'lastName',
        email: 'email',
        phone: 'number',
        companyName: 'companyName',
        jobTitle: 'jobTitle',
        country: 'country'
      }

      for (const [ serverField, fieldError ] of Object.entries(invalidParams)) {
        const clientField = fieldMap[fieldError?.path || serverField]
        if (!clientField) continue

        this.fieldErrors[clientField] = fieldError?.msg || 'Invalid value'
      }

      if (Object.keys(this.fieldErrors).length !== 0) return
    }

    this.submitError = err.body?.detail || err.message || 'Registration failed. Please try again.'
    this.notifier.error(this.submitError)
  }

  private extractInvalidParams (body?: ProblemDocumentWithInvalidParams) {
    return body?.['invalid-params'] || body?.data?.['invalid-params']
  }
}
