import { Component, Input, OnInit, inject } from '@angular/core';
import { combineLatest } from 'rxjs';
import { DatePipe, DecimalPipe } from '@angular/common';
import { MatCardModule } from '@angular/material/card';
import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule } from '@angular/material/icon';

import { HWActivityStat, HWGuildClan, HWGuildData, HWMember, HWMemberStat, HWWeekStat } from '@models/herowars';
import { HWDataService, UtilitiesService } from '@services';

@Component({
    selector: 'app-members-statistics',
    imports: [DatePipe, DecimalPipe, MatCardModule, MatDividerModule, MatIconModule],
    templateUrl: './members-statistics.component.html',
    styleUrl: './members-statistics.component.scss',
})
export class MembersStatisticsComponent implements OnInit {
    private _utilitiesService = inject(UtilitiesService);
    private _dataService = inject(HWDataService);

    public guildMembers: HWMember[] = [];
    public title = 'Members';
    public subtitle = 'statistics';
    public daysToWarn = 1;
    public guildSumAverages: HWActivityStat = {
        activity: 0,
        prestige: 0,
        titanite: 0,
        war: 0,
        adventure: 0,
        gifts: 0,
        score: 0,
        scoreGifts: 0,
        warGifts: 0,
        rewards: 0,
    };
    public guildTodayAverages: HWActivityStat = {
        activity: 0,
        prestige: 0,
        titanite: 0,
        war: 0,
        adventure: 0,
        gifts: 0,
        score: 0,
        scoreGifts: 0,
        warGifts: 0,
        rewards: 0,
    };
    public guildSumTotal: HWActivityStat = {
        activity: 0,
        prestige: 0,
        titanite: 0,
        war: 0,
        adventure: 0,
        gifts: 0,
        score: 0,
        scoreGifts: 0,
        warGifts: 0,
        rewards: 0,
    };
    public guildTodayTotal: HWActivityStat = {
        activity: 0,
        prestige: 0,
        titanite: 0,
        war: 0,
        adventure: 0,
        gifts: 0,
        score: 0,
        scoreGifts: 0,
        warGifts: 0,
        rewards: 0,
    };
    public guildData: HWGuildData = {} as HWGuildData;
    private _guildClan: HWGuildClan = {} as HWGuildClan;
    private _membersByName: HWMember[] = [];
    private _deviations: { activity: number[]; prestige: number[]; titanite: number[] } = {
        activity: [],
        prestige: [],
        titanite: [],
    };

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

