package com.usky.vpp.controller.web;

import com.usky.common.core.bean.ApiResult;
import com.usky.common.core.bean.CommonPage;
import com.usky.vpp.domain.VppDevice;
import com.usky.vpp.domain.VppResourcePoint;
import com.usky.vpp.domain.VppSite;
import com.usky.vpp.service.VppBaselineService;
import com.usky.vpp.service.VppDeviceService;
import com.usky.vpp.service.VppResourcePointService;
import com.usky.vpp.service.VppSiteService;
import com.usky.vpp.service.vo.DeviceRequest;
import com.usky.vpp.service.vo.ResourcePointRequest;
import com.usky.vpp.service.vo.SiteBaselineVO;
import com.usky.vpp.service.vo.SiteDeclaredCapacityVO;
import com.usky.vpp.service.vo.SiteConfigDetailVO;
import com.usky.vpp.service.vo.SiteConfigRequest;
import com.usky.vpp.service.vo.SiteListVO;
import com.usky.vpp.service.vo.SiteRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

/**
 * 站点管理接口
 * <p>网关前缀: /prod-api/service-vpp/site</p>
 */
@RestController
@RequestMapping("/site")
public class SiteController {

    @Autowired
    private VppSiteService vppSiteService;
    @Autowired
    private VppBaselineService vppBaselineService;
    @Autowired
    private VppResourcePointService vppResourcePointService;
    @Autowired
    private VppDeviceService vppDeviceService;

    /**
     * 站点管理 - 分页列表
     * <p>支持按 siteName（站点名称）、province/city/district（区域）、resourceType（站点下资源类型）筛选。</p>
     */
    @GetMapping
    public ApiResult<CommonPage<SiteListVO>> pageSite(@RequestParam(required = false) Map<String, Object> params) {
        return ApiResult.success(vppSiteService.pageSiteList(params));
    }

    /**
     * 站点管理 - 新增
     */
    @PostMapping
    public ApiResult<VppSite> createSite(@RequestBody SiteRequest body) {
        return ApiResult.success(vppSiteService.createSite(body));
    }

    /**
     * 站点管理 - 详情
     */
    @GetMapping("/{id}")
    public ApiResult<VppSite> getSite(@PathVariable("id") Long id) {
        return ApiResult.success(vppSiteService.getSite(id));
    }

    /**
     * 站点管理 - 编辑
     */
    @PutMapping("/{id}")
    public ApiResult<Void> updateSite(@PathVariable("id") Long id, @RequestBody SiteRequest body) {
        vppSiteService.updateSite(id, body);
        return ApiResult.success();
    }

    /**
     * 站点管理 - 删除（软删除）
     */
    @DeleteMapping("/{id}")
    public ApiResult<Void> deleteSite(@PathVariable("id") Long id) {
        vppSiteService.deleteSite(id);
        return ApiResult.success();
    }

    /**
     * 站点参数配置 - 查询
     * <p>包含采集频率、功率/SOC告警阈值、离线超时、响应优先级等。</p>
     */
    @GetMapping("/{siteId}/config")
    public ApiResult<SiteConfigDetailVO> getSiteConfig(@PathVariable("siteId") Long siteId) {
        return ApiResult.success(vppSiteService.getSiteConfigDetail(siteId));
    }

    /**
     * 站点参数配置 - 保存
     * <p>配置采集频率、告警阈值；responsePriority 写入站点响应优先级。</p>
     */
    @PutMapping("/{siteId}/config")
    public ApiResult<SiteConfigDetailVO> saveSiteConfig(@PathVariable("siteId") Long siteId,
                                                        @RequestBody SiteConfigRequest body) {
        return ApiResult.success(vppSiteService.saveSiteConfigDetail(siteId, body));
    }

    /**
     * 站点下设备列表
     */
    @GetMapping("/{siteId}/device")
    public ApiResult<CommonPage<VppDevice>> listSiteDevice(@PathVariable("siteId") Long siteId,
                                                           @RequestParam(required = false) Map<String, Object> params) {
        return ApiResult.success(vppDeviceService.listBySiteId(siteId, params));
    }

    /**
     * 站点下新增设备
     */
    @PostMapping("/{siteId}/device")
    public ApiResult<VppDevice> addSiteDevice(@PathVariable("siteId") Long siteId,
                                              @RequestBody DeviceRequest body) {
        return ApiResult.success(vppDeviceService.createDevice(siteId, body));
    }

