import { CurrencyPipe, DatePipe, registerLocaleData } from '@angular/common';
import localeDe from '@angular/common/locales/de';
import { Component, LOCALE_ID, computed, inject, signal } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { MatCardModule } from '@angular/material/card';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import type { ChartData, ChartOptions } from 'chart.js';
import { ChartCanvas } from '../../../shared/chart-canvas/chart-canvas';
import { TeamStore } from '../../../core/team/team-store';
import { TransactionsApi } from '../../../core/team/transactions-api';
import { TeamStatsApi } from '../../../core/team/team-stats-api';
import { TeamOverviewStats } from '../../../models/team-stats.model';
import { TeamActivity } from '../../../models/transaction.model';
import { TransactionAmount } from '../../../shared/transaction-amount/transaction-amount';
import { of } from 'rxjs';
import { catchError, distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators';

registerLocaleData(localeDe);

const BALANCE_COLOR = '#4f8f46';
const THEORETICAL_BALANCE_COLOR = '#1d70b8';
const INCOME_COLOR = '#4f8f46';
const EXPENSE_COLOR = '#c1121f';
const PENALTY_COLOR = '#9e9e9e';

function formatMonthLabel(month: string): string {
  const [year, monthNumber] = month.split('-').map(Number);
  return new Intl.DateTimeFormat('de-DE', { month: 'short', year: '2-digit' }).format(
    new Date(year, monthNumber - 1, 1),
  );
}

@Component({
  selector: 'app-overview',
  imports: [
    CurrencyPipe,
    DatePipe,
    MatButtonModule,
    MatCardModule,
    MatIconModule,
    MatProgressSpinnerModule,
    RouterLink,
    ChartCanvas,
    TransactionAmount,
  ],
  providers: [{ provide: LOCALE_ID, useValue: 'de-DE' }],
  templateUrl: './overview.html',
  styleUrl: './overview.scss',
})
export class Overview {
  private readonly route = inject(ActivatedRoute);
  private readonly transactionsApi = inject(TransactionsApi);
  private readonly teamStatsApi = inject(TeamStatsApi);
  protected readonly team = inject(TeamStore).team;
  protected readonly activities = signal<TeamActivity[]>([]);
  protected readonly loadingActivities = signal(true);
  protected readonly stats = signal<TeamOverviewStats | null>(null);
  protected readonly loadingStats = signal(true);

  protected readonly balanceHistory = computed(() => this.stats()?.balanceHistory ?? []);
  protected readonly monthlyFlow = computed(() => this.stats()?.monthlyFlow ?? []);
  protected readonly topOutstanding = computed(() => this.stats()?.topOutstanding ?? []);

  protected readonly balanceChartData = computed<ChartData>(() => {
    const points = this.balanceHistory();
    return {
      labels: points.map((point) => formatMonthLabel(point.month)),
      datasets: [
        {
          label: 'Kassenstand',
          data: points.map((point) => point.balance),
          borderColor: BALANCE_COLOR,
          backgroundColor: BALANCE_COLOR,
          tension: 0.3,
          fill: false,
          tooltip: {
            callbacks: {
              label: function(context) {
                return `In der Kasse: ${context.formattedValue} €`
              }
            }
          }
        },
        {
          label: 'Theoretisch (inkl. offene Beiträge)',
          data: points.map((point) => point.theoreticalBalance),
          borderColor: THEORETICAL_BALANCE_COLOR,
          backgroundColor: THEORETICAL_BALANCE_COLOR,
          borderDash: [6, 4],
          tension: 0.3,
          fill: false,
          tooltip: {
            callbacks: {
              label: function(context) {
                return `Kasse + Offen: ${context.formattedValue} €`
              }
            }
          }
        },
      ],
    };
  });

  protected readonly flowChartData = computed<ChartData>(() => {
    const points = this.monthlyFlow();
    return {
      labels: points.map((point) => formatMonthLabel(point.month)),
      datasets: [
        {
          label: 'Einnahmen',
          data: points.map((point) => point.income),
          backgroundColor: INCOME_COLOR,
          borderRadius: 4,
          tooltip: {
            callbacks: {
              label: function(context) {
                return `Einnahen: ${context.formattedValue} €`
              }
            }
          }
        },
        {
          label: 'Ausgaben',
          data: points.map((point) => point.expense),
          backgroundColor: EXPENSE_COLOR,
          borderRadius: 4,
          tooltip: {
            callbacks: {
              label: function(context) {
                return `Ausgaben: ${context.formattedValue} €`
              }
            }
          }
        },
        {
          label: 'Strafen & Umlagen',
          data: points.map((point) => point.penalties),
          backgroundColor: PENALTY_COLOR,
          borderRadius: 4,
          tooltip: {
            callbacks: {
              label: function(context) {
                return `Strafen & Umlagen: ${context.formattedValue} €`
              }
            }
          }
        },
      ],
    };
  });

  protected readonly topOutstandingChartData = computed<ChartData>(() => {
    const players = this.topOutstanding();
    return {
      labels: players.map((player) => player.playerName),
      datasets: [
        {
          label: 'Offener Betrag',
          data: players.map((player) => player.balance),
          backgroundColor: EXPENSE_COLOR,
          tooltip: {
            callbacks: {
              label: function(context) {
                return ` Offen: ${context.formattedValue} €`
              }
            }
          }
        },
      ],
    };
  });

  protected readonly balanceChartOptions: ChartOptions = {
    responsive: true,
    maintainAspectRatio: false,
    plugins: { legend: { position: 'bottom' } },
    scales: {
      y: {
        ticks: {
          callback: function(value, index, ticks) {
          return value.toLocaleString() + ' €';
        }
        }
      }
    },
    locale: 'de-DE'

  };

  protected readonly flowChartOptions: ChartOptions = {
    responsive: true,
    maintainAspectRatio: false,
    plugins: { legend: { position: 'bottom' } },
    scales: {
      y: {
        ticks: {
          callback: function(value, index, ticks) {
          return value.toLocaleString() + ' €';
        }
        }
      }
    },
  };

  protected readonly topOutstandingChartOptions: ChartOptions = {
    indexAxis: 'y',
    responsive: true,
    maintainAspectRatio: false,
    plugins: { legend: { display: false } },
    scales: {
      x: {
        ticks: {
          callback: function(value, index, ticks) {
          return value.toLocaleString() + ' €';
        }
        }
      }
    },
  };

  constructor() {
    const parentRoute = this.route.parent;
    if (!parentRoute) {
      this.loadingActivities.set(false);
      this.loadingStats.set(false);
      return;
    }

    const teamId$ = parentRoute.paramMap.pipe(
      map((params) => Number(params.get('id'))),
      distinctUntilChanged(),
    );

    teamId$
      .pipe(
        tap((id) => {
          this.activities.set([]);
          this.loadingActivities.set(Number.isInteger(id) && id > 0);
        }),
        switchMap((id) =>
          Number.isInteger(id) && id > 0
            ? this.transactionsApi.loadTeamTransactions(id).pipe(catchError(() => of([])))
            : of([]),
        ),
        takeUntilDestroyed(),
      )
      .subscribe((activities) => {
        this.activities.set(activities.slice(0, 10));
        this.loadingActivities.set(false);
      });

    teamId$
      .pipe(
        tap((id) => {
          this.stats.set(null);
          this.loadingStats.set(Number.isInteger(id) && id > 0);
        }),
        switchMap((id) =>
          Number.isInteger(id) && id > 0
            ? this.teamStatsApi.loadStats(id).pipe(catchError(() => of(null)))
            : of(null),
        ),
        takeUntilDestroyed(),
      )
      .subscribe((stats) => {
        this.stats.set(stats);
        this.loadingStats.set(false);
      });
  }

  protected activityIcon(activity: TeamActivity): string {
    return activity.isTeamWalletTransaction ? 'account_balance' : 'person';
  }
}