    ngOnInit() {
        combineLatest([this._dataService.guildData$, this._dataService.guildStatistics$]).subscribe({
            next: ([guildData, guildStatistics]) => {
                const oneDayInSec = 24 * 60 * 60;
                const today = new Date();
                const daysToKick = parseInt(guildData.clan.daysToKick);
                this.daysToWarn = parseInt(guildData.clan.daysToKick) / 2;
                this.guildMembers
                    .sort((a, b) => (a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1))
                    .map((data) => {
                        const last = new Date(parseInt(data.lastLoginTime) * 1000);
                        const exp = new Date(last.getTime() + daysToKick * oneDayInSec * 1000);
                        const diff = Math.floor((exp.getTime() - today.getTime()) / 1000);
                        const daysLeft = Math.floor(diff / oneDayInSec);
                        let timeLeft = diff;
                        if (daysLeft >= 1) {
                            timeLeft = diff - daysLeft * oneDayInSec;
                        }
                        data.inactivity = {
                            daysLeft,
                            timeLeft,
                            dropDelay: `${daysLeft}d, ${this._utilitiesService.secondsToDuration(timeLeft)}`,
                            dropDate: Math.floor(exp.getTime() / 1000),
                        };
                        this._membersByName.push(data);
                        return data;
                    });
                Object.assign(this._guildClan, guildData.clan);
                this.guildData.clan = this._guildClan;
                this.guildData.membersStat = guildData.membersStat;

                for (const item of Object.entries(guildStatistics.stat)) {
                    const index = this._membersByName.findIndex((member) => member.id === item[1].id);
                    if (index !== -1) {
                        this._membersByName[index].adventureSum = item[1].adventureStat.reduce(
                            (acc: number, cur: number) => acc + cur,
                            0,
                        );
                        this._membersByName[index].clanGiftsSum = item[1].clanGifts.reduce(
                            (acc: number, cur: number) => acc + cur,
                            0,
                        );
                        this._membersByName[index].clanWarSum = item[1].clanWarStat.reduce(
                            (acc: number, cur: number) => acc + cur,
                            0,
                        );
                        this.guildSumTotal.adventure += this._membersByName[index].adventureSum;
                        this.guildSumTotal.gifts += this._membersByName[index].clanGiftsSum;
                        this.guildSumTotal.war += this._membersByName[index].clanWarSum;
                        const stat: HWWeekStat = {} as HWWeekStat;
                        Object.assign(stat, item[1]);
                        this._membersByName[index].weekStat = stat;
                    }
                }

                for (const data of Object.entries(guildData.membersStat)) {
                    const stat: HWMemberStat = {} as HWMemberStat;
                    Object.assign(stat, data[1]);
                    // eslint-disable-next-line @typescript-eslint/no-explicit-any
                    const index = this._membersByName.findIndex((member) => member.id === (data[1] as any).userId);
                    if (index === -1) continue;
                    this._membersByName[index].stat = stat;
                    this._membersByName[index].score = stat.dungeonActivitySum + stat.activitySum + stat.prestigeSum;
                    this._membersByName[index].warGifts =
                        ((guildData.clan.giftsCount / 2) * ((this._membersByName[index].clanWarSum * 10) / 100)) / 20;
                    this.guildTodayTotal.activity += stat.todayActivity;
                    this.guildTodayTotal.prestige += stat.todayPrestige;
                    this.guildTodayTotal.titanite += stat.todayDungeonActivity;
                    this.guildTodayTotal.score += stat.todayDungeonActivity + stat.todayActivity + stat.todayPrestige;
                    this.guildSumTotal.activity += stat.activitySum;
                    this.guildSumTotal.prestige += stat.prestigeSum;
                    this.guildSumTotal.titanite += stat.dungeonActivitySum;
                    this.guildSumTotal.score += this._membersByName[index].score;
                    this.guildSumTotal.warGifts += this._membersByName[index].warGifts;
                    this._deviations.activity.push(stat.activitySum);
                    this._deviations.prestige.push(stat.prestigeSum);
                    this._deviations.titanite.push(stat.dungeonActivitySum);
                }
                this.guildSumTotal.scoreGifts = guildData.clan.giftsCount - Math.floor(this.guildSumTotal.warGifts);
                this.guildTodayAverages.activity = this.guildTodayTotal.activity / this._membersByName.length;
                this.guildTodayAverages.prestige = this.guildTodayTotal.prestige / this._membersByName.length;
                this.guildTodayAverages.titanite = this.guildTodayTotal.titanite / this._membersByName.length;
                this.guildTodayAverages.score = this.guildTodayTotal.score / this._membersByName.length;
                this.guildSumAverages.activity = this.guildSumTotal.activity / this._membersByName.length;
                this.guildSumAverages.prestige = this.guildSumTotal.prestige / this._membersByName.length;
                this.guildSumAverages.titanite = this.guildSumTotal.titanite / this._membersByName.length;
                this.guildSumAverages.war = this.guildSumTotal.war / 20;
                this.guildSumAverages.adventure = this.guildSumTotal.adventure / this._membersByName.length;
                this.guildSumAverages.gifts = this.guildSumTotal.gifts / this._membersByName.length;
                this.guildSumAverages.score = this.guildSumTotal.score / this._membersByName.length;
                this._membersByName.map((data) => {
                    data.scoreGifts = (data.score / this.guildSumTotal.score) * this.guildSumTotal.scoreGifts;
                    data.rewards = Math.floor(data.scoreGifts + data.warGifts);
                    this.guildSumTotal.rewards += data.rewards;
                    return data;
                });
                this.guildSumAverages.rewards = this.guildSumTotal.rewards / this._membersByName.length;
            },
            error: (err) => console.error(err),
        });
    }

    getMembersByName(): HWMember[] {
        return this._membersByName;
    }

    private _standardDeviation(array: number[]): number {
        const n = array.length;
        const mean = array.reduce((a, b) => a + b) / n;
        return Math.sqrt(array.map((x) => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n);
    }

    getStandardDeviationActivity(): number {
        return this._standardDeviation(this._deviations.activity);
    }

    getStandardDeviationAPrestige(): number {
        return this._standardDeviation(this._deviations.prestige);
    }

    getStandardDeviationTitanite(): number {
        return this._standardDeviation(this._deviations.titanite);
    }
}
