import { Component, AfterContentChecked, Input, ViewChild, OnChanges, OnDestroy } from '@angular/core';
import { CommonModule, DecimalPipe, DatePipe } from '@angular/common';
import { UntypedFormBuilder, UntypedFormGroup, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { Router, RouterLink } from '@angular/router';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatMenuModule } from '@angular/material/menu';
import { MatNativeDateModule } from '@angular/material/core';
import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSort, MatSortModule } from '@angular/material/sort';
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
import { MatSnackBar, MatSnackBarHorizontalPosition, MatSnackBarModule, MatSnackBarVerticalPosition } from '@angular/material/snack-bar';
import { Observable, Subject, Subscription } from 'rxjs';
import { take } from 'rxjs/operators';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';

import { ColumnDefinition, Errors, Jump, JumpList, JumpListConfig, jumpColumns } from 'src/app/core/models';
import { JumpsService, JumpTableService } from 'src/app/core/services';
import { JumpAddDialogComponent, JumpDeleteDialogComponent, JumpEditDialogComponent, JumpViewDialogComponent } from 'src/app/components/jump/dialogs'

@Component({
    standalone: true,
    imports: [
        CommonModule, DecimalPipe, DatePipe, RouterLink, FormsModule, ReactiveFormsModule, NgxSkeletonLoaderModule,
        MatButtonModule, MatCardModule, MatDialogModule,
        MatFormFieldModule, MatIconModule, MatInputModule, MatNativeDateModule, MatMenuModule,
        MatPaginatorModule, MatProgressSpinnerModule, MatSnackBarModule, MatSortModule, MatTableModule,
        JumpAddDialogComponent, JumpDeleteDialogComponent, JumpEditDialogComponent, JumpViewDialogComponent
    ],
    selector: 'huapp-jump-table',
    styleUrls: ['./jump-table.component.scss'],
    templateUrl: './jump-table.component.html'
})
export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChecked {
    private _subject: Subject<void> = new Subject<void>();
    private _jumps: Subscription = new Subscription();
    private _jump: Subscription = new Subscription();
    private _query: JumpListConfig = { type: 'all', filters: {} };
    private _lastjump: Jump = {} as Jump;
    private _currentPage = 1;
    public errors!: Errors;
    public jump: Jump = {} as Jump;
    public jumps!: MatTableDataSource<Jump>;
    public jumpsCount = 0;
    /* public displayedColumns: string[] = [
        'numero', 'date', 'lieu', 'oaci', 'aeronef',
        'imat', 'hauteur', 'voile', 'taille', 'categorie',
        'module', 'participants', 'programme', 'accessoires',
        'zone', 'video', 'actions'
    ];*/
    public displayedColumns: string[] = [
        'numero', 'date', 'lieu', 'aeronef',
        'hauteur', 'voile', 'categorie',
        'participants', 'zone', 'accessoires',
        'video', 'actions'
    ];
    //public displayedColumns: string[] = jumpColumns.map((col) => col.key)
    public columnsSchema: Array<ColumnDefinition> = jumpColumns;
    public loading = false;
    public isSubmitting = false;
    public isDeleting = false;
    public searchForm: UntypedFormGroup;
    public valid: any = {};
    public tableRefresh = false;
    public jumpRefresh = false;

    @ViewChild(MatSort) sort!: MatSort;
    @ViewChild(MatPaginator) paginator!: MatPaginator;

    constructor(
        private router: Router,
        private _jumpsService: JumpsService,
        private _jumpTableService: JumpTableService,
        private dialog: MatDialog,
        private fb: UntypedFormBuilder,
        private snackBar: MatSnackBar
    ) {
        this._resetErrors();
        this.searchForm = this.fb.group({
            //numero: ['', Validators.required]
            numero: ''
        });
    }

    @Input() title = '';
    @Input() limit = 0;
    @Input() showAdd = false;
    @Input() isUser = false;
    @Input()
    set config(config: JumpListConfig) {
        if (config) {
            this._query = config;
            this._currentPage = 1;
        }
    }

    get config(): JumpListConfig {
        return this._query;
    }

    ngOnChanges() {
        this.loading = true;
        this._query = this.config;
        this.runQuery();
        //console.log('ngOnChanges event in jump-table component');
    }

    ngOnDestroy() {
        this._jumps.unsubscribe();
        this._jump.unsubscribe();
    }

    ngAfterContentChecked() {
        if (this.jumpRefresh != this._jumpTableService.jumpRefresh) {
            this.jumpRefresh = this._jumpTableService.jumpRefresh;
            this.runQuery();
            //console.log('table has been refreshed in jump-table component');
        }
    }

    runQuery() {
        const jump$: Observable<Jump> = this._jumpsService.getLastJump();
        this._jump = jump$.subscribe((jump) => {
            this._lastjump = jump;
        });

        if (this.limit) {
            this._query.filters.limit = this.limit;
            this._query.filters.offset = (this.limit * (this._currentPage - 1));
        } else {
            this._query.filters.limit = 0;
            this._query.filters.offset = 0;
        }

        const jumps$: Observable<JumpList> = this._jumpsService.query(this._query);
        this._jumps = jumps$.subscribe({
            next: (data: JumpList) => {
                this.loading = false;
                this.jumps = new MatTableDataSource<Jump>(data.jumps);
                this.jumpsCount = data.jumpsCount;
                this.paginator.length = data.jumpsCount;
                this.jumps.paginator = this.paginator;
                this.jumps.sort = this.sort;
                this._resetErrors();
            },
            error: (err) => {
                this.errors = err;
            }
        });
    }

    deleteJump(slug: string) {
        this.isDeleting = true;
        this._jumpsService.destroy(slug).pipe(take(1))
            .subscribe(() => {
                this.router.navigateByUrl('/');
            });
    }

    openDeleteDialog(jump: Jump): void {
        const dialogRef = this.dialog.open(JumpDeleteDialogComponent, {
            width: '60vw',
            data: jump
        });
        dialogRef.afterClosed().pipe(take(1))
            .subscribe(result => {
                if (result != undefined) {
                    this._onDelete(result.slug);
                }
            });
    }

    openEditDialog(jump: Jump): void {
        const dialogRef = this.dialog.open(JumpEditDialogComponent, {
            width: '70vw',
            data: jump
        });
        dialogRef.afterClosed().pipe(take(1))
        .subscribe(result => {
            if (result != undefined) {
                this._onEdit(result);
            }
        });
    }

    openViewDialog(jump: Jump): void {
        const dialogRef = this.dialog.open(JumpViewDialogComponent, {
            width: '60vw',
            data: jump
        });
    }

    getErrorMessage() {
        if (this.searchForm.controls['numero'].errors !== null) {
            return 'Vous devez indiquer une valeur';
        }
        return '';
    }

    submitForm() {
        if (this.searchForm.valid) {
            this._query.filters.numero = this.searchForm.value.numero;
            this._resetErrors();
            this.runQuery();
        }
    }

    private _onDelete(slug: string): void {
        try {
            this.isDeleting = true;
            this._jumpsService.destroy(slug)
            .pipe(take(1))
            .subscribe({
                next: () => {
                    this._resetErrors();
                    this._openSnackBar(`Le saut a été supprimé !`, 'OK');
                    this.runQuery();
                    this.tableRefresh = !this.tableRefresh;
                    this._jumpTableService.updateTableRefresh(this.tableRefresh);
                },
                error: (err) => {
                    this.errors = err;
                }
            });
        } catch (error) {
            console.error(error);
        }
    }

    private _onEdit(jump: Jump): void {
        try {
            this.isSubmitting = true;
            this._jumpsService.update(jump)
            .pipe(take(1))
            .subscribe({
                next: (jump) => {
                    this._resetErrors();
                    this._openSnackBar(`Le saut n°${jump.numero} a été mis à jour !`, 'OK');
                    this.runQuery();
                    this.tableRefresh = !this.tableRefresh;
                    this._jumpTableService.updateTableRefresh(this.tableRefresh);
                },
                error: (err) => {
                    this.errors = err;
                    this.isSubmitting = false;
                }
            });
        } catch (error) {
            console.error(error);
        }
    }

    private _openSnackBar(content: string, title: string) {
        this.snackBar.open(content, title, {
            horizontalPosition: <MatSnackBarHorizontalPosition>'end',
            verticalPosition: <MatSnackBarVerticalPosition>'bottom',
            duration: 4000,
        });
    }

    private _resetErrors(): void {
        this.errors = { errors: {} };
    }

    inputHandler(e: any, id: number, key: string) {
        if (!this.valid[id]) {
            this.valid[id] = {}
        }
        this.valid[id][key] = e.target.validity.valid
    }

    disableSubmit(id: number) {
        if (this.valid[id]) {
            return Object.values(this.valid[id]).some((item) => item === false)
        }
        return false
    }

    /*
    isAllSelected() {
        return this.jumps.data.every((item) => item.isSelected)
    }

    isAnySelected() {
        return this.jumps.data.some((item) => item.isSelected)
    }

    selectAll(event: any) {
        this.jumps.data = this.jumps.data.map((item) => ({
            ...item,
            isSelected: event.checked,
        }))
    }
    */

}
