import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { AlertController } from '@ionic/angular';
import * as Parse from 'parse';
import { AiChatService } from './aichart.service';
import { HttpService } from './http.service';
import { MessageService } from './message.service';
declare const AgoraRTC: any;
import BeautyExtension from 'agora-extension-beauty-effect'; // 引入美颜扩展
@Injectable({
  providedIn: 'root',
})
export class LiveService {
  isAnchor: boolean = false; //是否是主播
  options: {
    appid: string;
    channel: string;
    token: string;
  } = {
    appid: '',
    channel: '',
    token: '',
  };
  localTracks: any = {
    audioTrack: null,
    videoTrack: null,
  };
  rid?: string; //房间id(channel)
  profile?: any = localStorage.getItem('profile');
  client: any; //客户端
  company: string = '';
  UID: any;
  tools: any = {
    audio: false, //是否关闭音频
    camera: false, //是否切换摄像头
    glorify: false, //是否开启美颜
    mute: false, //是否静音
  };
  user_published_list: Array<any> = []; //已发布列表
  timer: any; //轮询获取频道token的定时
  alert: any; //提示框
  media_devices: {
    //音视频设备列表
    audioDevices: Array<any>;
    videoDevices: Array<any>;
  } = {
    audioDevices: [],
    videoDevices: [],
  };
  currentUsedDevice: { audioDevice: string; videoDevice: string } = {
    //当前使用的设备
    audioDevice: '',
    videoDevice: '',
  };
  room?: Parse.Object; //直播间
  connection_state?: string; //连接状态
  surplusNumber: number = 0; //剩余可通话时长（单位：秒s）
  countdown: number = 0; // 新增倒计时变量
  timer_countdown: any;
  liveLog?: Parse.Object; //直播记录

