/*
 * 文 件 名:  SquareLightCtlTemplate
 * 版    权:  华设设计集团股份有限公司
 * 描    述:  <描述>
 * 修 改 人:  lvwenbin
 * 修改时间:  2025/9/15
 * 跟踪单号:  <跟踪单号>
 * 修改单号:  <修改单号>
 * 修改内容:  <修改内容>
 */
package com.ruoyi.ems.core;

import com.alibaba.fastjson.support.retrofit.Retrofit2ConverterFactory;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.huashe.common.exception.Assert;
import com.ruoyi.common.core.utils.SpringUtils;
import com.ruoyi.ems.config.SquareLightCtlConfig;
import com.ruoyi.ems.model.CallData;
import com.ruoyi.ems.model.slightctl.AppLoginReq;
import com.ruoyi.ems.model.slightctl.AppLoginRes;
import com.ruoyi.ems.model.slightctl.DeviceInfo;
import com.ruoyi.ems.model.slightctl.SlcDevice;
import com.ruoyi.ems.model.slightctl.SlcProject;
import com.ruoyi.ems.model.slightctl.SlcProjectSubset;
import com.ruoyi.ems.model.slightctl.SlcResponse;
import com.ruoyi.ems.retrofit.SquareLightCtlApi;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.Retrofit;

import java.util.ArrayList;
import java.util.List;

