import { BadRequestException, Controller, Get, Logger, Post, Query, UseGuards } from '@nestjs/common';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { RequirePermission } from '../auth/decorators/permission.decorator';
import { SyncService } from './sync.service';
import type { SyncPlatform } from '../entities/sync-log.entity';
import { ScheduleSyncQueryDto } from './dto/schedule-sync.dto';

@UseGuards(JwtAuthGuard)
@Controller('sync')
export class SyncController {
  private readonly logger = new Logger(SyncController.name);
  constructor(private readonly syncService: SyncService) {}

  @Post('trigger')
  @RequirePermission('sync:trigger')
  async triggerSync(
    @Query('platform') platform?: SyncPlatform,
    @Query('rootDeptId') rootDeptId?: string,
  ) {
    const rootId = rootDeptId ? this.parseRootDeptId(rootDeptId) : 1;
    const logs = await this.syncService.triggerSync(platform, rootId);
    return { synced: logs.length, logs };
  }

  @Get('status')
  @RequirePermission('sync:read')
  async getStatus() {
    const lastDingTalkStudents = await this.syncService.getLastSync('dingtalk_students');
    const lastDingTalkAttendance = await this.syncService.getLastSync('dingtalk_attendance');
    const lastWeCom = await this.syncService.getLastSync('wecom');
    return {
      dingTalkStudents: lastDingTalkStudents ? { lastSyncAt: lastDingTalkStudents.finishedAt, status: lastDingTalkStudents.status } : null,
      dingTalkAttendance: lastDingTalkAttendance ? { lastSyncAt: lastDingTalkAttendance.finishedAt, status: lastDingTalkAttendance.status } : null,
      weCom: lastWeCom ? { lastSyncAt: lastWeCom.finishedAt, status: lastWeCom.status } : null,
    };
  }

  /** 获取钉钉组织部门树，供前端选择同步起点 */
  @Get('dingtalk/org-tree')
  @RequirePermission('sync:read')
  async getDingTalkOrgTree(@Query('rootDeptId') rootDeptId?: string) {
    const rootId = rootDeptId ? this.parseRootDeptId(rootDeptId) : 1;
    const tree = await this.syncService.getDingTalkOrgTree(rootId);
    return { success: true, data: tree };
  }

  /** 获取钉钉组织部门树（含用户），供同步用户选择器使用 */
  @Get('dingtalk/org-tree-with-users')
  @RequirePermission('sync:read')
  async getDingTalkOrgTreeWithUsers(@Query('rootDeptId') rootDeptId?: string) {
    const rootId = rootDeptId ? this.parseRootDeptId(rootDeptId) : 1;
    const tree = await this.syncService.getDingTalkOrgTreeWithUsers(rootId);
    return { success: true, data: tree };
  }

  @Get('dingtalk/attendance-groups')
  @RequirePermission('sync:read')
  async getDingTalkAttendanceGroups() {
    return { success: true, data: await this.syncService.getDingTalkAttendanceGroups() };
  }

  @Post('dingtalk/attendance-groups/delete-all')
  @RequirePermission('sync:trigger')
  async deleteAllDingTalkAttendanceGroups() {
    return {
      success: true,
      data: await this.syncService.deleteAllDingTalkAttendanceGroups(),
    };
  }

  @Get('logs')
  @RequirePermission('sync:read')
  async getLogs(
    @Query('platform') platform?: SyncPlatform,
    @Query('limit') limit?: number,
  ) {
    return this.syncService.getLogs(platform, limit ? Number(limit) : 50);
  }

  // ── 排班同步 ──

  /** 触发排班同步到钉钉考勤排班 */
  @Post('schedule/sync')
  @RequirePermission('sync:trigger')
  async syncSchedule(@Query() query: ScheduleSyncQueryDto) {
    const result = await this.syncService.syncScheduleToDingTalk(
      query.dateFrom,
      query.days,
      query.attendanceMachineOnly,
    );
    return { success: true, data: result };
  }

  /** 查询钉钉排班状态（核对本地 vs 钉钉） */
  @Get('schedule/status')
  @RequirePermission('sync:read')
  async getScheduleStatus(
    @Query('date') date?: string,
  ) {
    const status = await this.syncService.getScheduleSyncStatus(date);
    return { success: true, data: status };
  }


  private parseRootDeptId(rootDeptId: string): number {
    if (!/^\d+$/.test(rootDeptId)) {
      throw new BadRequestException('rootDeptId must be a positive integer');
    }
    const parsed = Number(rootDeptId);
    if (!Number.isSafeInteger(parsed) || parsed < 1) {
      throw new BadRequestException('rootDeptId must be a positive integer');
    }
    return parsed;
  }
}