  isOpenEvaluate: boolean = false; //是否开启评价
  isBeautyExtensionRegistered: boolean = false; //是否注册美颜扩展
  processor: any; //音视频处理
  constructor(
    private http: HttpService,
    private router: Router,
    private aiServ: AiChatService,
    private alertController: AlertController,
    private msgSer: MessageService
  ) {
    this.client?.leave();
    this.company = this.aiServ.company;
    this.getProfile();
  }
  async getProfile() {
    if (this.profile) return;
    let queryProfile = new Parse.Query('Profile');
    queryProfile.equalTo('user', Parse.User.current()?.id);
    queryProfile.notEqualTo('isDeleted', true);
    queryProfile.equalTo('isCross', true);
    this.profile = await queryProfile.first();
    this.profile?.id &&
      localStorage.setItem('profile', JSON.stringify(this.profile.toJSON()));
  }
  /* 初始化Agora */
  initAgora() {
    this.tools = {
      audio: false, //是否关闭音频
      camera: false, //是否切换摄像头
      glorify: false, //是否开启美颜
      mute: false, //是否静音
    };
    this.timer && clearTimeout(this.timer);
    this.timer_countdown && clearInterval(this.timer_countdown);
    this.options['token'] = '';
    this.options['channel'] = '';
    this.user_published_list = [];
    this.client?.leave();
    this.client = AgoraRTC.createClient({ mode: 'rtc', codec: 'h264' });
    AgoraRTC.enableLogUpload();

    if (!this.isBeautyExtensionRegistered) {
      // 创建 BeautyExtension 实例
      const extension: any = new BeautyExtension();
      // 注册插件
      AgoraRTC.registerExtensions([extension]);
      // 创建 BeautyProcessor 实例
      this.processor = extension.createProcessor();
    }
    this.setBeautyOptions();
  }
  // 获取所有音视频设备
  getDevices() {
    AgoraRTC.getDevices()
      .then((devices: any) => {
        this.media_devices.audioDevices = devices.filter(function (
          device: any
        ) {
          return device.kind === 'audioinput';
        });
        this.media_devices.videoDevices = devices.filter(function (
          device: any
        ) {
          return device.kind === 'videoinput';
        });
        console.log(this.media_devices);
        this.currentUsedDevice = {
          audioDevice: this.media_devices.audioDevices[0].deviceId,
          videoDevice: this.media_devices.videoDevices[0].deviceId,
        };
        // return Promise.all([
        //   AgoraRTC.createCameraVideoTrack(),
        //   AgoraRTC.createMicrophoneAudioTrack(),
        // ]);
      })
      .then((tracks: any) => {
        console.log(tracks);
      })
      .catch((err: any) => {
        console.warn('获取媒体权限失败', err);
        this.alertTips('获取媒体权限失败');
      });
  }
  /* 获取token */
  async getToken(room: Parse.Object) {
    this.room = room;
    this.isAnchor = room?.get('user')?.id === Parse.User.current()?.id;
    this.timer && clearTimeout(this.timer);
    let remoteEle = document.getElementById('vice-video');
    (remoteEle as any).style.display = 'none';
    //获取频道token记录
    let baseurl = 'https://server.fmode.cn/api/ailiao/token';
    if (this.isAnchor) {
      this.UID = 111111;
      baseurl = 'https://server.fmode.cn/api/webrtc/build_token';
    }
    let reqBody = {
      company: this.company, // this.aiSer.company,
      profile: room?.get('profile').id,
      channelName: room?.get('profile').id,
    };
    let data: any = await this.http.httpRequst(baseurl, reqBody, 'POST');
    console.log(data);
    if (data.code == 200) {
      this.options.token = data.data.token;
      this.options.appid = data.data.appid;
    } else {
      this.timer = setTimeout(() => {
        this.getToken(room);
      }, 2000);
      return;
    }
    this.options.channel = room?.get('profile').id;
    this.join();
  }
  async updateToken(pid: string) {
    let sql = `select  "rtc"."objectId" as "rid","rtc"."channel", "rtc"."token",  "rtc"."expiraTime" from "RtcToken" as "rtc" where "rtc"."profile" = '${pid}' and "rtc"."expiraTime" >= now() order by "createdAt" desc limit 1`;
    let tokenData: any = await this.http.customSQL(sql);
    if (
      tokenData &&
      tokenData.code == 200 &&
      tokenData.data &&
      tokenData.data.length > 0
    ) {
      return tokenData.data[0];
    } else {
      return null;
    }
  }
  /* 进入频道 */
  async join() {
    let path = location.pathname;
    if (path.indexOf('/live/link-room/') == -1) return;
    console.log('频道id：', this.options.channel);
    this.client
      .join(
        this.options.appid,
        this.options.channel,
        this.options.token,
        this.UID
      )
      .then(async (uid: any) => {
        // await this.client.setClientRole('host');
        this.connection_state = this.client.connectionState;
        console.log('进入频道当前uid：', uid, '状态：', this.connection_state);
        let user = Parse.User.current();
        this.msgSer?.publishMessage(
          `${user?.get('name') || user?.get('nickname')}加入频道直播`,
          this.room?.get('user')?.id
        );
        if (!this.isAnchor) {
          // 观众进入直播间，创建直播记录
          await this.createLiveLog(uid);
        } else {
          //主播进入直播间直接发送自己推流
          await this.publishSelf();
        }
        await this.joinReady();
        this.afterJoin();
      })
      .catch((err: any) => {
        console.error('进入频道失败：', err);
      });
  }
  /* 发布本地视频 */
  async publishSelf() {
    try {
      let data = await Promise.all([
        /* 创建音频和视频轨道 */
        AgoraRTC.createMicrophoneAudioTrack(this.currentUsedDevice.audioDevice),
        AgoraRTC.createCameraVideoTrack(this.currentUsedDevice.videoDevice),
      ]);
      this.localTracks.audioTrack = data[0];
      this.localTracks.videoTrack = data[1];
      // console.log(this.localTracks);
      let remoteEle = document.getElementById('vice-video');
      if (remoteEle) {
        remoteEle.textContent = '';
        remoteEle.style.display = 'block';
      }
      this.localTracks.videoTrack.play('vice-video'); //播放自己视频渲染
      if (this.tools['audio']) {
        this.localTracks.audioTrack.setEnabled(false);
      } else {
        this.localTracks.audioTrack.setEnabled(true);
      }

      if (this.processor && this.localTracks.videoTrack) {
        // 将插件注入 SDK 内的视频处理管道
        this.localTracks.videoTrack
          .pipe(this.processor)
          .pipe(this.localTracks.videoTrack.processorDestination);
        // 开启美颜
        await this.processor.enable();
      }
      await this.client.publish(Object.values(this.localTracks));
    } catch (err) {
      console.log('发布本地视频失败：', err);
      // history.back()
      this.alertTips('发布本地视频失败，请检查摄像头是否授权或正常', '提示');
      this.client.leave();
    }
  }
  /* 设置各项美颜参数 */
  async setBeautyOptions() {
    this.processor.setOptions({
      lighteningContrastLevel: 2, // 对比度
      lighteningLevel: 0.8, // 亮度
      smoothnessLevel: 0.8, // 平滑度
      sharpnessLevel: 0.5, // 锐化程度
      rednessLevel: 0.5, // 红润度
    });
    this.tools['glorify'] = true;
  }

