import { Component, Injectable, inject, Input, OnInit } from '@angular/core';
import { DatePipe, DecimalPipe } from '@angular/common';
import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
import { STEPPER_GLOBAL_OPTIONS } from '@angular/cdk/stepper';
import { MatCardModule } from '@angular/material/card';
import { MatButtonModule } from '@angular/material/button';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatDividerModule } from '@angular/material/divider';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatStepperIntl, MatStepperModule } from '@angular/material/stepper';
import { MatTooltipModule } from '@angular/material/tooltip';

import { HWGuildRaid, HWGuildRaidAttacker, HWGuildRaidAttackers, HWGuildRaidStage, HWMember } from '@models';
import { HWDataService } from '@services';

@Injectable()
export class StepperIntl extends MatStepperIntl {
    // the default optional label text, if unspecified is "Optional"
    override optionalLabel = 'Optional Label';
}
@Component({
    selector: 'app-guildraids-log',
    providers: [
        {
            provide: STEPPER_GLOBAL_OPTIONS,
            useValue: { displayDefaultIndicatorType: false },
        },
    ],
    imports: [
        DatePipe,
        DecimalPipe,
        FormsModule,
        ReactiveFormsModule,
        MatButtonModule,
        MatCardModule,
        MatDatepickerModule,
        MatDividerModule,
        MatFormFieldModule,
        MatIconModule,
        MatInputModule,
        MatTooltipModule,
        MatStepperModule,
    ],
    templateUrl: './guildraids-log.component.html',
    styleUrl: './guildraids-log.component.scss',
})
export class GuildraidsLogComponent implements OnInit {
    private fb = inject(FormBuilder);
    private _dataService = inject(HWDataService);

    public now: Date;
    public raidsForm: FormGroup;
    public guildMembers: HWMember[] = [];
    public title = 'Guild Raids';
    public subtitle = 'Log';
    public minVarPct = 3;
    private _matStepperIntl = inject(MatStepperIntl);
    private _guildRaids: HWGuildRaid[] = [];
    private _raidStages: HWGuildRaidStage[] = [
        { num: 1, name: 'Stage 1', maxPower: 350000, duration: 8, startTime: 0, endTime: 0 },
        { num: 2, name: 'Stage 2', maxPower: 550000, duration: 8, startTime: 0, endTime: 0 },
        { num: 3, name: 'Stage 3', maxPower: 0, duration: 0, startTime: 0, endTime: 0 },
    ];

    @Input() set members(value: HWMember[]) {
        this.guildMembers = value;
    }

    constructor() {
        this.now = new Date();
        const raidsDate = new Date();
        const startHour = 4;
        raidsDate.setHours(startHour, 0, 0, 0);
        const controlsConfig = {
            num: 1,
            name: 'Stage 1',
            maxPower: 350,
            duration: 8,
            startTime: [raidsDate.getTime(), Validators.required],
            endTime: 0,
        };
        this.raidsForm = this.fb.group(controlsConfig);
    }

    _setStagesTime(startTime: number): void {
        const raidsDate = new Date(startTime);
        const startHour = 4;
        raidsDate.setHours(startHour, 0, 0, 0);
        this._raidStages[0].startTime = raidsDate.getTime();

        raidsDate.setHours(startHour + this._raidStages[0].duration, 0, 0, 0);
        this._raidStages[0].endTime = raidsDate.getTime();
        this._raidStages[1].startTime = raidsDate.getTime();

        raidsDate.setHours(startHour + this._raidStages[0].duration + this._raidStages[1].duration, 0, 0, 0);
        this._raidStages[1].endTime = raidsDate.getTime();
        this._raidStages[2].startTime = raidsDate.getTime();

        raidsDate.setHours(startHour, 0, 0, 0);
        raidsDate.setDate(raidsDate.getDate() + 4);
        this._raidStages[2].endTime = raidsDate.getTime();
        this._matStepperIntl.optionalLabel = this._raidStages[1].duration.toString() + 'h';
    }

