import { Resolver, Query, Args, Context, ResolveField, Parent } from '@nestjs/graphql';
import { UseGuards } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Between } from 'typeorm';
import { format } from 'date-fns';
import { DashboardType, DailySummaryType } from '../types/dashboard.type';
import { ActivityGQLType } from '../types/activity.type';
import { ChildType } from '../types/child.type';
import { UserType } from '../types/user.type';
import { Child } from '../../database/entities/child.entity';
import { Activity, ActivityType } from '../../database/entities/activity.entity';
import { FamilyMember } from '../../database/entities/family-member.entity';
import { User } from '../../database/entities/user.entity';
import { GqlAuthGuard } from '../guards/gql-auth.guard';
import { ChildDataLoader } from '../dataloaders/child.dataloader';
import { UserDataLoader } from '../dataloaders/user.dataloader';

@Resolver(() => DashboardType)
@UseGuards(GqlAuthGuard)
export class DashboardResolver {
  constructor(
    @InjectRepository(Child)
    private readonly childRepository: Repository<Child>,
    @InjectRepository(Activity)
    private readonly activityRepository: Repository<Activity>,
    @InjectRepository(FamilyMember)
    private readonly familyMemberRepository: Repository<FamilyMember>,
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
  ) {}

  @Query(() => DashboardType, { name: 'dashboard' })
  async getDashboard(
    @Args('childId', { nullable: true }) childId: string,
    @Context() context: any,
  ): Promise<DashboardType> {
    console.log('[DashboardResolver] Context:', {
      hasReq: !!context.req,
      hasUser: !!context.req?.user,
      user: context.req?.user,
      headers: context.req?.headers?.authorization?.substring(0, 20),
    });

    const userId = context.req?.user?.userId;

    if (!userId) {
      throw new Error('User not authenticated');
    }

    // Get user's family memberships
    const familyMemberships = await this.familyMemberRepository.find({
      where: { userId },
      relations: ['family'],
    });

    const familyIds = familyMemberships.map((fm) => fm.familyId);

    // Get all children in user's families
    const children = await this.childRepository.find({
      where: familyIds.length > 0 ? familyIds.map(id => ({ familyId: id })) : [],
      order: { createdAt: 'ASC' },
    });

    // Select child (specified or first child)
    const selectedChild = childId
      ? children.find((c) => c.id === childId)
      : children[0];

    // Get today's date range
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const tomorrow = new Date(today);
    tomorrow.setDate(tomorrow.getDate() + 1);

    // Get recent activities (last 10 for selected child)
    const recentActivities = selectedChild
      ? await this.activityRepository.find({
          where: { childId: selectedChild.id },
          order: { startedAt: 'DESC' },
          take: 10,
        })
      : [];

    // Get today's activities for selected child
    const todayActivities = selectedChild
      ? await this.activityRepository.find({
          where: {
            childId: selectedChild.id,
            startedAt: Between(today, tomorrow),
          },
        })
      : [];

    // Calculate today's summary
    const todaySummary = this.calculateDailySummary(
      todayActivities,
      format(today, 'yyyy-MM-dd'),
    );

    // Get all family members
    const familyMembers = await this.familyMemberRepository.find({
      where: familyIds.length > 0 ? familyIds.map(id => ({ familyId: id })) : [],
      relations: ['user'],
    });

    return {
      children: children as any[],
      selectedChild: selectedChild as any,
      recentActivities: recentActivities as any[],
      todaySummary,
      familyMembers: familyMembers as any[],
      totalChildren: children.length,
      totalActivitiesToday: todayActivities.length,
    };
  }

  @ResolveField(() => ChildType, { nullable: true })
  async child(
    @Parent() activity: ActivityGQLType,
    @Context() context: any,
  ): Promise<ChildType> {
    const childLoader: ChildDataLoader = context.childLoader;
    return childLoader.batchChildren.load(activity.childId) as any;
  }

  @ResolveField(() => UserType, { nullable: true })
  async logger(
    @Parent() activity: ActivityGQLType,
    @Context() context: any,
  ): Promise<UserType> {
    const userLoader: UserDataLoader = context.userLoader;
    return userLoader.batchUsers.load(activity.loggedBy);
  }

  private calculateDailySummary(
    activities: Activity[],
    date: string,
  ): DailySummaryType {
    const summary = {
      feedingCount: 0,
      totalFeedingAmount: 0,
      sleepCount: 0,
      totalSleepDuration: 0,
      diaperCount: 0,
      medicationCount: 0,
      date,
    };

    activities.forEach((activity) => {
      switch (activity.type) {
        case ActivityType.FEEDING:
          summary.feedingCount++;
          if (activity.metadata?.amount) {
            summary.totalFeedingAmount += activity.metadata.amount;
          }
          break;
        case ActivityType.SLEEP:
          summary.sleepCount++;
          if (activity.endedAt && activity.startedAt) {
            const duration = Math.floor(
              (activity.endedAt.getTime() - activity.startedAt.getTime()) / 60000,
            );
            summary.totalSleepDuration += duration;
          }
          break;
        case ActivityType.DIAPER:
          summary.diaperCount++;
          break;
        case ActivityType.MEDICATION:
        case ActivityType.MEDICINE:
          summary.medicationCount++;
          break;
      }
    });

    return summary;
  }
}