  /* 订阅远程视频 */
  async joinReady() {
    this.client.remoteUsers.forEach((user: any) => {
      // console.log('remoteUsers', user.uid);
      this.client.subscribe(user, 'audio').then((audioTrack: any) => {
        // this.user_published_list.add(user);
        if (!this.user_published_list.find((item) => item.uid === user.uid)) {
          this.user_published_list.push(user);
        }
        audioTrack.setVolume(100);
        audioTrack.play();
      });
      this.client.subscribe(user, 'video').then((videoTrack: any) => {
        let remoteEle = document.getElementById('video');
        if (remoteEle) {
          remoteEle.textContent = '';
        }
        videoTrack.play('video');
      });
    });
    this.client.on('user-joined', (user: any) => {
      console.log(user, `${user.uid} 加入频道`);
    });
    this.client.on('user-published', async (user: any, mediaType: string) => {
      console.log('用户推流成功', user);
      await this.client.subscribe(user, mediaType);
      let remoteEle = document.getElementById('video');
      if (remoteEle) {
        remoteEle.textContent = '';
      }
      if (mediaType === 'video') {
        user.videoTrack.play('video');
        this.alert?.dismiss();
      }
      if (mediaType === 'audio') {
        user.audioTrack.play();
        // this.user_published_list.add(user);
        if (!this.user_published_list.find((item) => item.uid === user.uid)) {
          this.user_published_list.push(user);
        }
      }
    });
    this.client.on('user-unpublished', async (user: any, mediaType: string) => {
      if (mediaType === 'audio') {
        console.log('对方已静音');
        // this.user_published_list.delete(user);
        let idx = this.user_published_list.findIndex(
          (item) => item.uid === user.uid
        );
        if (idx >= 0) {
          this.user_published_list.splice(idx, 1);
        }
      }
      if (mediaType === 'video') {
        console.log('用户取消推流');
        // let remoteEle = document.getElementById('video');
        // if (remoteEle) {
        //   remoteEle.textContent = '对方已离开直播间';
        // }
        // // this.client.leave();
        // this.alertTips('对方已离开直播间');
      }
    });
    // 注册用户离开事件处理函数
    this.client.on('user-left', (user: any) => {
      console.log(`用户 ${user.uid} 离开了频道`);
      //主播离开，停止计时计费
      if (user.uid !== 100001) this.client.leave();
      this.alertTips('对方已离开直播间');
    });
    this.client.on(
      'connection-state-change',
      (curState: any, prevState: any) => {
        this.connection_state = curState;
        if (
          curState == 'RECONNECTING' ||
          curState == 'DISCONNECTED' ||
          curState == 'DISCONNECTING'
        ) {
          this.timer && clearTimeout(this.timer);
          this.timer_countdown && clearInterval(this.timer_countdown);
          if (!this.isAnchor) {
            //用户离开直播间，断开与主播状态连接频道
            this.msgSer.unsubscribeMessage(this.room?.get('user')?.id);
            this.isOpenEvaluate = true;
          }
          console.log(this.router.url);
          if (this.router.url.indexOf('/live/link-room/') == 0)
            curState == 'DISCONNECTED' && history.back();
        }
        console.log('live状态变更：', this.connection_state);
      }
    );
    this.monitorDevices();
  }
  async createLiveLog(uid: string) {
    let profile = JSON.parse(localStorage.getItem('profile') || '{}');
    let obj = Parse.Object.extend('LiveLog');
    let liveLog = new obj();
    liveLog.set('title', `与${profile?.name || profile?.mobile}进行直播`);
    liveLog.set('uid', String(uid));
    liveLog.set('company', {
      __type: 'Pointer',
      className: 'Company',
      objectId: this.company,
    });
    liveLog.set('room', {
      __type: 'Pointer',
      className: 'Room',
      objectId: this.room?.id,
    });
    liveLog.set('user', {
      __type: 'Pointer',
      className: '_User',
      objectId: Parse.User.current()?.id,
    });
    liveLog.set('profile', {
      __type: 'Pointer',
      className: 'Profile',
      objectId: this.room?.get('profile')?.id,
    });
    this.liveLog = await liveLog.save();
  }
  /* 连线成功立即创建直播记录，同步获取剩余可通话时长，并且开始计时 */
  async afterJoin() {
    this.timer && clearTimeout(this.timer);
    this.timer_countdown && clearInterval(this.timer_countdown);
    const targetUser = this.client.remoteUsers?.find(
      (user: any) => user.uid !== 100001
    ); //排出超管
    console.log(targetUser);
    if (this.client.remoteUsers.length > 0 && targetUser) {
      if (this.isAnchor) {
        //如果是主播，进入获取remoteUsers.user获取livelog再获取对方剩余通话时长
        this.getLiveLog(targetUser.uid);
      } else {
        let query = new Parse.Query('LiveLog');
        query.equalTo('objectId', this.liveLog?.id);
        query.equalTo('isLive', true);
        query.select('objectId');
        const resultData = await query.first();
        if (resultData?.id) {
          //首次进入至少计时2分钟，不足2分钟按2分钟计算扣时
          await this.publishSelf();
          await this.get_duration();
          this.computeDuration(60000 * 2);
        } else {
          this.timer = setTimeout(() => {
            this.afterJoin();
          }, 1000);
        }
      }
    } else {
      this.timer = setTimeout(() => {
        this.afterJoin();
      }, 1000);
    }
  }
  async getLiveLog(tarUid: string) {
    // let uid = this.client.remoteUsers[0].uid;
    this.timer && clearTimeout(this.timer);
    let query = new Parse.Query('LiveLog');
    query.equalTo('uid', String(tarUid));
    query.equalTo('room', this.room?.id);
    query.notEqualTo('isDeleted', true);
    query.notEqualTo('isLive', true);
    query.descending('createdAt');
    this.liveLog = await query.first();
    if (this.liveLog?.id) {
      this.liveLog?.set('isLive', true);
      await this.liveLog?.save();
      await this.get_duration();
      this.getCallDuration();
      return;
    }
    this.timer = setTimeout(() => {
      this.getLiveLog(tarUid);
    }, 1000);
  }
  async get_duration() {
    this.timer_countdown && clearInterval(this.timer_countdown);
    let url = 'https://server.fmode.cn/api/ailiao/remain_second';
    let params = {
      rid: this.room?.id,
      uid: this.liveLog?.get('user')?.id || this.liveLog?.get('user')?.objectId,
    };
    let data = await this.http.httpRequst(url, params, 'POST');
    console.log(data);
    this.surplusNumber = data.data ?? 0;
    this.countdown = this.surplusNumber; // 初始化倒计时
    let arr = ['CONNECTING', 'CONNECTED'];
    if (arr.includes(this.connection_state as any)) {
      if (this.countdown <= 120) {
        this.alertTips('剩余通话时间不足2分钟，请及时充值');
      }
      this.startCountdown();
    }
  }