    /**
     * 基线管理 - 负荷曲线
     * <p><b>GET</b> /site/{siteId}/baseline</p>
     * <p>完整路径：GET /prod-api/service-vpp/site/{siteId}/baseline</p>
     *
     * <p>根据站点 ID 与响应开始时间，返回需求响应基线管理页面所需的三条负荷曲线：</p>
     * <ul>
     *   <li>预测基线（黄色）：典型历史日同时段各时间点负荷均值 × 修正系数 K</li>
     *   <li>今日实际（绿色）：响应日当天 00:00 至响应开始时间的实测负荷</li>
     *   <li>昨日实际（蓝色）：响应日前一日全天实测负荷</li>
     * </ul>
     *
     * <p><b>路径参数</b></p>
     * <ul>
     *   <li>siteId — 站点 ID</li>
     * </ul>
     *
     * <p><b>Query 参数</b></p>
     * <ul>
     *   <li>responseStartTime — 响应开始时间，必填，格式 yyyy-MM-dd HH:mm:ss</li>
     * </ul>
     *
     * <p><b>典型历史日选取规则</b>（基于 Hutool 法定节假日 + 调休判定）</p>
     * <ul>
     *   <li>响应日为工作日：取邀约日前最近 5 个工作日；剔除响应当日、历史响应日（vpp_dr_event 已结束）</li>
     *   <li>响应日为非工作日：取邀约日前最近 3 个非工作日（含法定节假日）；剔除响应当日、历史响应日</li>
     * </ul>
     *
     * <p><b>修正系数 K</b>：取响应开始时间前连续 2 小时今日实测与同时段原始基线之比，限制在 0.7 ~ 1.2。</p>
     * <p>原始基线在本模块内对多历史日同时段各时间点（默认 10 分钟粒度）求平均，
     * 逐日调用 service-tsdb {@code queryHistoryDeviceData} 获取设备时序后聚合；
     * 设备范围为站点下 is_control=1 的资源点关联设备。</p>
     *
     * <p><b>响应 data：SiteBaselineVO</b></p>
     * <ul>
     *   <li>siteId / siteName — 站点信息</li>
     *   <li>responseStartTime — 响应开始时间</li>
     *   <li>responseDayType — WORKDAY（工作日）/ NON_WORKDAY（非工作日）</li>
     *   <li>responseDayTypeLabel — 工作日 / 非工作日</li>
     *   <li>referenceDates — 参与计算的典型历史日（yyyy-MM-dd）</li>
     *   <li>correctionFactorK — 日内修正系数 K</li>
     *   <li>dataSource — tsdb（时序库）</li>
     *   <li>points — 曲线点列表（BaselinePointVO：time、predictedBaselineKw、todayActualKw、yesterdayActualKw）</li>
     * </ul>
     *
     * <p><b>示例</b>：GET /site/1/baseline?responseStartTime=2026-07-08 19:00:00</p>
     */
    @GetMapping("/{siteId}/baseline")
    public ApiResult<SiteBaselineVO> getSiteBaseline(@PathVariable("siteId") Long siteId,
                                                     @RequestParam("responseStartTime") String responseStartTime) {
        return ApiResult.success(vppBaselineService.getSiteBaseline(siteId, responseStartTime));
    }

    /**
     * 响应申报容量和预估响应容量
     * <p><b>GET</b> /site/{siteId}/declared-capacity</p>
     * <p>完整路径：GET /prod-api/service-vpp/site/{siteId}/declared-capacity</p>
     *
     * <p>根据站点 ID、响应开始/结束时间，计算需求响应申报容量：</p>
     * <p><b>申报容量 = 响应时段内同时间段历史负荷均值 × 执行时段小时数 / 2</b></p>
     *
     * <p><b>Query 参数</b></p>
     * <ul>
     *   <li>responseStartTime — 响应开始时间，必填，格式 yyyy-MM-dd HH:mm:ss</li>
     *   <li>responseEndTime — 响应结束时间，必填，格式 yyyy-MM-dd HH:mm:ss（需与开始时间同一天）</li>
     * </ul>
     *
     * <p><b>典型历史日选取规则</b>（基于 Hutool 法定节假日 + 调休判定）</p>
     * <ul>
     *   <li>响应日为工作日：取邀约日前最近 5 个工作日；剔除响应当日、历史响应日（vpp_dr_event 已结束）和响应日 &gt;= 今日</li>
     *   <li>响应日为非工作日：取邀约日前最近 3 个非工作日（含法定节假日）；剔除响应当日、历史响应日和响应日 &gt;= 今日</li>
     * </ul>
     * <p>历史均值仅统计响应开始至结束时段。</p>
     *
     * <p><b>响应 data：SiteDeclaredCapacityVO</b></p>
     * <ul>
     *   <li>declaredCapacityKw — 申报容量 kW</li>
     *   <li>referenceDates — 参与计算的典型历史日</li>
     *   <li>points — 响应时段各时间点申报容量（DeclaredCapacityPointVO）</li>
     * </ul>
     *
     * <p><b>示例</b>：GET /site/1/declared-capacity?responseStartTime=2026-07-08 19:00:00&responseEndTime=2026-07-08 21:00:00</p>
     */
    @GetMapping("/{siteId}/declared-capacity")
    public ApiResult<SiteDeclaredCapacityVO> getSiteDeclaredCapacity(@PathVariable("siteId") Long siteId,
                                                                   @RequestParam("responseStartTime") String responseStartTime,
                                                                   @RequestParam("responseEndTime") String responseEndTime) {
        return ApiResult.success(vppBaselineService.getSiteDeclaredCapacity(siteId, responseStartTime, responseEndTime));
    }

    /**
     * 站点下资源点列表
     */
    @GetMapping("/{siteId}/resource")
    public ApiResult<CommonPage<VppResourcePoint>> listSiteResource(@PathVariable("siteId") Long siteId,
                                                                    @RequestParam(required = false) Map<String, Object> params) {
        return ApiResult.success(vppResourcePointService.listBySiteId(siteId, params));
    }

    /**
     * 站点下新增资源点
     */
    @PostMapping("/{siteId}/resource")
    public ApiResult<VppResourcePoint> addSiteResource(@PathVariable("siteId") Long siteId,
                                                       @RequestBody ResourcePointRequest body) {
        return ApiResult.success(vppResourcePointService.createResourcePoint(siteId, body));
    }
}
