import {Component, inject, OnDestroy, OnInit} from '@angular/core';
import {ConfirmationService, MessageService} from 'primeng/api';
import {KoboService, KoboSyncSettings} from './kobo.service';
import {FormsModule} from '@angular/forms';
import {Button} from 'primeng/button';
import {InputText} from 'primeng/inputtext';
import {ConfirmDialog} from 'primeng/confirmdialog';
import {UserService} from '../../../user-management/user.service';
import {Subject} from 'rxjs';
import {debounceTime, filter, take, takeUntil} from 'rxjs/operators';
import {ToggleSwitch} from 'primeng/toggleswitch';
import {Slider} from 'primeng/slider';
import {Divider} from 'primeng/divider';
import {AppSettingsService} from '../../../../../shared/service/app-settings.service';
import {SettingsHelperService} from '../../../../../shared/service/settings-helper.service';
import {AppSettingKey, KoboSettings} from '../../../../../shared/model/app-settings.model';
import {ShelfService} from '../../../../book/service/shelf.service';
import {ExternalDocLinkComponent} from '../../../../../shared/components/external-doc-link/external-doc-link.component';
import {ToastModule} from 'primeng/toast';
import {TranslocoDirective, TranslocoService} from '@jsverse/transloco';

@Component({
  selector: 'app-kobo-sync-setting-component',
  standalone: true,
  templateUrl: './kobo-sync-settings-component.html',
  styleUrl: './kobo-sync-settings-component.scss',
  imports: [FormsModule, Button, InputText, ConfirmDialog, ToggleSwitch, Slider, Divider, ExternalDocLinkComponent, ToastModule, TranslocoDirective],
  providers: [MessageService, ConfirmationService]
})
export class KoboSyncSettingsComponent implements OnInit, OnDestroy {
  private koboService = inject(KoboService);
  private messageService = inject(MessageService);
  private confirmationService = inject(ConfirmationService);
  protected userService = inject(UserService);
  protected appSettingsService = inject(AppSettingsService);
  protected settingsHelperService = inject(SettingsHelperService);
  private shelfService = inject(ShelfService);
  private readonly t = inject(TranslocoService);

  private readonly destroy$ = new Subject<void>();
  private readonly sliderChange$ = new Subject<void>();
  private readonly progressThresholdChange$ = new Subject<void>();

  hasKoboTokenPermission = false;
  isAdmin = false;
  credentialsSaved = false;
  showToken = false;

  koboSettings: KoboSettings = {
    convertToKepub: false,
    conversionLimitInMb: 100,
    convertCbxToEpub: false,
    conversionImageCompressionPercentage: 85,
    conversionLimitInMbForCbx: 100,
    forceEnableHyphenation: false
  };

  koboSyncSettings: KoboSyncSettings = {
    token: '',
    syncEnabled: false,
    progressMarkAsReadingThreshold: 1,
    progressMarkAsFinishedThreshold: 99,
    autoAddToShelf: true,
    twoWayProgressSync: false
  }

  ngOnInit() {
    this.setupSliderDebouncing();
    this.setupUserStateSubscription();
  }

  private setupSliderDebouncing() {
    this.sliderChange$.pipe(
      debounceTime(500),
      takeUntil(this.destroy$)
    ).subscribe(() => {
      this.saveSettings();
    });

    this.progressThresholdChange$.pipe(
      debounceTime(500),
      takeUntil(this.destroy$)
    ).subscribe(() => {
      this.updateKoboSettings(this.t.translate('settingsDevice.kobo.progressUpdated'));
    });
  }

  private setupUserStateSubscription() {
    let prevHasKoboTokenPermission = false;
    let prevIsAdmin = false;
    this.userService.userState$.pipe(
      filter(userState => !!userState?.user && userState.loaded),
      takeUntil(this.destroy$)
    ).subscribe(userState => {
      const currHasKoboTokenPermission = (userState.user?.permissions.canSyncKobo) ?? false;
      const currIsAdmin = userState.user?.permissions.admin ?? false;

      if (currHasKoboTokenPermission && !prevHasKoboTokenPermission) {
        this.hasKoboTokenPermission = true;
        this.loadKoboUserSettings();
      } else {
        this.hasKoboTokenPermission = currHasKoboTokenPermission;
      }

      if (currIsAdmin && !prevIsAdmin) {
        this.isAdmin = true;
        this.loadKoboAdminSettings();
      } else {
        this.isAdmin = currIsAdmin;
      }

      prevHasKoboTokenPermission = currHasKoboTokenPermission;
      prevIsAdmin = currIsAdmin;
    });
  }

  private loadKoboUserSettings() {
    this.koboService.getUser().subscribe({
      next: (settings: KoboSyncSettings) => {
        this.koboSyncSettings.token = settings.token;
        this.koboSyncSettings.syncEnabled = settings.syncEnabled;
        this.koboSyncSettings.progressMarkAsReadingThreshold = settings.progressMarkAsReadingThreshold ?? 1;
        this.koboSyncSettings.progressMarkAsFinishedThreshold = settings.progressMarkAsFinishedThreshold ?? 99;
        this.koboSyncSettings.autoAddToShelf = settings.autoAddToShelf ?? false;
        this.koboSyncSettings.twoWayProgressSync = settings.twoWayProgressSync ?? false;
        this.credentialsSaved = !!settings.token;
      },
      error: () => {
        this.messageService.add({severity: 'error', summary: this.t.translate('common.error'), detail: this.t.translate('settingsDevice.kobo.loadError')});
      }
    });
  }

