import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, computed, signal } from '@angular/core';
import { ZardCardComponent } from '@shared/components/card/card.component';
import { UserService } from 'src/app/core/services/user';
import { AgentService } from 'src/app/core/services/agent';
import { TpeService } from 'src/app/core/services/tpe';
import { AgentLimitService } from 'src/app/core/services/agent-limit';
import { HippodromeService } from 'src/app/core/services/hippodrome';
import { ReunionService } from 'src/app/core/services/reunion';
import { CourseService } from 'src/app/core/services/course';
import { RoleService } from 'src/app/core/services/role';
import { AgentFamilyMemberService } from 'src/app/core/services/agent-family-member';
import { ListParams, SortDir } from '@shared/paging/paging';
import { forkJoin, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
import type { Course as CourseModel } from 'src/app/core/interfaces/course';

@Component({
  selector: 'app-main',
  imports: [ZardCardComponent, CommonModule],
  changeDetection: ChangeDetectionStrategy.OnPush,
  templateUrl: './main.html',
  styleUrl: './main.css',
})
export class Main {
  // Loading & error state
  statsLoading = signal(false);
  statsError = signal<string | null>(null);

  // Global totals
  totalUsers = signal(0);
  totalAgents = signal(0);
  totalTpes = signal(0);
  totalAgentLimits = signal(0);
  totalHippodromes = signal(0);
  totalReunions = signal(0);
  totalCourses = signal(0);
  totalRoles = signal(0);
  totalPermissions = signal(0);
  totalAgentFamilyMembers = signal(0);

  // TPE status breakdown for charts
  tpeStatusBreakdown = signal<{ statut: string; count: number; percent: number; color: string }[]>(
    []
  );
  tpeAssignedCount = signal(0);

  // Derived value for TPE assignment rate
  tpeAssignRate = computed(() => {
    const total = this.totalTpes();
    const assigned = this.tpeAssignedCount();
    if (!total) return 0;
    return Math.round((assigned / total) * 100);
  });

  // CSS conic-gradient for a TPE status pie/donut chart
  tpePieGradient = computed(() => {
    const segments = this.tpeStatusBreakdown();
    if (!segments.length) {
      return 'conic-gradient(#e5e7eb 0deg 360deg)';
    }
    let current = 0;
    const parts: string[] = [];
    for (const seg of segments) {
      const start = current;
      const sweep = (seg.percent || 0) * 3.6; // percent -> degrees
      const end = start + sweep;
      parts.push(`${seg.color} ${start}deg ${end}deg`);
      current = end;
    }
    return `conic-gradient(${parts.join(', ')})`;
  });

  // Simple entity activity series for a line chart (users, agents, tpes, reunions, courses)
  entityLabels: string[] = ['USERS', 'AGENTS', 'TPE', 'REUNIONS', 'COURSES'];
  entitySeries = computed(() => [
    this.totalUsers(),
    this.totalAgents(),
    this.totalTpes(),
    this.totalReunions(),
    this.totalCourses(),
  ]);

  // SVG polyline points for the entitySeries (normalized to 0–40 viewport)
  entityPolylinePoints = computed(() => {
    const values = this.entitySeries();
    const max = Math.max(...values, 1);
    const n = values.length;
    if (!n) return '';
    const stepX = n > 1 ? 100 / (n - 1) : 100;
    return values
      .map((v, i) => {
        const x = i * stepX;
        const norm = v / max; // 0–1
        const y = 40 - norm * 30; // keep some top/bottom padding
        return `${x},${y}`;
      })
      .join(' ');
  });

  // Live / upcoming courses (RUNNING or PROGRAMMEE, nearest in time)
  liveCourses = signal<CourseModel[]>([]);

  constructor(
    private userService: UserService,
    private agentService: AgentService,
    private tpeService: TpeService,
    private agentLimitService: AgentLimitService,
    private hippodromeService: HippodromeService,
    private reunionService: ReunionService,
    private courseService: CourseService,
    private roleService: RoleService,
    private familyService: AgentFamilyMemberService
  ) {
    this.loadStats();
  }

  private baseParams(): ListParams {
    return {
      page: 1,
      size: 1,
      search: '',
      sortKey: 'id',
      sortDir: 'asc' as SortDir,
    };
  }

  private loadStats() {
    this.statsLoading.set(true);
    this.statsError.set(null);

    const params = this.baseParams();
    // Fetch more courses to filter for live/upcoming ones
    const coursesParams = {
      ...params,
      perPage: 100, // Fetch up to 100 courses to filter from
      sortKey: 'dateDepartCourse',
      sortDir: 'desc' as SortDir,
    };

    forkJoin({
      users: this.userService
        .list(params)
        .pipe(catchError(() => of({ data: [], meta: { total: 0 } } as any))),
      agents: this.agentService
        .list(params)
        .pipe(catchError(() => of({ data: [], meta: { total: 0 } } as any))),
      tpes: this.tpeService
        .list(params)
        .pipe(catchError(() => of({ data: [], meta: { total: 0 } } as any))),
      limits: this.agentLimitService
        .list(params)
        .pipe(catchError(() => of({ data: [], meta: { total: 0 } } as any))),
      hippodromes: this.hippodromeService
        .list(params, true)
        .pipe(catchError(() => of({ data: [], meta: { total: 0 } } as any))),
      reunions: this.reunionService
        .list(params, true)
        .pipe(catchError(() => of({ data: [], meta: { total: 0 } } as any))),
      courses: this.courseService
        .list(coursesParams)
        .pipe(catchError(() => of({ data: [], meta: { total: 0 } } as any))),
      roles: this.roleService
        .list(params)
        .pipe(catchError(() => of({ data: [], meta: { total: 0 } } as any))),
      permissions: this.roleService.allPermissions().pipe(catchError(() => of([]))),
      familyMembers: this.familyService.list().pipe(catchError(() => of([]))),
      tpeByStatut: this.tpeService.getCountByStatut().pipe(catchError(() => of({}))),
      tpeAssignes: this.tpeService.getAssignesStats().pipe(catchError(() => of(0))),
    }).subscribe({
      next: (res) => {
        this.totalUsers.set(res.users.meta?.total ?? 0);
        this.totalAgents.set(res.agents.meta?.total ?? 0);
        this.totalTpes.set(res.tpes.meta?.total ?? 0);
        this.totalAgentLimits.set(res.limits.meta?.total ?? 0);
        this.totalHippodromes.set(res.hippodromes.meta?.total ?? 0);
        this.totalReunions.set(res.reunions.meta?.total ?? 0);
        this.totalCourses.set(res.courses.meta?.total ?? 0);
        this.totalRoles.set(res.roles.meta?.total ?? 0);
        this.totalPermissions.set((res.permissions as any[]).length ?? 0);
        this.totalAgentFamilyMembers.set((res.familyMembers as any[]).length ?? 0);

        // TPE status breakdown
        const totalTpes = res.tpes.meta?.total ?? 0;
        const statusColors: Record<string, string> = {
          VALIDE: '#16a34a', // green
          DISPONIBLE: '#22c55e',
          AFFECTE: '#3b82f6', // blue
          EN_PANNE: '#f97316', // orange
          EN_MAINTENANCE: '#eab308', // yellow
          BLOQUE: '#ef4444', // red
          INVALIDE: '#6b7280', // gray
          HORS_SERVICE: '#4b5563',
          VOLE: '#7c3aed',
        };
        const rawStats = res.tpeByStatut || {};
        const entries = Object.entries(rawStats as Record<string, number>).filter(
          ([, count]) => count > 0
        );
        const totalFromStats =
          entries.reduce((sum, [, count]) => sum + (count || 0), 0) || totalTpes || 1;
        const breakdown = entries.map(([statut, count]) => {
          const upper = statut.toUpperCase();
          const color = statusColors[upper] || '#6b7280';
          const percent = Math.round(((count || 0) / totalFromStats) * 100);
          return { statut: upper, count: count || 0, percent, color };
        });
        this.tpeStatusBreakdown.set(breakdown);
        this.tpeAssignedCount.set(res.tpeAssignes ?? 0);

        // Live / upcoming courses: filter by statut & date
        const allCourses = (res.courses.data as CourseModel[]) ?? [];
        const now = new Date();
        const oneHourAgo = new Date(now.getTime() - 60 * 60 * 1000);
        const oneDayAhead = new Date(now.getTime() + 24 * 60 * 60 * 1000);

        const live = allCourses
          .filter((c) => {
            const statut = String(c.statut || '').toUpperCase();

            // Include RUNNING courses
            if (statut === 'RUNNING') return true;

            // Include PROGRAMMEE courses that are scheduled within the next 24 hours
            if (statut === 'PROGRAMMEE') {
              const d = c.heureDepartPrevue ? c.heureDepartPrevue : null;
              if (!d) return false;
              // Include if departure is in the past hour (just started) or within next 24 hours
              return d ;
            }

            // Also include VALIDATED courses that are about to start (within next 24 hours)
            if (statut === 'VALIDATED') {
              const d = c.heureDepartPrevue ? c.heureDepartPrevue : null;
              if (!d) return false;
              return d;
            }

            return false;
          })
          .slice(0, 6);
        this.liveCourses.set(live);

        this.statsLoading.set(false);
      },
      error: () => {
        this.statsError.set('Erreur lors du chargement des statistiques du dashboard.');
        this.statsLoading.set(false);
      },
    });
  }
}
