import { Body, Controller, Param, Post } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { ZodResponse } from 'nestjs-zod';
import { Permission } from '@pac/types';
import { RequirePermission } from '../../common/decorators/permissions.decorator';
import { CurrentUser, AuthenticatedUser } from '../../common/decorators/current-user.decorator';
import {
  TenantScope,
  TenantScopeContext,
} from '../../common/decorators/tenant-scope.decorator';
import {
  RefreshPatientResponseDto,
  TriggerSyncRequestDto,
  TriggerSyncResponseDto,
} from './dto/sync.dto';
import { SyncService } from './sync.service';

@ApiTags('sync')
@ApiBearerAuth('accessToken')
@Controller('sync')
export class SyncController {
  constructor(private readonly sync: SyncService) {}

  @Post('trigger')
  @ZodResponse({ status: 202, type: TriggerSyncResponseDto })
  @RequirePermission(Permission.PLATFORM_MANAGE)
  @ApiOperation({
    summary: 'Force a pull run (ops). Defaults to current host; admin can target any.',
  })
  async trigger(
    @CurrentUser() user: AuthenticatedUser,
    @Body() dto: TriggerSyncRequestDto,
  ) {
    const target = dto.hostId ?? user.hostId;
    // Stub: W2 实现后 runPull 返回 { syncLogId, fetched, transactionsWritten, factsEmitted }
    await this.sync.runPull(target);
    return {
      accepted: true as const,
      syncLogId: '00000000-0000-0000-0000-000000000000',
      fetched: 0,
      transactionsWritten: 0,
      factsEmitted: 0,
    };
  }

  /**
   * Single-patient on-demand pull (staff/leader path). Used when a CSR opens
   * a patient page and wants the latest host-side state.
   *
   * Concurrency:
   *   - 30s in-flight dedupe (multiple clicks share the same run)
   *   - 60s cooldown after a recent successful refresh (rate limit)
   *   - Adapter without pullPatient → 30804 SYNC_PATIENT_PULL_NOT_SUPPORTED
   */
  @Post('patient/:patientId/refresh')
  @ZodResponse({ status: 200, type: RefreshPatientResponseDto })
  @RequirePermission(Permission.PATIENT_VIEW)
  @ApiOperation({ summary: 'On-demand single-patient refresh (staff/leader)' })
  async refreshPatient(
    @TenantScope() scope: TenantScopeContext,
    @Param('patientId') patientId: string,
  ) {
    const r = await this.sync.runPullForPatient(scope, patientId);
    return {
      syncLogId: r.syncLogId,
      status: r.status,
      transactionsWritten: r.transactionsWritten,
      factsEmitted: r.factsEmitted,
      plansCreated: r.plansCreated,
    };
  }
}
