import { InjectClient, Provide, Inject } from '@midwayjs/core';
import { BaseService } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { PushWeightEntity } from '../entity/weight';
import { PushSiteweightEntity } from '../entity/siteweight';
import { PushAuditlogEntity } from '../entity/auditlog';
import { PushCameraGpsEntity } from '../entity/cameragps';
import { PushVehicleGpsEntity } from '../entity/vehiclegps';
import { PushDeviceOnoffEntity } from '../entity/deviceonoff';
import { PushDevicealarmEntity } from '../entity/devicealarm';
import { PluginService } from '../../plugin/service/info';
import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager';

/**
 * 开放接口业务逻辑服务
 */
@Provide()
export class PushOpenService extends BaseService {
  @InjectEntityModel(PushWeightEntity)
  pushWeightEntity: Repository<PushWeightEntity>;

  @InjectEntityModel(PushSiteweightEntity)
  pushSiteweightEntity: Repository<PushSiteweightEntity>;

  @InjectEntityModel(PushCameraGpsEntity)
  pushCameraGpsEntity: Repository<PushCameraGpsEntity>;

  @InjectEntityModel(PushVehicleGpsEntity)
  pushVehicleGpsEntity: Repository<PushVehicleGpsEntity>;

  @InjectEntityModel(PushDeviceOnoffEntity)
  pushDeviceOnoffEntity: Repository<PushDeviceOnoffEntity>;

  @InjectEntityModel(PushDevicealarmEntity)
  pushDevicealarmEntity: Repository<PushDevicealarmEntity>;

  @InjectEntityModel(PushAuditlogEntity)
  pushAuditlogEntity: Repository<PushAuditlogEntity>;

  @Inject()
  pluginService: PluginService;

  @InjectClient(CachingFactory, 'default')
  midwayCache: MidwayCache;

  /**
   * 上报称重数据核心业务
   */
  async reportWeight(data: any) {
    const logTime = new Date();

    try {
      // 1. 保存原始称重数据
      const rawWeight = new PushWeightEntity();
      rawWeight.deviceNo = data.deviceNo;
      rawWeight.uploadTime = data.uploadTime
        ? new Date(data.uploadTime)
        : new Date();
      rawWeight.garbageType = data.garbageType;
      rawWeight.weight = data.garbageWeight || 0;
      rawWeight.extraData =
        typeof data.extraData === 'object'
          ? JSON.stringify(data.extraData)
          : data.extraData;
      await this.pushWeightEntity.save(rawWeight);

      // 2. 模拟关联基础数据模块查询获取商户信息并写入业务称重表
      const siteWeight = new PushSiteweightEntity();
      siteWeight.deviceNo = data.deviceNo;
      siteWeight.uploadTime = rawWeight.uploadTime;
      siteWeight.garbageType = data.garbageType;
      siteWeight.weight = data.garbageWeight || 0;
      siteWeight.extraData = rawWeight.extraData;

      // 动态查询设备基础数据关联信息
      const iotDevices = await this.nativeQuery(
        'SELECT businessId, departmentId FROM t_basicdata_iot WHERE iotCode = ? LIMIT 1',
        [data.deviceNo],
      );

      if (iotDevices && iotDevices.length > 0) {
        siteWeight.businessId = iotDevices[0].businessId;
        siteWeight.departmentId = iotDevices[0].departmentId;
        await this.pushSiteweightEntity.save(siteWeight);

      } else {
        siteWeight.businessId = 'UNKNOWN';
        siteWeight.departmentId = -1;
        await this.writePushAuditLog("weight", { "deviceNo": data.deviceNo, "requestContent": data, "errorMessage": "电子秤还未分配到垃圾收集点." });
      }

    } catch (err) {
      await this.writePushAuditLog("weight", { "deviceNo": data.deviceNo || "UNKNOW", "requestContent": data, "errorMessage": err });
    }

  }

  /**
   * 接收萤石云 消息并缓存
   */
  async saveYingshiyunMessage(body: any) {
    const messageId = body?.header?.messageId || Math.random().toString(36).substring(2);
    await this.midwayCache.set(`push:yingshiyun:queue:${messageId}`, JSON.stringify(body), 24 * 3600);
    this.processYingshiyunAsync(messageId).catch(err => {
      console.error('异步处理GPS消息失败:', err);
    });
    return messageId;
  }

