import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from '@core/database/prisma/prisma.service';
import { AnnualLeaveSyncService } from './sync/annual-leave-sync.service';
import { DingtalkYidaService } from './sdk/dingtalk-yida.service';

type AnnualLeaveReleasePlanRow = {
  userId: string;
  year: number;
  adjustmentDays: unknown;
  notCountDays: number;
  totalDays: number;
  releaseSchedule: unknown;
  lastCalculatedAt: Date | null;
};

@Injectable()
export class AnnualLeavePlanAdminService {
  constructor(
    private prisma: PrismaService,
    private annualLeaveSyncService: AnnualLeaveSyncService,
    private yidaService: DingtalkYidaService,
  ) {}

  async getPlanSettings(userId: string, year?: number) {
    const targetYear = year ?? new Date().getFullYear();
    const record = await this.getPlanRepo().findUnique({
      where: {
        userId_year: {
          userId,
          year: targetYear,
        },
      },
    }) as AnnualLeaveReleasePlanRow | null;

    if (!record) {
      const employee = await this.loadEmployee(userId);
      if (!employee) {
        throw new NotFoundException(`未找到员工 ${userId} 在 ${targetYear} 年的年假释放计划`);
      }
    }

    return await this.toPlanSettings(record ?? {
      userId,
      year: targetYear,
      adjustmentDays: 0,
      notCountDays: 0,
      totalDays: 0,
      releaseSchedule: [],
      lastCalculatedAt: null,
    });
  }

  async updatePlanSettings(input: {
    userId: string;
    year: number;
    adjustmentDays?: number;
    notCountDays?: number;
    recalculate?: boolean;
  }) {
    const repo = this.getPlanRepo();
    const existing = await repo.findUnique({
      where: {
        userId_year: {
          userId: input.userId,
          year: input.year,
        },
      },
    }) as AnnualLeaveReleasePlanRow | null;

    const target = existing || await this.createPlaceholderPlan(input.userId, input.year);

    await repo.update({
      where: {
        userId_year: {
          userId: target.userId,
          year: input.year,
        },
      },
      data: {
        ...(input.adjustmentDays !== undefined ? { adjustmentDays: input.adjustmentDays } : {}),
        ...(input.notCountDays !== undefined ? { notCountDays: input.notCountDays } : {}),
        lastCalculatedAt: new Date(),
      },
    });

    if (input.recalculate !== false) {
      await this.annualLeaveSyncService.refreshPlan(input.userId, input.year);
    }

    return this.getPlanSettings(input.userId, input.year);
  }

  private getPlanRepo() {
    return (this.prisma as any).dingtalkAnnualLeaveReleasePlan;
  }

  private async createPlaceholderPlan(userId: string, year: number): Promise<AnnualLeaveReleasePlanRow> {
    const employee = await this.loadEmployee(userId);
    if (!employee) {
      throw new NotFoundException(`未找到员工 ${userId} 在 ${year} 年的年假释放计划`);
    }

    return this.getPlanRepo().upsert({
      where: {
        userId_year: {
          userId,
          year,
        },
      },
      update: {
        lastCalculatedAt: new Date(),
      },
      create: {
        userId,
        year,
        adjustmentDays: 0,
        notCountDays: 0,
        totalDays: 0,
        releaseSchedule: [],
        lastCalculatedAt: new Date(),
      },
    }) as Promise<AnnualLeaveReleasePlanRow>;
  }

  private async loadEmployee(userId: string): Promise<{ userId: string } | null> {
    const employeeRepo = (this.prisma as any).dingtalkEmployee;
    return employeeRepo.findUnique({
      where: { userId },
      select: { userId: true },
    });
  }

  private async toPlanSettings(record: AnnualLeaveReleasePlanRow) {
    return {
      userId: record.userId,
      year: record.year,
      adjustmentDays: Number(record.adjustmentDays || 0),
      notCountDays: Number(record.notCountDays || 0),
      totalDays: Number(record.totalDays || 0),
      releaseSchedule: Array.isArray(record.releaseSchedule) ? record.releaseSchedule : [],
      lastCalculatedAt: record.lastCalculatedAt?.toISOString() ?? null,
    };
  }
}
