package com.xyw.console.asset.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xyw.console.asset.dto.*;
import com.xyw.console.asset.entity.PhoneAssetEntity;
import com.xyw.console.asset.exception.PhoneAssetNotFoundException;
import com.xyw.console.asset.exception.PhoneAssetValidationException;
import com.xyw.console.asset.mapper.PhoneAssetMapper;
import java.time.LocalDateTime;
import java.util.List;
import org.springframework.stereotype.Service;

@Service
public class PhoneAssetService {
  private final PhoneAssetMapper mapper;
  /** 代码作用（白话）：接收手机号资产表的数据库访问入口。关联文件：PhoneAssetMapper.java、PhoneAssetController.java。关联逻辑（调用链/数据流）：Controller -> Service -> Mapper -> as_phone_asset。 */
  public PhoneAssetService(PhoneAssetMapper mapper) { this.mapper = mapper; }
  /** 代码作用（白话）：按分页、手机号片段、ICCID、实名人和使用状态读取未删除资产。关联文件：PhoneAssetPageQuery.java、PhoneAssetController.java。关联逻辑（调用链/数据流）：GET 参数 -> 查询条件 -> Mapper -> Response。 */
  public PhoneAssetPageResponse page(PhoneAssetPageQuery query) {
    Page<PhoneAssetEntity> page = mapper.selectPage(new Page<>(query.resolvedPage(), query.resolvedSize()), activeQuery(query));
    List<PhoneAssetResponse> records = page.getRecords().stream().map(this::toResponse).toList();
    return new PhoneAssetPageResponse(records, page.getTotal(), query.resolvedPage(), query.resolvedSize());
  }
  /** 代码作用（白话）：组合现有资产筛选条件，保证旧的完整号码与 ICCID 参数继续可用。关联文件：PhoneAssetPageQuery.java、PhoneAssetEntity.java。关联逻辑（调用链/数据流）：Query DTO -> LambdaQueryWrapper -> SQL where 条件。 */
  private LambdaQueryWrapper<PhoneAssetEntity> activeQuery(PhoneAssetPageQuery query) {
    LambdaQueryWrapper<PhoneAssetEntity> wrapper = new LambdaQueryWrapper<PhoneAssetEntity>().eq(PhoneAssetEntity::getDeleteTime, 0L);
    applyPhoneNumberFilter(wrapper, query.phoneNumber());
    wrapper.eq(hasText(query.iccid()), PhoneAssetEntity::getIccid, query.iccid())
        .like(hasText(query.realNameOwner()), PhoneAssetEntity::getRealNameOwner, query.realNameOwner())
        .eq(hasText(query.disposalStatus()), PhoneAssetEntity::getDisposalStatus, query.disposalStatus())
        .orderByDesc(PhoneAssetEntity::getId);
    return wrapper;
  }
  /** 代码作用（白话）：按 3、4、7、11 位手机号规则追加查询条件，其余长度保持原有精确查询。关联文件：PhoneAssetPageQuery.java、PhoneAssetView.js。关联逻辑（调用链/数据流）：搜索输入 -> phoneNumber 参数 -> 前缀/后缀/精确 SQL 匹配。 */
  private void applyPhoneNumberFilter(LambdaQueryWrapper<PhoneAssetEntity> wrapper, String phoneNumber) {
    if (!hasText(phoneNumber)) return;
    if (phoneNumber.length() == 3) wrapper.likeRight(PhoneAssetEntity::getPhoneNumber, phoneNumber);
    else if (phoneNumber.length() == 4) wrapper.likeLeft(PhoneAssetEntity::getPhoneNumber, phoneNumber);
    else if (phoneNumber.length() == 7) wrapper.likeRight(PhoneAssetEntity::getPhoneNumber, phoneNumber.substring(0, 3)).likeLeft(PhoneAssetEntity::getPhoneNumber, phoneNumber.substring(3));
    else wrapper.eq(PhoneAssetEntity::getPhoneNumber, phoneNumber);
  }
  /** 代码作用（白话）：判断筛选文本是否有内容，避免空字符串参与数据库筛选。关联文件：PhoneAssetPageQuery.java、PhoneAssetService.java。关联逻辑（调用链/数据流）：请求参数 -> hasText -> 是否追加条件。 */
  private boolean hasText(String value) { return value != null && !value.isBlank(); }
  /** 代码作用（白话）：新增手机号资产并初始化审计字段和内部关联快照。关联文件：PhoneAssetSaveRequest.java、PhoneAssetMapper.java、PhoneAssetController.java。关联逻辑（调用链/数据流）：POST 请求 -> DTO -> Service.create -> Mapper.insert -> as_phone_asset。 */
  public PhoneAssetResponse create(PhoneAssetSaveRequest request) { PhoneAssetEntity entity=new PhoneAssetEntity(); applyEditableFields(entity,request); entity.setNumberType("SELF"); LocalDateTime now=LocalDateTime.now(); entity.setCreateTime(now); entity.setUpdateTime(now); entity.setDeleteTime(0L); entity.setLinkedWecomAccounts("[]"); entity.setLinkedWechatAccounts("[]"); entity.setLinkedDouyinAccounts("[]"); entity.setLinkedDomainAccounts("[]"); entity.setLinkedMerchants("[]"); if(mapper.insert(entity)!=1) throw new IllegalStateException("手机号资产新增失败"); return toResponse(entity); }
  /** 代码作用（白话）：更新有效资产的用户可写字段。关联文件：PhoneAssetSaveRequest.java、PhoneAssetMapper.java、PhoneAssetController.java。关联逻辑（调用链/数据流）：PUT 请求 -> Service 查找 -> Mapper.updateById -> Response。 */
  public PhoneAssetResponse update(Long id, PhoneAssetSaveRequest request) { PhoneAssetEntity entity=requireActiveEntity(id); applyEditableFields(entity,request); entity.setUpdateTime(LocalDateTime.now()); if(mapper.updateById(entity)!=1) throw new PhoneAssetNotFoundException("手机号资产不存在或已删除"); return toResponse(entity); }
  /** 代码作用（白话）：将资产标记为删除，供 Controller 删除接口调用。关联文件：PhoneAssetController.java、PhoneAssetMapper.java。关联逻辑（调用链/数据流）：DELETE 请求 -> Service -> Mapper.updateById。 */
  public void softDelete(Long id) { PhoneAssetEntity entity=requireActiveEntity(id); entity.setDeleteTime(System.currentTimeMillis()); entity.setUpdateTime(LocalDateTime.now()); if(mapper.updateById(entity)!=1) throw new PhoneAssetNotFoundException("手机号资产不存在或已删除"); }
  /** 代码作用（白话）：读取一条仍有效的资产，供编辑和删除共用。关联文件：PhoneAssetMapper.java、PhoneAssetExceptionHandler.java。关联逻辑（调用链/数据流）：Service 查询 -> 无记录 -> 404 异常。 */
  private PhoneAssetEntity requireActiveEntity(Long id){ PhoneAssetEntity entity=mapper.selectOne(new LambdaQueryWrapper<PhoneAssetEntity>().eq(PhoneAssetEntity::getDeleteTime,0L).eq(PhoneAssetEntity::getId,id)); if(entity==null) throw new PhoneAssetNotFoundException("手机号资产不存在或已删除"); return entity; }
  /** 代码作用（白话）：把表单允许提交的字段写入实体，并统一处理手机号和默认使用状态。关联文件：PhoneAssetSaveRequest.java、PhoneAssetEntity.java。关联逻辑（调用链/数据流）：弹窗表单 -> DTO -> Entity -> Mapper 保存。 */
  private void applyEditableFields(PhoneAssetEntity entity, PhoneAssetSaveRequest request){ entity.setPhoneNumber(normalizePhoneNumber(request.phoneNumber())); entity.setCardType(request.cardType()); entity.setIccid(request.iccid()); entity.setRealNameOwner(request.realNameOwner()); entity.setManagementType(request.managementType()); entity.setDisposalStatus(request.disposalStatus()==null||request.disposalStatus().isBlank()?"正常使用":request.disposalStatus()); entity.setDeviceId(request.deviceId()); }
  /** 代码作用（白话）：按已确认规则清理手机号并验证其最终格式。关联文件：PhoneAssetSaveRequest.java、PhoneAssetExceptionHandler.java。关联逻辑（调用链/数据流）：前端输入 -> 去空格和 +86 -> 格式失败返回 400。 */
  private String normalizePhoneNumber(String value){ String normalized=value==null?"":value.trim(); if(normalized.startsWith("+86")) normalized=normalized.substring(3); if(!normalized.matches("\\d{11}")) throw new PhoneAssetValidationException("手机号必须是 11 位数字"); return normalized; }
  /** 代码作用（白话）：只挑选列表需要展示的字段。关联文件：PhoneAssetResponse.java、PhoneAssetEntity.java。关联逻辑（调用链/数据流）：实体 -> DTO -> ApiResponse -> 表格。 */
  private PhoneAssetResponse toResponse(PhoneAssetEntity entity){ return new PhoneAssetResponse(entity.getId(),entity.getPhoneNumber(),entity.getNumberType(),entity.getSourceAssetType(),entity.getSourceAssetId(),entity.getCardType(),entity.getIccid(),entity.getRealNameOwner(),entity.getManagementType(),entity.getDisposalStatus(),entity.getDeviceId(),entity.getRelationSyncedAt()); }
}