  startCountdown() {
    this.timer_countdown = setInterval(() => {
      if (this.countdown > 0) {
        this.countdown--;
        // console.log(this.countdown);
      } else {
        clearInterval(this.timer_countdown);
        // history.back()
        this.alertTips('通话时间结束');
        this.client.leave(); // 结束通话
      }
    }, 1000);
  }
  /* 开始计时 */
  async computeDuration(num?: number) {
    //每10秒保存一次数据
    this.timer && clearTimeout(this.timer);
    let p = JSON.parse(this.profile);
    console.log(p);
    let url = 'https://server.fmode.cn/api/ailiao/count/duration';
    let params = {
      company: this.company,
      profile: p?.objectId,
      rid: this.room?.id,
      uid: Parse.User.current()?.id,
      duration: num ? num / 1000 : 10,
      logid: this.liveLog?.id,
    };
    let data = await this.http.httpRequst(url, params, 'POST');
    console.log(data);
    this.timer = setTimeout(() => {
      this.computeDuration();
    }, num ?? 10000);
  }
  /* 主播每10s获取一次对方可通话时长 */
  getCallDuration() {
    this.timer && clearTimeout(this.timer);
    this.timer = setTimeout(async () => {
      await this.get_duration();
      let arr = ['CONNECTING', 'CONNECTED'];
      if (arr.includes(this.connection_state as any)) {
        this.getCallDuration();
      }
    }, 10000);
  }
  /* 监听音视频设备插拔 */
  monitorDevices() {
    AgoraRTC.onMicrophoneChanged = async (changedDevice: any) => {
      // 插入麦克风设备时，切换到新插入的设备
      if (changedDevice.state === 'ACTIVE') {
        this.localTracks.audioTrack.setDevice(changedDevice.device.deviceId);
        this.currentUsedDevice.audioDevice = changedDevice.device.deviceId;

        // 拔出设备为当前设备时，切换到一个已有的设备
      } else if (
        changedDevice.device.label ===
        this.localTracks.audioTrack.getTrackLabel()
      ) {
        const oldMicrophones = await AgoraRTC.getMicrophones();
        oldMicrophones[0] &&
          this.localTracks.audioTrack.setDevice(oldMicrophones[0].deviceId);
        this.currentUsedDevice.audioDevice = oldMicrophones[0].deviceId;
      }
    };

    AgoraRTC.onCameraChanged = async (changedDevice: any) => {
      // 插入相机设备时，切换到新插入的设备
      if (changedDevice.state === 'ACTIVE') {
        this.localTracks.videoTrack.setDevice(changedDevice.device.deviceId);
        this.currentUsedDevice.videoDevice = changedDevice.device.deviceId;
        // 拔出设备为当前设备时，切换到一个已有的设备
      } else if (
        changedDevice.device.label ===
        this.localTracks.videoTrack.getTrackLabel()
      ) {
        const oldCameras = await AgoraRTC.getCameras();
        oldCameras[0] &&
          this.localTracks.videoTrack.setDevice(oldCameras[0].deviceId);
        this.currentUsedDevice.videoDevice = oldCameras[0].deviceId;
      }
    };
  }
  /* 关开麦 */
  async updatePublishedAudioTrack() {
    this.tools['audio'] = !this.tools['audio'];
    if (this.tools['audio'] && this.localTracks.audioTrack) {
      await this.localTracks.audioTrack.setEnabled(false);
      console.log('停止推送音频');
    } else {
      await this.localTracks.audioTrack.setEnabled(true);
      console.log('恢复推送音频');
    }
    // await this.client.unpublish(this.localTracks.audioTrack);
    return true;
  }
  /* 静音 */
  async muteAudio() {
    this.tools['mute'] = !this.tools['mute'];
    let list = Array.from(this.user_published_list);
    for (let index = 0; index < list.length; index++) {
      const user = list[index];
      if (this.tools['mute']) {
        console.log('静音');
        await this.client.unsubscribe(user, 'audio');
      } else {
        await this.client.subscribe(user, 'audio');
        console.log('恢复声音');
      }
    }
  }