  /**
   * 异步解析萤石云消息，按照消息类型 入库
   */
  async processYingshiyunAsync(messageId: string) {
    const dataStr = await this.midwayCache.get(`push:yingshiyun:queue:${messageId}`) as string | null;
    if (!dataStr) return;
    const body = JSON.parse(dataStr);

    const type = body?.header?.type;

    try {
      switch (type) {

        // 设备上下线
        case 'ys.onoffline': {
          await this.pushDeviceOnoffEntity.save({
            deviceId:body.header.deviceId,
            channelNo: body.header.channelNo,
            messageId: body.header.messageId,
            messageTime: new Date(body.header.messageTime),
            msgType: body.body.msgType,
            devType: body.body.devType,
            deviceName: body.body.deviceName,
            subSerial: body.body.subSerial,
            dasId: body.body.dasId,
            natIp: body.body.natIp,
            occurTime: body.body.occurTime,
            regTime: body.body.regTime
          });
          break;
        }

        // 萤石告警
        case 'ys.alarm': {
          // 图片下载并上传到本地/对象存储  pictureList: Array<{ url: string; id: string }>;
          const localUrls: Record<string, string>[] = [];
          if (body.body.pictureList && Array.isArray(body.body.pictureList)) {
            const filePlugin = await this.pluginService.getInstance('upload');
            for (const item of body.body.pictureList) {
              try {
                const result = await filePlugin.downAndUpload(item.url);
                localUrls.push({url: result, id: item.id});
              } catch (err) {
                console.error(`图片下载失败: ${item.url}`, err);
              }
            }
          }
          await this.pushDevicealarmEntity.save({
            devSerial: body.body.devSerial,
            channelNo: body.body.channelNo || String(body.body.channel),
            alarmId: body.body.alarmId,
            alarmTime: body.body.alarmTime,
            alarmType: body.body.alarmType,
            channelName: body.body.channelName,
            channelType: body.body.channelType ? Number(body.body.channelType) : 1,
            checksum: body.body.checksum,
            crypt: body.body.crypt ? Number(body.body.crypt) : 0,
            customInfo: body.body.customInfo,
            customType: body.body.customType,
            describe: body.body.describe,
            location: body.body.location,
            relationId: body.body.relationId,
            status: body.body.status ? Number(body.body.status) : 1,
            pictureList: localUrls || []
          });
          break;
        }

        // 海康 ISAPI
        //case 'ys.open.isapi': {
          //processCameraGpsAsync(body)
          //await this.pushIsapiRepo.save({
          //  messageId,
          //  raw: JSON.stringify(body),
          //  createTime: new Date(),
          //});
          //break;
        //}

        default:
          console.warn('Unknown yingshi webhook type:', type);
      }
    } catch (err) {
      await this.writePushAuditLog(type || 'unknown', {
        deviceNo: body?.sn || 'UNKNOWN',
        requestContent: body,
        errorMessage: err,
      });
    }

    // 不管成功与否，删除缓存中的任务队列
    await this.midwayCache.del(`push:yingshiyun:queue:${messageId}`);

}



  /**
   * 异步解析车载监控的GPS数据，存储并添加业务表
   */
  async processCameraGpsAsync(body: any) {


    try {
      let vehicleNo = '';
      if (body.sn) {

        const gpsData = body.data || {};
        const statusVal = gpsData.status === 'A' ? 'A' : 'B';

        await this.pushCameraGpsEntity.save({
          sn: body.sn,
          msgSeq: body.msgSeq,
          createDate: body.createDate && !isNaN(Number(body.createDate))
            ? new Date(Number(body.createDate))
            : new Date(),
          gpsTime: gpsData.gpsTime
            ? new Date(gpsData.gpsTime.replace(' ', 'T'))
            : new Date(),
          longitude: gpsData.longitude,
          latitude: gpsData.latitude,
          speed: gpsData.speed,
          direction: gpsData.direction,
          elevation: gpsData.elevation,
          status: statusVal,
        });

        const iotDevice: any[] = await this.nativeQuery(
          'SELECT businessId FROM t_basicdata_iot WHERE iotCode = ? LIMIT 1',
          [body.sn]
        );
        if (iotDevice && iotDevice.length > 0 && iotDevice[0].businessId) {
          vehicleNo = `vehicle_${iotDevice[0].businessId}`;

          await this.pushVehicleGpsEntity.save({
            sn: body.sn,
            msgSeq: body.msgSeq,
            createDate: body.createDate && !isNaN(Number(body.createDate))
              ? new Date(Number(body.createDate))
              : new Date(),
            vehicleNo,
            gpsTime: gpsData.gpsTime
              ? new Date(gpsData.gpsTime.replace(' ', 'T'))
              : new Date(),
            longitude: gpsData.longitude,
            latitude: gpsData.latitude,
            speed: gpsData.speed,
            direction: gpsData.direction,
            elevation: gpsData.elevation,
            status: statusVal,
          });

        } else {
          await this.writePushAuditLog("camera_gps", { "deviceNo": body.sn, "requestContent": body, "errorMessage": "车载监控还未分配到车辆" });
        }
      } else {
        await this.writePushAuditLog("camera_gps", { "deviceNo": "UNKOWN", "requestContent": body, "errorMessage": "未包含设备号SN" });
      }

    } catch (err: any) {

      await this.writePushAuditLog("camera_gps", { "deviceNo": body.sn || "UNKNOW", "requestContent": body, "errorMessage": err });

    }
  }

  async writePushAuditLog(pushType: string, data: any) {
    let isSuccess = true;
    let errorMsg = '';
    try {
      const auditLog = new PushAuditlogEntity();
      auditLog.logTime = new Date();
      auditLog.pushType = pushType;
      auditLog.deviceNo = data.deviceNo || 'unknown-device';
      auditLog.requestContent = JSON.stringify(data.requestContent);
      auditLog.errorMessage = data.errorMessage || 'unknown-erroe';
      await this.pushAuditlogEntity.save(auditLog);

    } catch (err) {
      isSuccess = false;
    }

  }





}