/**
 * 广场灯控接口模板
 * <功能详细描述>
 *
 * @author lvwenbin
 * @version [版本号, 2025/9/15]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Slf4j
public class SquareLightCtlTemplate extends BaseApiTemplate {
    /**
     * 访问地址
     */
    protected String url;

    /**
     * 调用代理
     */
    protected final SquareLightCtlApi api;

    public SquareLightCtlTemplate(String restUrl) {
        this.url = restUrl;

        OkHttpClient httpClient = getClient();
        Retrofit retrofit = new Retrofit.Builder().baseUrl(restUrl)
            .addConverterFactory(Retrofit2ConverterFactory.create()).client(httpClient).build();
        this.api = retrofit.create(SquareLightCtlApi.class);
    }

    /**
     * 构造调用模板
     *
     * @param restUrl        服务地址 (http://ip:port)
     * @param connectTimeout 连接超时
     * @param readTimeout    读取超时
     * @param writeTimeout   写超时
     */
    public SquareLightCtlTemplate(String restUrl, int connectTimeout, int readTimeout, int writeTimeout) {
        super.connectTimeout = connectTimeout;
        super.readTimeout = readTimeout;
        super.writeTimeout = writeTimeout;
        this.url = restUrl;

        OkHttpClient httpClient = getClient();
        Retrofit retrofit = new Retrofit.Builder().baseUrl(restUrl)
            .addConverterFactory(Retrofit2ConverterFactory.create()).client(httpClient).build();
        api = retrofit.create(SquareLightCtlApi.class);
    }

    /**
     * 登录接口
     *
     * @param cfg 请求参数
     * @return 登录响应
     */
    public AppLoginRes appLogin(SquareLightCtlConfig cfg) {
        AppLoginRes appLoginRes = null;

        try {
            AppLoginReq req = new AppLoginReq();
            req.setLoginType(3);
            req.setClientId(cfg.getClientId());
            req.setUsername(cfg.getUserName());
            req.setPassword(cfg.getPassword());
            req.setTenantId(cfg.getTenantId());

            // 执行调用
            Call<String> call = api.appLogin(req);
            Response<String> response = call.execute();
            String res = response.body();
            log.debug("appLogin response:{}", res);
            Assert.notEmpty(res, -1, "获取Token失败");
            SlcResponse slcRes = JSON.parseObject(res, SlcResponse.class);
            Assert.notNull(slcRes, -1, "解析登录响应失败.");
            Assert.isTrue(200 == slcRes.getCode(), -1, "登录失败：" + slcRes.getMsg());
            appLoginRes = JSON.parseObject(slcRes.getData(), AppLoginRes.class);
        }
        catch (Exception e) {
            log.error("appLogin fail!", e);
        }

        return appLoginRes;
    }

    public synchronized String getToken() {
        SquareLightCtlConfig config = SpringUtils.getBean(SquareLightCtlConfig.class);
        AppLoginRes res = appLogin(config);
        return res.accessToken;
    }

    /**
     * 获取项目列表
     *
     * @return 登录响应
     */
    public CallData<SlcProject> getProjectList() {
        CallData<SlcProject> ret = null;
        String token = null;
        String resBody = null;

        try {
            SquareLightCtlConfig config = SpringUtils.getBean(SquareLightCtlConfig.class);
            token = getToken();

            Assert.notEmpty(token, -1, "获取Token失败");
            token = "Bearer " + token;

            // 执行调用
            Call<String> call = api.getProjectList(config.getClientId(), token);
            Response<String> response = call.execute();
            resBody = response.body();

            log.debug("getProjectList response:{}", resBody);
            Assert.notEmpty(resBody, -1, "获取项目列表失败");
            SlcResponse slcRes = JSON.parseObject(resBody, SlcResponse.class);
            Assert.notNull(slcRes, -1, "解析项目列表响应失败.");
            Assert.isTrue(200 == slcRes.getCode(), -1, slcRes.getMsg());
            ret = CallData.<SlcProject>builder().addCallParam("ClientId", config.getClientId())
                .addCallParam("token", token).setCallStatus(0).setResPayload(resBody)
                .setList(JSON.parseArray(slcRes.getData(), SlcProject.class)).build();
        }
        catch (Exception e) {
            log.error("getProjectList fail!", e);
            ret = CallData.<SlcProject>builder().addCallParam("token", token).setCallStatus(2).setResPayload(resBody)
                .build();
        }

        return ret;
    }

    /**
     * 获取项目分组列表
     *
     * @return 登录响应
     */
    public CallData<SlcProjectSubset> getProjectSubsetList(String projectId) {
        CallData<SlcProjectSubset> ret = null;
        String token = null;
        String resBody = null;

        try {
            SquareLightCtlConfig config = SpringUtils.getBean(SquareLightCtlConfig.class);

            token = getToken();
            Assert.notEmpty(token, -1, "获取Token失败");
            token = "Bearer " + token;

            Call<String> call = api.getProjectSubsetList(config.getClientId(), token, projectId);
            Response<String> response = call.execute();
            resBody = response.body();
            log.debug("getProjectSubsetList response:{}", resBody);
            Assert.notEmpty(resBody, -1, "获取项目分组列表失败");
            SlcResponse slcRes = JSON.parseObject(resBody, SlcResponse.class);
            Assert.notNull(slcRes, -1, "解析项目分组列表响应失败.");
            Assert.isTrue(200 == slcRes.getCode(), -1, slcRes.getMsg());

            ret = CallData.<SlcProjectSubset>builder().addCallParam("ClientId", config.getClientId())
                .addCallParam("token", token).addCallParam("projectId", projectId).setCallStatus(0)
                .setResPayload(resBody).setList(JSON.parseArray(slcRes.getData(), SlcProjectSubset.class)).build();

        }
        catch (Exception e) {
            log.error("getProjectSubsetList fail!", e);
            ret = CallData.<SlcProjectSubset>builder().addCallParam("token", token).addCallParam("projectId", projectId)
                .setCallStatus(2).setResPayload(resBody).build();
        }

        return ret;
    }

    /**
     * 获取设备列表
     *
     * @return 登录响应
     */
    public CallData<SlcDevice> getDeviceList(String projectId, String subsetId) {
        CallData.Builder<SlcDevice> builder = CallData.builder();

        try {
            SquareLightCtlConfig config = SpringUtils.getBean(SquareLightCtlConfig.class);

            String token = getToken();
            Assert.notEmpty(token, -1, "获取Token失败");
            token = "Bearer " + token;

            int pageNum = 1;
            int pageSize = 50;
            int total = 0;

            List<SlcDevice> list = new ArrayList<>();
            builder.addCallParam("projectId", projectId).addCallParam("token", token);

            do {
                // 执行调用
                Call<String> call = api.getDeviceList(config.getClientId(), token, projectId, subsetId, pageNum,
                    pageSize);

                Response<String> response = call.execute();
                String resBody = response.body();
                log.debug("getDeviceList response:{}", resBody);
                builder.appendResPayload(String.format("response(pageNum-%d): %s", pageNum, System.lineSeparator()))
                    .appendResPayload(resBody).appendResPayload(System.lineSeparator());
                Assert.notEmpty(resBody, -1, "获取设备列表失败");
                SlcResponse slcRes = JSON.parseObject(resBody, SlcResponse.class);
                Assert.notNull(slcRes, -1, "解析设备列表响应失败.");
                Assert.isTrue(200 == slcRes.getCode(), -1, slcRes.getMsg());
                total = slcRes.getTotal();
                list.addAll(JSON.parseArray(slcRes.getRows(), SlcDevice.class));
                pageNum++;
            }
            while (list.size() < total);

            builder.setList(list).setCallStatus(0);
        }
        catch (Exception e) {
            builder.setCallStatus(2);
            log.error("getDeviceList fail!", e);
        }

        return builder.build();
    }

    /**
     * 获取设备
     *
     * @return 登录响应
     */
    public CallData<DeviceInfo> getDeviceInfo(String projectId, String deviceId) {
        CallData.Builder<DeviceInfo> builder = CallData.builder();

        try {
            SquareLightCtlConfig config = SpringUtils.getBean(SquareLightCtlConfig.class);

            String token = getToken();
            Assert.notEmpty(token, -1, "获取Token失败");
            token = "Bearer " + token;

            // 执行调用
            builder.addCallParam("projectId", projectId);
            Call<String> call = api.getDeviceInfo(config.getClientId(), projectId, token, deviceId);
            Response<String> response = call.execute();
            String resBody = response.body();
            log.debug("getDeviceInfo response:{}", resBody);
            builder.appendResPayload(String.format("getDeviceInfo response: %s%s", resBody, System.lineSeparator()));
            SlcResponse slcRes = JSON.parseObject(resBody, SlcResponse.class);
            Assert.notNull(slcRes, -1, "解析设备状态响应失败.");
            Assert.isTrue(200 == slcRes.getCode(), -1, slcRes.getMsg());
            String data = slcRes.getData();
            DeviceInfo deviceInfo = JSON.parseObject(data, DeviceInfo.class);
            builder.setData(deviceInfo).setCallStatus(0);
        }
        catch (Exception e) {
            builder.setCallStatus(2);
            log.error("getDeviceInfo fail!", e);
        }

        return builder.build();
    }

    /**
     * 照明控制
     *
     * @return 登录响应
     */
    public CallData<Void> lightControl(String projectId, JSONObject req) {
        CallData.Builder<Void> builder = CallData.builder();

        try {
            SquareLightCtlConfig config = SpringUtils.getBean(SquareLightCtlConfig.class);

            String token = getToken();
            Assert.notEmpty(token, -1, "获取Token失败");
            token = "Bearer " + token;

            // 执行调用
            builder.addCallParam("token", token).addCallParam("body", req.toString())
                .addCallParam("projectId", projectId);
            Call<String> call = api.lightControl(config.getClientId(), projectId, token, req);
            Response<String> response = call.execute();
            String resBody = response.body();
            log.debug("lightControl response:{}", resBody);
            builder.setResPayload(resBody).setCallStatus(0);
            Assert.notEmpty(resBody, -1, "获取灯控响应失败");
            SlcResponse slcRes = JSON.parseObject(resBody, SlcResponse.class);
            Assert.notNull(slcRes, -1, "解析灯控响应失败.");
            Assert.isTrue(200 == slcRes.getCode(), -1, slcRes.getMsg());
        }
        catch (Exception e) {
            builder.setCallStatus(2);
            log.error("lightControl fail!", e);
        }

        return builder.build();
    }

    /**
     * 亮度调节
     *
     * @return 登录响应
     */
    public CallData<Void> controlBrightness(String projectId, JSONObject req) {
        CallData.Builder<Void> builder = CallData.builder();

        try {
            SquareLightCtlConfig config = SpringUtils.getBean(SquareLightCtlConfig.class);

            String token = getToken();
            Assert.notEmpty(token, -1, "获取Token失败");
            token = "Bearer " + token;

            // 执行调用
            builder.addCallParam("token", token).addCallParam("body", req.toString());
            Call<String> call = api.controlBrightness(config.getClientId(), projectId, token, req);
            Response<String> response = call.execute();
            String resBody = response.body();
            log.debug("controlBrightness response:{}", resBody);
            builder.setResPayload(resBody).setCallStatus(0);
            Assert.notEmpty(resBody, -1, "获取调光响应失败");
            SlcResponse slcRes = JSON.parseObject(resBody, SlcResponse.class);
            Assert.notNull(slcRes, -1, "解析调光响应失败.");
            Assert.isTrue(200 == slcRes.getCode(), -1, slcRes.getMsg());
        }
        catch (Exception e) {
            log.error("controlBrightness fail!", e);
        }

        return builder.build();
    }
}