  /* 切换摄像头 */
  async changeCamera() {
    const oldCameras = await AgoraRTC.getCameras(true);
    console.log('oldCameras：', oldCameras);
    let newCamers = oldCameras.find(
      (item: any) => item.deviceId !== this.currentUsedDevice.videoDevice
    );
    console.log(newCamers);
    newCamers &&
      (await this.localTracks.videoTrack.setDevice(newCamers.deviceId));
    // .then(() => {
    //   this.tools['camera'] = !this.tools['camera'];
    //   this.currentUsedDevice.videoDevice = newCamers.deviceId;
    // })
    // .catch((err: any) => {
    //   console.log('set device error', err);
    //   this.tools['camera'] = !this.tools['camera'];
    //   this.currentUsedDevice.videoDevice = newCamers.deviceId;
    //   this.alertTips('切换摄像头失败');
    // });
    this.tools['camera'] = !this.tools['camera'];
    this.currentUsedDevice.videoDevice = newCamers.deviceId;
    return true;
  }
  /* 切换美颜 */
  changeBeauty() {
    if (!this.tools['glorify']) {
      this.setBeautyOptions();
    } else {
      // 关闭美颜
      this.processor.setOptions({
        lighteningContrastLevel: 0,
        lighteningLevel: 0,
        smoothnessLevel: 0,
        sharpnessLevel: 0,
        rednessLevel: 0,
      });
      this.tools['glorify'] = false;
    }
  }
  /* 提示 */
  async alertTips(message: string, title?: string, callBack?: Function) {
    this.alert = await this.alertController.create({
      header: title || '提示',
      message: message,
      backdropDismiss: false,
      buttons: [
        {
          text: '确认',
          handler: () => {
            callBack && callBack();
          },
        },
      ],
    });
    await this.alert.present();
  }
}
