import { Component, computed, effect, inject, signal } from '@angular/core';
import { RouterLink } from '@angular/router';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatDialog } from '@angular/material/dialog';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSnackBar } from '@angular/material/snack-bar';
import { toString as qrToString } from 'qrcode';
import { AuthStore } from '../../../../core/auth/auth-store';
import { PublicAccessApi } from '../../../../core/team/public-access-api';
import { TeamStore } from '../../../../core/team/team-store';
import { PublicAccessStatus } from '../../../../models/public-access.model';
import { ConfirmDialog, ConfirmDialogData } from '../../../../shared/confirm-dialog/confirm-dialog';

@Component({
  selector: 'app-public-access',
  imports: [
    RouterLink,
    MatButtonModule,
    MatCardModule,
    MatFormFieldModule,
    MatIconModule,
    MatInputModule,
    MatProgressSpinnerModule,
  ],
  templateUrl: './public-access.html',
  styleUrl: './public-access.scss',
})
export class PublicAccess {
  private readonly api = inject(PublicAccessApi);
  private readonly authStore = inject(AuthStore);
  private readonly dialog = inject(MatDialog);
  private readonly snackBar = inject(MatSnackBar);
  private readonly teamStore = inject(TeamStore);
  private loadedTeamId: number | null = null;

  protected readonly team = this.teamStore.team;
  protected readonly status = signal<PublicAccessStatus | null>(null);
  protected readonly loading = signal(true);
  protected readonly saving = signal(false);
  protected readonly loadFailed = signal(false);
  protected readonly qrDataUrl = signal('');
  protected readonly publicUrl = computed(() => {
    const status = this.status();
    return status?.enabled && status.token ? `${location.origin}/t/${status.token}` : '';
  });
  protected readonly canManage = computed(() => {
    const user = this.authStore.currentUser();
    if (user?.role?.id === 1) return true;
    return (
      this.team()?.players?.some(
        (player) =>
          player.active && player.user?.id === user?.id && (player.teamRole?.id ?? 0) >= 3,
      ) ?? false
    );
  });

  constructor() {
    effect(() => {
      const teamId = this.team()?.id;
      if (teamId && teamId !== this.loadedTeamId) {
        this.loadedTeamId = teamId;
        this.load(teamId);
      }
    });
  }

  protected toggleAccess(): void {
    const teamId = this.team()?.id;
    const status = this.status();
    if (!this.canManage() || !teamId || !status || this.saving()) return;
    this.saveStatus(this.api.setEnabled(teamId, !status.enabled));
  }

  protected rotateLink(): void {
    const teamId = this.team()?.id;
    if (!this.canManage() || !teamId || this.saving()) return;
    const data: ConfirmDialogData = {
      title: 'Öffentlichen Link erneuern',
      message: 'Der bisherige Link wird sofort ungültig. Wirklich einen neuen Link erzeugen?',
      confirmLabel: 'Link erneuern',
    };
    this.dialog
      .open(ConfirmDialog, { data })
      .afterClosed()
      .subscribe((confirmed) => {
        if (confirmed) this.saveStatus(this.api.rotate(teamId));
      });
  }

  protected async copyLink(): Promise<void> {
    const url = this.publicUrl();
    if (!url) return;
    try {
      await navigator.clipboard.writeText(url);
      this.snackBar.open('Öffentlicher Link wurde kopiert.', undefined, { duration: 4000 });
    } catch {
      this.snackBar.open('Link konnte nicht kopiert werden.', undefined, { duration: 5000 });
    }
  }

  protected async shareLink(): Promise<void> {
    const url = this.publicUrl();
    if (!url) return;
    if (navigator.share) {
      try {
        await navigator.share({ title: this.team()?.name ?? 'TeamWallet', url });
        return;
      } catch (error) {
        if (error instanceof DOMException && error.name === 'AbortError') return;
      }
    }
    await this.copyLink();
  }

  protected retry(): void {
    const teamId = this.team()?.id;
    if (teamId) this.load(teamId);
  }

  private load(teamId: number): void {
    this.loading.set(true);
    this.loadFailed.set(false);
    this.api.getStatus(teamId).subscribe({
      next: (status) => {
        this.loading.set(false);
        this.acceptStatus(status);
      },
      error: () => {
        this.loading.set(false);
        this.loadFailed.set(true);
      },
    });
  }

  private saveStatus(request: ReturnType<PublicAccessApi['setEnabled']>): void {
    this.saving.set(true);
    request.subscribe({
      next: (status) => {
        this.saving.set(false);
        this.acceptStatus(status);
      },
      error: () => {
        this.saving.set(false);
        this.snackBar.open('Freigabe konnte nicht aktualisiert werden.', undefined, {
          duration: 5000,
        });
      },
    });
  }

  private acceptStatus(status: PublicAccessStatus): void {
    this.status.set(status);
    void this.generateQrCode();
  }

  private async generateQrCode(): Promise<void> {
    const url = this.publicUrl();
    if (!url) {
      this.qrDataUrl.set('');
      return;
    }
    try {
      const svg = await qrToString(url, { type: 'svg', width: 240, margin: 1 });
      this.qrDataUrl.set(`data:image/svg+xml;charset=UTF-8,${encodeURIComponent(svg)}`);
    } catch {
      this.qrDataUrl.set('');
    }
  }
}
