import { trigger, state, style, animate, transition } from '@angular/animations';
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { ActivatedRoute } from '@angular/router';
import { DatePipe, DecimalPipe } from '@angular/common';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatDividerModule } from '@angular/material/divider';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';

import { Observable, Subscription } from 'rxjs';

import { MenuItems } from '@components/shared';
import {
    BarsChartComponent,
    CircleChartComponent,
    LineChartComponent,
    LineAreaChartComponent,
} from '@components/shared/helpers-chart';
import { UtilitiesService } from '@services';
import { Jump, JumpByCategorie, JumpByDate, JumpByDateByModule, JumpByModule, JumpsPageData, JumpYears } from '@models';

@Component({
    selector: 'app-jumps',
    imports: [
        DatePipe,
        DecimalPipe,
        MatButtonModule,
        MatCardModule,
        MatDividerModule,
        MatExpansionModule,
        MatIconModule,
        MatMenuModule,
        BarsChartComponent,
        CircleChartComponent,
        LineChartComponent,
        LineAreaChartComponent,
    ],
    templateUrl: './jumps.component.html',
    styleUrl: './jumps.component.scss',
    animations: [
        trigger('flyInOut', [
            state('in', style({ transform: 'translateX(0)' })),
            transition('void => *', [style({ transform: 'translateX(-100%)' }), animate(200)]),
            transition('* => void', [style({ transform: 'translateX(100%)' }), animate(200)]),
        ]),
    ],
})
export class JumpsComponent implements OnInit, OnDestroy {
    private route = inject(ActivatedRoute);
    private _utilitiesService = inject(UtilitiesService);
    menuItems = inject(MenuItems);

