import { Provide, Inject } from '@midwayjs/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository, In, LessThan } from 'typeorm';
import { ReportJoblogEntity } from '../entity/joblog';
import { TaskServiceXinYueGps } from './taskservicexinyuegps';

/**
 * 芯跃三轮车定位实时同步执行器
 * 负责 joblog 状态机与同步周期节流，具体拉数由 TaskServiceXinYueGps 完成
 */
@Provide()
export class ExecutorXinYueVehicleGps {
  @InjectEntityModel(ReportJoblogEntity)
  reportJoblogEntity: Repository<ReportJoblogEntity>;

  @Inject()
  taskServiceXinYueGps: TaskServiceXinYueGps;

  async execute() {
    const pendingJobs = await this.reportJoblogEntity.find({
      where: {
        status: In(['INIT', 'FAILED']),
        jobName: 'XINYUE_VEHICLE_GPS',
      },
      order: {
        dataDate: 'ASC',
      },
    });

    for (const job of pendingJobs) {
      const intervalSeconds = await this.taskServiceXinYueGps.getSyncIntervalSeconds();
      if (this.shouldSkipByInterval(job, intervalSeconds)) {
        continue;
      }

      const lockResult = await this.reportJoblogEntity.update(
        { id: job.id, status: job.status },
        { status: 'RUNNING', startTime: new Date() }
      );

      if (lockResult.affected === 0) {
        continue;
      }

      try {
        const result = await this.taskServiceXinYueGps.syncRealtimeData();
        await this.reportJoblogEntity.update(job.id, {
          status: 'SUCCESS',
          recordsProcessed: result.recordsProcessed,
          endTime: new Date(),
          errorMessage: result.errorMessage || '',
        });
      } catch (error) {
        await this.reportJoblogEntity.update(job.id, {
          status: 'FAILED',
          endTime: new Date(),
          errorMessage: this.stringifyError(error),
          failedCount: () => 'failedCount + 1',
        });
      }
    }
  }

  /**
   * 将卡住的 RUNNING 任务洗回 INIT，避免进程中断后永远不跑
   */
  async recoverStuckJobs() {
    const expireAt = new Date(Date.now() - 10 * 60 * 1000);
    await this.reportJoblogEntity.update(
      {
        jobName: 'XINYUE_VEHICLE_GPS',
        status: 'RUNNING',
        startTime: LessThan(expireAt),
      },
      { status: 'INIT' }
    );
  }

  /**
   * 距上次结束未到同步周期则跳过，避免后台 cron 比参数更密时刷接口
   */
  private shouldSkipByInterval(job: ReportJoblogEntity, intervalSeconds: number): boolean {
    if (!intervalSeconds || intervalSeconds <= 0) {
      return false;
    }
    if (!job.endTime) {
      return false;
    }
    const elapsed = Date.now() - new Date(job.endTime).getTime();
    return elapsed < intervalSeconds * 1000;
  }

  private stringifyError(error: any): string {
    if (error instanceof Error) {
      return error.stack ?? error.message;
    }
    if (typeof error === 'string') {
      return error;
    }
    try {
      return JSON.stringify(error);
    } catch {
      return String(error);
    }
  }
}