  private loadKoboAdminSettings() {
    this.appSettingsService.appSettings$
      .pipe(
        filter(settings => settings != null),
        take(1),
      )
      .subscribe(settings => {
        this.koboSettings.convertToKepub = settings?.koboSettings?.convertToKepub ?? true;
        this.koboSettings.conversionLimitInMb = settings?.koboSettings?.conversionLimitInMb ?? 100;
        this.koboSettings.convertCbxToEpub = settings?.koboSettings?.convertCbxToEpub ?? false;
        this.koboSettings.conversionLimitInMbForCbx = settings?.koboSettings?.conversionLimitInMbForCbx ?? 100;
        this.koboSettings.forceEnableHyphenation = settings?.koboSettings?.forceEnableHyphenation ?? false;
        this.koboSettings.conversionImageCompressionPercentage = settings?.koboSettings?.conversionImageCompressionPercentage ?? 85;
      });
  }

  copyText(text: string, label: string = 'Text') {
    if (!text) {
      return;
    }
    navigator.clipboard.writeText(text).then(() => {
      this.messageService.add({
        severity: 'success',
        summary: this.t.translate('settingsDevice.copied'),
        detail: this.t.translate('settingsDevice.copiedDetail', {label})
      });
    }).catch(err => {
      console.error('Copy failed', err);
      this.messageService.add({
        severity: 'error',
        summary: this.t.translate('settingsDevice.copyFailed'),
        detail: this.t.translate('settingsDevice.copyFailedDetail', {label})
      });
    });
  }

  toggleShowToken() {
    this.showToken = !this.showToken;
  }


  confirmRegenerateToken() {
    this.confirmationService.confirm({
      message: this.t.translate('settingsDevice.kobo.confirmRegenerate'),
      header: this.t.translate('settingsDevice.kobo.confirmRegenerateHeader'),
      icon: 'pi pi-exclamation-triangle',
      accept: () => this.regenerateToken()
    });
  }

  private regenerateToken() {
    this.koboService.createOrUpdateToken().subscribe({
      next: (settings) => {
        this.koboSyncSettings.token = settings.token;
        this.credentialsSaved = true;
        this.messageService.add({severity: 'success', summary: this.t.translate('settingsDevice.kobo.tokenRegenerated'), detail: this.t.translate('settingsDevice.kobo.tokenRegeneratedDetail')});
      },
      error: () => {
        this.messageService.add({severity: 'error', summary: this.t.translate('common.error'), detail: this.t.translate('settingsDevice.kobo.tokenRegenerateError')});
      }
    });
  }

  onToggleChange() {
    this.saveSettings();
  }

  onSliderChange() {
    this.sliderChange$.next();
  }

  onSyncToggle() {
    if (!this.koboSyncSettings.syncEnabled) {
      this.confirmationService.confirm({
        message: this.t.translate('settingsDevice.kobo.confirmDisable'),
        header: this.t.translate('settingsDevice.kobo.confirmDisableHeader'),
        icon: 'pi pi-exclamation-triangle',
        accept: () => this.updateKoboSettings(this.t.translate('settingsDevice.kobo.syncDisabled')),
        reject: () => {
          this.koboSyncSettings.syncEnabled = true;
        }
      });
    } else {
      this.updateKoboSettings(this.t.translate('settingsDevice.kobo.syncEnabled'));
    }
  }

  onProgressThresholdsChange() {
    this.progressThresholdChange$.next();
  }

  onAutoAddToggle() {
    const message = this.koboSyncSettings.autoAddToShelf
      ? this.t.translate('settingsDevice.kobo.autoAddEnabled')
      : this.t.translate('settingsDevice.kobo.autoAddDisabled');
    this.updateKoboSettings(message);
  }

  onTwoWaySyncToggle() {
    const message = this.koboSyncSettings.twoWayProgressSync
      ? this.t.translate('settingsDevice.kobo.twoWaySyncEnabled')
      : this.t.translate('settingsDevice.kobo.twoWaySyncDisabled');
    this.updateKoboSettings(message);
  }

  private updateKoboSettings(successMessage: string) {
    this.koboService.updateSettings(this.koboSyncSettings).subscribe({
      next: () => {
        this.messageService.add({
          severity: 'success',
          summary: this.t.translate('settingsDevice.kobo.settingsUpdated'),
          detail: successMessage
        });
        this.shelfService.reloadShelves();
      },
      error: () => {
        this.messageService.add({
          severity: 'error',
          summary: this.t.translate('common.error'),
          detail: this.t.translate('settingsDevice.kobo.settingsUpdateError')
        });
      }
    });
  }

  saveSettings() {
    this.settingsHelperService.saveSetting(AppSettingKey.KOBO_SETTINGS, this.koboSettings)
      .subscribe({
        next: () => {
          this.messageService.add({
            severity: 'success',
            summary: this.t.translate('settingsDevice.kobo.settingsSaved'),
            detail: this.t.translate('settingsDevice.kobo.settingsSuccess')
          });
        },
        error: () => {
          this.messageService.add({
            severity: 'error',
            summary: this.t.translate('settingsDevice.kobo.saveFailed'),
            detail: this.t.translate('settingsDevice.kobo.saveError')
          });
        }
      });
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }
}