    private _data: Subscription = new Subscription();
    private _jumpsByCategorie: Array<JumpByCategorie> = [];
    private _jumpsByModule: Array<JumpByModule> = [];
    private _jumpsByDate: Array<JumpByDate> = [];
    public lastJump: Jump = {} as Jump;
    public title: string = 'Sauts';
    public subtitle: string = 'Nombre total de sauts par mois';
    public displayCharts = false;
    public destroyRef = inject(DestroyRef);
    public min = 0;
    public max = 0;
    public grandAvg = 0;
    public grandAvgLastYears = 0;
    public grandTotal = 0;
    public seriesHeader: string[] = [];
    public seriesName: string[] = [];
    public seriesRow: Array<Array<number>> = [];
    public seriesColor: {
        backgroundColor: string[];
        borderColor: string[];
    } = {
        backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
        borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
    };
    public seriesTypesHeader: string[] = [];
    public seriesTypesName: string[] = [];
    public seriesTypesRow: Array<Array<number>> = [];
    public seriesTypesRowCumulated: Array<Array<number>> = [];
    public seriesTypesColor: {
        backgroundColor: string[];
        borderColor: string[];
    } = {
        backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'pastels'),
        borderColor: this._utilitiesService.getSeriesColors(1, 'pastels'),
    };
    public seriesColorClass: string[] = this._utilitiesService.getChartColors();
    public seriesRowTotal: number[] = [];
    public seriesRowAvg: number[] = [];
    public seriesRowAvgLastYears: number[] = [];
    public seriesColTotal: number[] = [];
    public seriesColTotalClosed: number[] = [];
    public seriesColTotalLastYears: number[] = [];

    ngOnInit() {
        const data$: Observable<{ pageData: JumpsPageData }> = this.route.data as Observable<{
            pageData: JumpsPageData;
        }>;
        this._data = data$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { pageData: JumpsPageData }) => {
            const pageData: JumpsPageData = data.pageData;
            this.lastJump = pageData.lastjump;
            const currentYear: number = new Date().getFullYear();
            const types: Array<string> = ['FF', 'Solo', 'VR', 'Wingsuit'];
            const verticals: Array<string> = ['Chutas', 'Head Up', 'Head Down'];
            const others: Array<string> = ['Track', 'Trace'];
            const modules: Array<string> = [...verticals, ...others];
            const minoration = 2; // -2 pour ne pas compter la première année
            this.min = pageData.jumpsByYears[0].year;
            this.max = pageData.jumpsByYears[pageData.jumpsByYears.length - 1].year;

            this.seriesHeader = this._utilitiesService.getMonthsList();
            const values: Array<number> = this.seriesHeader.map(() => 0);
            this.seriesColTotal = [...values];
            this.seriesColTotalClosed = [...values];
            this.seriesColTotalLastYears = [...values];
            this.seriesName = pageData.jumpsByYears.map((row: JumpYears) => {
                this.seriesRow.push([...values]);
                return row.year.toString();
            });

            this._jumpsByDate = pageData.jumpsByDate.map((row: JumpByDate) => {
                this.seriesRow[row.year - this.min][row.month - 1] = row.count;
                this.seriesColTotal[row.month - 1] += row.count;
                if (row.year < currentYear) {
                    this.seriesColTotalClosed[row.month - 1] += row.count;
                }
                if (row.year >= currentYear - 3 && row.year < currentYear) {
                    this.seriesColTotalLastYears[row.month - 1] += row.count;
                }
                return row;
            });
            this.seriesRow.forEach((row: number[]) => {
                const total = row.reduce((partialSum, a) => partialSum + a, 0);
                this.seriesRowTotal.push(total);
            });
            this.seriesColTotalClosed.forEach((row: number) => {
                const value: number = row / (this.seriesName.length - minoration);
                this.seriesRowAvg.push(parseInt(value.toFixed(0)));
            });
            this.seriesColTotalLastYears.forEach((row: number) => {
                const value: number = row / 3; // Les 3 dernières années
                this.seriesRowAvgLastYears.push(parseInt(value.toFixed(0)));
            });
            this.grandAvg = this.seriesRowAvg.reduce((partialSum, accumulated) => partialSum + accumulated, 0);
            this.grandAvgLastYears = this.seriesRowAvgLastYears.reduce(
                (partialSum, accumulated) => partialSum + accumulated,
                0,
            );
            this.grandTotal = this.seriesColTotal.reduce((partialSum, accumulated) => partialSum + accumulated, 0);

            pageData.jumpsByCategory.forEach((row: JumpByCategorie) => {
                if (types.indexOf(row.categorie) !== -1) {
                    this._jumpsByCategorie.push(row);
                }
            });

            //const focus: Array<string> = ['FF', 'Solo']; // ['FF']
            let verticalCount: number = 0;
            let otherCount: number = 0;
            pageData.jumpsByModule.forEach((row: JumpByModule) => {
                //if (focus.indexOf(row.categorie) !== -1 && modules.indexOf(row.module) !== -1) {
                if (modules.indexOf(row.module) !== -1) {
                    if (verticals.indexOf(row.module) !== -1) {
                        verticalCount += row.count;
                    } else {
                        otherCount += row.count;
                    }
                }
            });
            if (verticalCount > 0) {
                const row: JumpByModule = {
                    categorie: 'FF',
                    module: 'Vertical',
                    count: verticalCount,
                };
                this._jumpsByModule.push(row);
            }
            if (otherCount > 0) {
                const row: JumpByModule = {
                    categorie: 'FF',
                    module: 'Track/Trace',
                    count: otherCount,
                };
                this._jumpsByModule.push(row);
            }

            for (let year = 0; year < pageData.jumpsByYears.length; year++) {
                for (let index = 0; index < 12; index++) {
                    const month: string = index + 1 < 10 ? `0${index + 1}` : `${index + 1}`;
                    this.seriesTypesHeader.push(`${month}-${pageData.jumpsByYears[year].year}`);
                }
            }
            const emptyValues: Array<number> = this.seriesTypesHeader.map(() => 0);
            this.seriesTypesName = types;
            this.seriesTypesName.forEach(() => {
                this.seriesTypesRow.push([...emptyValues]);
            });
            pageData.jumpsByDateByModule.forEach((row: JumpByDateByModule) => {
                const indexOf: number = this.seriesTypesName.indexOf(row.categorie);
                if (indexOf !== -1) {
                    this.seriesTypesRow[indexOf][(row.year - this.min) * 12 + row.month - 1] += row.count;
                }
            });
            this.seriesTypesRowCumulated = this.seriesTypesRow.map((row: Array<number>) => {
                let accumulated: number = 0;
                return row.map((value: number) => {
                    accumulated += value;
                    return accumulated;
                });
            });
            this.seriesTypesHeader = this.seriesTypesHeader.slice(
                pageData.jumpsByDateByModule[0].month + 1,
                -pageData.jumpsByDateByModule[pageData.jumpsByDateByModule.length - 1].month,
            );
            this.seriesTypesRow = this.seriesTypesRow.map((row: Array<number>) => {
                return row.slice(
                    pageData.jumpsByDateByModule[0].month + 1,
                    -pageData.jumpsByDateByModule[pageData.jumpsByDateByModule.length - 1].month,
                );
            });
            this.seriesTypesRowCumulated = this.seriesTypesRowCumulated.map((row: Array<number>) => {
                return row.slice(
                    pageData.jumpsByDateByModule[0].month + 1,
                    -pageData.jumpsByDateByModule[pageData.jumpsByDateByModule.length - 1].month,
                );
            });
            /*
            console.log('this.min', this.min);
            console.log('this.max', this.max);
            console.log('this.lastJump', this.lastJump);
            console.log('this.seriesHeader', this.seriesHeader);
            console.log('this.seriesName', this.seriesName);
            console.log('this.seriesRow', this.seriesRow);
            console.log('this.seriesRowTotal', this.seriesRowTotal);
            console.log('this.seriesRowAvg', this.seriesRowAvg);
            console.log('this.seriesRowAvgLastYears', this.seriesRowAvgLastYears);
            console.log('this._jumpsByCategorie', this._jumpsByCategorie);
            console.log('this._jumpsByModule', this._jumpsByModule);
            console.log('this.seriesTypesHeader', this.seriesTypesHeader);
            console.log('this.seriesTypesName', this.seriesTypesName);
            console.log('this.seriesTypesRow', this.seriesTypesRow);
            console.log('this.seriesTypesRowCumulated', this.seriesTypesRowCumulated);
            */
            this.displayCharts = true;
        });
    }

    ngOnDestroy() {
        this._data.unsubscribe();
    }

    public getCategories(): Array<JumpByCategorie> {
        return this._jumpsByCategorie;
    }

    public getModules(): Array<JumpByModule> {
        return this._jumpsByModule;
    }

    public getModuleColor(index: number): number {
        return this._jumpsByCategorie.length + index;
    }
}
