/**
 * 电子围栏坐标点模型
 * 用于存储围栏绘制过程中用户选定的经纬度坐标点
 */

const { DataTypes } = require('sequelize');
const { sequelize } = require('../config/database-simple');
const BaseModel = require('./BaseModel');

class ElectronicFencePoint extends BaseModel {
  // 模型属性定义
  static attributes = {
    id: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      autoIncrement: true,
      comment: '主键ID'
    },
    fence_id: {
      type: DataTypes.INTEGER,
      allowNull: false,
      comment: '关联的围栏ID',
      references: {
        model: 'electronic_fences',
        key: 'id'
      }
    },
    point_order: {
      type: DataTypes.INTEGER,
      allowNull: false,
      comment: '坐标点在围栏中的顺序（从0开始）'
    },
    longitude: {
      type: DataTypes.DECIMAL(10, 7),
      allowNull: false,
      comment: '经度'
    },
    latitude: {
      type: DataTypes.DECIMAL(10, 7),
      allowNull: false,
      comment: '纬度'
    },
    point_type: {
      type: DataTypes.ENUM('corner', 'control', 'marker'),
      allowNull: false,
      defaultValue: 'corner',
      comment: '坐标点类型：corner-拐角点，control-控制点，marker-标记点'
    },
    description: {
      type: DataTypes.TEXT,
      allowNull: true,
      comment: '坐标点描述信息'
    },
    is_active: {
      type: DataTypes.BOOLEAN,
      allowNull: false,
      defaultValue: true,
      comment: '是否激活'
    },
    created_by: {
      type: DataTypes.INTEGER,
      allowNull: true,
      comment: '创建人ID'
    },
    updated_by: {
      type: DataTypes.INTEGER,
      allowNull: true,
      comment: '更新人ID'
    }
  };

  // 模型选项
  static options = {
    tableName: 'electronic_fence_points',
    comment: '电子围栏坐标点表',
    indexes: [
      {
        fields: ['fence_id']
      },
      {
        fields: ['fence_id', 'point_order']
      },
      {
        fields: ['longitude', 'latitude']
      },
      {
        fields: ['point_type']
      },
      {
        fields: ['is_active']
      }
    ],
    hooks: {
      beforeCreate: (point, options) => {
        // 创建前钩子
        if (!point.point_order && point.point_order !== 0) {
          // 如果没有指定顺序，自动计算
          return ElectronicFencePoint.count({
            where: { fence_id: point.fence_id }
          }).then(count => {
            point.point_order = count;
          });
        }
      }
    }
  };

  // 实例方法
  /**
   * 获取坐标点的经纬度对象
   * @returns {Object} 包含lng和lat的对象
   */
  getCoordinates() {
    return {
      lng: parseFloat(this.longitude),
      lat: parseFloat(this.latitude)
    };
  }

  /**
   * 设置坐标点
   * @param {number} lng - 经度
   * @param {number} lat - 纬度
   */
  setCoordinates(lng, lat) {
    this.longitude = lng;
    this.latitude = lat;
  }

  /**
   * 转换为前端格式
   * @returns {Object} 前端使用的坐标点格式
   */
  toFrontendFormat() {
    return {
      id: this.id,
      fenceId: this.fence_id,
      pointOrder: this.point_order,
      lng: parseFloat(this.longitude),
      lat: parseFloat(this.latitude),
      pointType: this.point_type,
      description: this.description,
      isActive: this.is_active,
      createdAt: this.created_at,
      updatedAt: this.updated_at
    };
  }

  /**
   * 计算到另一个点的距离（米）
   * @param {ElectronicFencePoint} otherPoint - 另一个坐标点
   * @returns {number} 距离（米）
   */
  distanceTo(otherPoint) {
    const R = 6371000; // 地球半径（米）
    const lat1 = this.latitude * Math.PI / 180;
    const lat2 = otherPoint.latitude * Math.PI / 180;
    const deltaLat = (otherPoint.latitude - this.latitude) * Math.PI / 180;
    const deltaLng = (otherPoint.longitude - this.longitude) * Math.PI / 180;

    const a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +
              Math.cos(lat1) * Math.cos(lat2) *
              Math.sin(deltaLng / 2) * Math.sin(deltaLng / 2);
    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

    return R * c;
  }

  /**
   * 检查坐标点是否在指定范围内
   * @param {number} centerLng - 中心点经度
   * @param {number} centerLat - 中心点纬度
   * @param {number} radius - 半径（米）
   * @returns {boolean} 是否在范围内
   */
  isWithinRadius(centerLng, centerLat, radius) {
    const centerPoint = {
      longitude: centerLng,
      latitude: centerLat
    };
    return this.distanceTo(centerPoint) <= radius;
  }

  // 静态方法
  /**
   * 根据围栏ID获取所有坐标点
   * @param {number} fenceId - 围栏ID
   * @param {Object} options - 查询选项
   * @returns {Promise<Array>} 坐标点数组
   */
  static async getByFenceId(fenceId, options = {}) {
    const defaultOptions = {
      where: {
        fence_id: fenceId,
        is_active: true
      },
      order: [['point_order', 'ASC']]
    };

    return this.findAll({
      ...defaultOptions,
      ...options
    });
  }

  /**
   * 批量创建坐标点
   * @param {number} fenceId - 围栏ID
   * @param {Array} points - 坐标点数组
   * @param {Object} options - 创建选项
   * @returns {Promise<Array>} 创建的坐标点数组
   */
  static async createPoints(fenceId, points, options = {}) {
    const pointsData = points.map((point, index) => ({
      fence_id: fenceId,
      point_order: index,
      longitude: point.lng,
      latitude: point.lat,
      point_type: point.type || 'corner',
      description: point.description || null,
      created_by: options.createdBy || null
    }));

    return this.bulkCreate(pointsData, options);
  }

  /**
   * 更新围栏的所有坐标点
   * @param {number} fenceId - 围栏ID
   * @param {Array} points - 新的坐标点数组
   * @param {Object} options - 更新选项
   * @returns {Promise<Array>} 更新后的坐标点数组
   */
  static async updateFencePoints(fenceId, points, options = {}) {
    const transaction = options.transaction || await sequelize.transaction();
    
    try {
      // 删除现有坐标点
      await this.destroy({
        where: { fence_id: fenceId },
        transaction
      });

      // 创建新的坐标点
      const newPoints = await this.createPoints(fenceId, points, {
        ...options,
        transaction
      });

      if (!options.transaction) {
        await transaction.commit();
      }

      return newPoints;
    } catch (error) {
      if (!options.transaction) {
        await transaction.rollback();
      }
      throw error;
    }
  }

  /**
   * 获取围栏的边界框
   * @param {number} fenceId - 围栏ID
   * @returns {Promise<Object>} 边界框对象
   */
  static async getFenceBounds(fenceId) {
    const points = await this.getByFenceId(fenceId);
    
    if (points.length === 0) {
      return null;
    }

    const lngs = points.map(p => parseFloat(p.longitude));
    const lats = points.map(p => parseFloat(p.latitude));

    return {
      minLng: Math.min(...lngs),
      maxLng: Math.max(...lngs),
      minLat: Math.min(...lats),
      maxLat: Math.max(...lats),
      center: {
        lng: (Math.min(...lngs) + Math.max(...lngs)) / 2,
        lat: (Math.min(...lats) + Math.max(...lats)) / 2
      }
    };
  }
}

// 初始化模型
ElectronicFencePoint.init(ElectronicFencePoint.attributes, {
  ...ElectronicFencePoint.options,
  sequelize,
  modelName: 'ElectronicFencePoint'
});

module.exports = ElectronicFencePoint;