    ngOnInit() {
        this.guildMembers.map((data) => {
            data.raids = [];
            data.raidsInfo = { variationAvg: 0, variationSum: 0 };
            return data;
        });

        this._dataService.guildRaids$.subscribe({
            next: (guildRaids) => {
                for (const member of Object.entries(guildRaids)) {
                    const index = this.guildMembers.findIndex((item) => item.id === member[0]);
                    const memberRaids: HWGuildRaid[] = [];
                    if (index !== -1) {
                        // eslint-disable-next-line @typescript-eslint/no-explicit-any
                        for (const data of Object.entries(member[1] as Record<string, any>)) {
                            const raid: HWGuildRaid = {} as HWGuildRaid;
                            Object.assign(raid, data[1]);
                            const startTime: number = parseInt(raid.startTime) * 1000;
                            if (this._guildRaids.length === 0) {
                                this._setStagesTime(startTime);
                            }
                            const raidsDate = new Date(startTime);
                            if (raidsDate.getTime() > this._raidStages[1].endTime) {
                                raid.stage = this._raidStages[2];
                            } else if (raidsDate.getTime() > this._raidStages[0].endTime) {
                                raid.stage = this._raidStages[1];
                            } else {
                                raid.stage = this._raidStages[0];
                            }
                            raid.damage = data[1].result.damage;
                            raid.level = data[1].result.level;
                            raid.userName = this.guildMembers[index].name;
                            const attackers: HWGuildRaidAttackers = {} as HWGuildRaidAttackers;
                            Object.assign(attackers, data[1].attackers);
                            raid.attackers = [];
                            raid.power = 0;
                            for (const item of Object.entries(attackers)) {
                                const attacker: HWGuildRaidAttacker = {
                                    id: item[1].id,
                                    power: item[1].power,
                                    type: item[1].type,
                                } as HWGuildRaidAttacker;
                                raid.power += attacker.power;
                                raid.attackers.push(attacker);
                            }
                            let percent = 0;
                            if (raid.stage.maxPower > 0) {
                                percent = (raid.power / raid.stage.maxPower - 1) * 100;
                            }
                            let color = 'default';
                            let value = 0;
                            if (raid.stage.maxPower > 0) {
                                if (percent > 15) {
                                    color = 'raspberry';
                                } else if (percent > 10) {
                                    color = 'red';
                                } else if (percent > 5) {
                                    color = 'orange';
                                }
                                value = raid.power - raid.stage.maxPower;
                            }
                            raid.variation = { value, percent, color };
                            raid.tooltip = Math.floor(raid.variation.value / 1000) + 'k';
                            memberRaids.push(raid);
                            this._guildRaids.push(raid);
                        }
                        this.guildMembers[index].raids = memberRaids;
                        const varSum = memberRaids.reduce((acc, cur) => acc + cur.variation.percent, 0);
                        this.guildMembers[index].raidsInfo = {
                            variationAvg: varSum / memberRaids.length,
                            variationSum: varSum,
                        };
                    }
                }
                this._guildRaids.sort((a, b) => (a.startTime < b.startTime ? -1 : 1));
                this.guildMembers.sort((a, b) => (a.raidsInfo.variationAvg > b.raidsInfo.variationAvg ? -1 : 1));
            },
            error: (err) => console.error(err),
        });
    }

    public getMembers(): HWMember[] {
        //return this.guildMembers;
        return this.minVarPct
            ? this.guildMembers.filter((member) => member.raidsInfo.variationAvg >= this.minVarPct === true)
            : this.guildMembers;
    }

    public getRaidsLog(stageNum: number): HWGuildRaid[] {
        return this._guildRaids.filter((raid) => (raid.stage.num === stageNum) === true);
    }

    public getStagesTime(stageNum: number): HWGuildRaidStage {
        return this._raidStages[stageNum];
    }

    public onDateChange(): void {
        const timestamp: number = Date.parse(this.raidsForm.controls['startTime'].value);
        if (isNaN(timestamp) == false) {
            this._setStagesTime(timestamp);
        }
    }

    submitForm(): void {}
}
