import {
    AfterContentChecked,
    Component,
    EventEmitter,
    Input,
    Output,
    OnChanges,
    OnDestroy,
    ViewChild,
    inject,
} from '@angular/core';
import { CommonModule, DatePipe } from '@angular/common';
import { UntypedFormBuilder, UntypedFormGroup, 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, MatPaginatorIntl, MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressBarModule } from '@angular/material/progress-bar';
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, Subscription } from 'rxjs';
import { take } from 'rxjs/operators';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';

import { FrenchPaginator } from '@components/shared/french-paginator.component';
import {
    ColumnDefinition,
    Errors,
    Jump,
    JumpByDay,
    JumpFile,
    JumpFileType,
    JumpList,
    JumpListConfig,
    jumpColumns,
} from '@models';
import { JumpsService, JumpTableService } from '@services';
import {
    JumpDeleteDialogComponent,
    JumpEditDialogComponent,
    JumpViewDialogComponent,
} from '@components/logbook/dialogs';

@Component({
    imports: [
        CommonModule,
        DatePipe,
        RouterLink,
        FormsModule,
        ReactiveFormsModule,
        NgxSkeletonLoaderModule,
        MatButtonModule,
        MatCardModule,
        MatDialogModule,
        MatFormFieldModule,
        MatIconModule,
        MatInputModule,
        MatNativeDateModule,
        MatMenuModule,
        MatPaginatorModule,
        MatProgressBarModule,
        MatProgressSpinnerModule,
        MatSnackBarModule,
        MatSortModule,
        MatTableModule,
    ],
    selector: 'app-jump-table',
    styleUrl: './jump-table.component.scss',
    templateUrl: './jump-table.component.html',
    providers: [{ provide: MatPaginatorIntl, useClass: FrenchPaginator }],
})
export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChecked {
    private router = inject(Router);
    private _jumpsService = inject(JumpsService);
    private _jumpTableService = inject(JumpTableService);
    private dialog = inject(MatDialog);
    private fb = inject(UntypedFormBuilder);
    private snackBar = inject(MatSnackBar);

    private _jumps: Subscription = new Subscription();
    private _subscriptions: Array<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', 'files', 'actions'
    ];*/
    public displayedColumns: string[] = [
        'numero',
        'date',
        'lieu',
        'aeronef',
        'hauteur',
        'voile',
        'categorie',
        'participants',
        'zone',
        'accessoires',
        'files',
        'actions',
    ];
    //public displayedColumns: string[] = jumpColumns.map((col) => col.key)
    public columnsSchema: Array<ColumnDefinition> = jumpColumns;
    public searchForm: UntypedFormGroup;
    public loading = false;
    public isSubmitting = false;
    public isDeleting = false;
    public tableRefresh = false;
    public jumpRefresh = false;
    //public valid: any = {};

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

    constructor() {
        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;
    }
    @Output() countChange: EventEmitter<number> = new EventEmitter();

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

    ngOnDestroy() {
        this._jumps.unsubscribe();
        this._subscriptions.forEach((subscription) => {
            subscription.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;
        }
        /*
        this._query.filters.numeroRangeStart = 1;
        this._query.filters.numeroRangeEnd = 0;
        this._query.filters.tailleRangeStart = 135;
        this._query.filters.tailleRangeEnd = 230;
        this._query.filters.participantsRangeStart = 1;
        this._query.filters.participantsRangeEnd = 10;
        this._query.filters.hauteurRangeStart = 0;
        this._query.filters.hauteurRangeEnd = 8000;
        */

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

    linkSkydiverIdJumps() {
        const config: JumpListConfig = { type: 'all', filters: {} } as JumpListConfig;
        config.filters.limit = 200;
        config.filters.offset = 0;
        config.filters.dateRangeStart = '2024-01-01 00:00:00';
        //const year = new Date().getFullYear();
        //config.filters.dateRangeEnd = `${year}-12-31 23:59:59`;
        config.filters.dateRangeEnd = '2024-12-31 23:59:59';
        //console.log(config.filters);
        const subscription: Subscription = this._jumpsService
            .getAllByDay(config)
            .pipe(take(1))
            .subscribe({
                next: (days) => {
                    this._resetErrors();
                    //console.log('getAllByDay : ', days);
                    days.forEach((day) => {
                        this.loadSkydiverIdJumps(day, config);
                    });
                },
                error: (err) => {
                    this.errors = err;
                },
            });
        this._subscriptions.push(subscription);
    }

    loadSkydiverIdJumps(day: JumpByDay, config: JumpListConfig) {
        config.filters.dateRangeStart = `${day.jumps[0].date!.substring(0, 10)} 00:00:00`;
        config.filters.dateRangeEnd = `${day.jumps[0].date!.substring(0, 10)} 23:59:59`;
        const subscription: Subscription = this._jumpsService
            .getAllFromSkydiverIdApi(config)
            .pipe(take(1))
            .subscribe({
                next: (data) => {
                    if (data.items.length) {
                        const diff = day.count - data.items.length;
                        if (diff < 0) {
                            console.error(
                                `${diff} ${diff > 1 ? 'données' : 'donnée'} altimètre de trop le ${day.jumps[0].date!.substring(0, 10)}`,
                            );
                        } else {
                            if (diff > 0) {
                                console.error(
                                    `${diff}/${day.count} ${diff > 1 ? 'données altimètre manquantes' : 'donnée altimètre manquante'} le ${day.jumps[0].date!.substring(0, 10)}`,
                                    day.jumps,
                                    data.items,
                                );
                            }
                            console.log(
                                `${day.count} ${day.count > 1 ? 'sauts' : 'saut'} le ${data.items[0].date!.substring(0, 10)}`,
                                day.jumps.sort((a, b) => b.numero! - a.numero!),
                                data.items,
                            );
                            data.items.map((jump, index) => {
                                const file: JumpFile = {
                                    name: jump.name,
                                    path: `/Volumes/Storage/Skydive/X2_Logs/${day.jumps[index].date!.substring(0, 4)}/`,
                                    type: JumpFileType.CSV,
                                } as JumpFile;
                                this._subscriptions.push(
                                    this._jumpsService
                                        .saveX2Data(day.jumps[index].slug!, file, jump)
                                        .pipe(take(1))
                                        .subscribe({
                                            next: (jump) => {
                                                this._resetErrors();
                                                console.log(
                                                    `Le fichier ${file.name} a été ajouté au saut n°${jump.numero} !`,
                                                    'OK',
                                                );
                                            },
                                            error: (err) => {
                                                this.errors = err;
                                            },
                                        }),
                                );
                                return jump;
                            });
                        }
                        //console.log(`${day.count} ${day.count > 1 ? 'sauts' : 'saut'} le ${day.jumps[0].date!.substring(0, 10)}`);
                        //console.log(`${data.items.length} ${data.items.length > 1 ? 'sauts' : 'saut'} le ${data.items[0].date!.substring(0, 10)}`, data);
                    } else {
                        console.info('Aucune données altimètre pour le ', day.jumps[0].date!.substring(0, 10));
                    }
                },
                error: (err) => {
                    console.error('getAllFromSkydiverIdApi error');
                    this.errors = err;
                },
            });
        this._subscriptions.push(subscription);
    }

    updateJumps(jumps: Array<Jump>) {
        jumps.map((jump) => {
            jump.files = [];
            if (jump.dossier !== '' && jump.video !== '') {
                const file: JumpFile = {
                    name: jump.video!,
                    path: jump.dossier!,
                    type: JumpFileType.VIDEO,
                } as JumpFile;
                this._subscriptions.push(
                    this._jumpsService
                        .saveFile(jump.slug, file)
                        .pipe(take(1))
                        .subscribe({
                            next: (file) => {
                                this._resetErrors();
                                jump.files.push(file);
                                //console.log(`Le fichier ${file.name} a été ajouté au saut n°${jump.numero} !`, 'OK');
                            },
                            error: (err) => {
                                this.errors = err;
                            },
                        }),
                );
            }
            return jump;
        });
    }

    getKmlJumpFiles(jumps: Array<Jump>) {
        jumps.map((jump) => {
            if (jump.x2data !== null) {
                //console.log(`Le fichier ${jump.x2data.name} existe pour le saut n°${jump.numero} !`, `https://skydiver.id/api/jump/${jump.x2data.id}/kml`);
                const file: JumpFile = {
                    name: jump.x2data.name.substring(0, -4) + '.kml',
                    path: `/X2_Kmls/${jump.date.substring(0, 4)}/`,
                    type: JumpFileType.KML,
                } as JumpFile;
                this._subscriptions.push(
                    this._jumpsService
                        .saveKml(jump.slug, file)
                        .pipe(take(1))
                        .subscribe({
                            next: (file) => {
                                this._resetErrors();
                                console.log(
                                    `Le fichier ${file.path}${file.name} a été ajouté au saut n°${jump.numero} !`,
                                    'OK',
                                );
                            },
                            error: (err) => {
                                this.errors = err;
                            },
                        }),
                );
            }
            return jump;
        });
    }

    deleteJump(slug: string) {
        this.isDeleting = true;
        this._subscriptions.push(
            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,
        });
        this._subscriptions.push(
            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,
        });
        this._subscriptions.push(
            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,
        });
        dialogRef.afterClosed();
    }

    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._subscriptions.push(
                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._subscriptions.push(
                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: {} };
    }

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

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

    /*
    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,
        }))
    }
    */
}
