package org.xyzh.system.controller;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson2.JSON;

import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.xyzh.api.auth.service.AuthService;
import org.xyzh.api.system.service.GuestService;
import org.xyzh.api.system.service.ModulePermissionService;
import org.xyzh.api.system.vo.PermissionVO;
import org.xyzh.common.core.domain.LoginDomain;
import org.xyzh.common.core.domain.LoginParam;
import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.core.page.PageRequest;
import org.xyzh.common.dto.sys.TbGuestDTO;
import org.xyzh.common.dto.sys.TbSysPermissionDTO;
import org.xyzh.common.dto.sys.TbSysUserDTO;
import org.xyzh.common.dto.sys.TbSysUserInfoDTO;
import org.xyzh.common.dto.sys.TbSysUserRoleDTO;
import org.xyzh.common.dto.sys.TbSysViewDTO;
import org.xyzh.common.utils.id.IdUtil;
import org.xyzh.common.utils.validation.ValidationUtils;
import org.xyzh.common.auth.utils.JwtTokenUtil;
import org.xyzh.common.redis.service.RedisService;

import io.swagger.v3.oas.annotations.Operation;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

/**
 * @description    来客控制器
 * @filename    GuestController.java
 * @author    yslg
 * @copyright xyzh
 * @since 2025-12-18
 */
@Validated
@RestController
@RequestMapping("/system/guest")
public class GuestController {

    @Autowired
    private GuestService guestService;

    @DubboReference(version = "1.0.0", group = "auth", timeout = 5000, check = false, retries = 0)
    private AuthService authService;

    @Autowired
    private ModulePermissionService modulePermissionService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private RedisService redisService;


    @PostMapping
    public ResultDomain<TbGuestDTO> createGuest(TbGuestDTO guest) {
        ValidationUtils.validate(guest, Arrays.asList(
            ValidationUtils.requiredString("name", "姓名"),
            ValidationUtils.atLeastOne(
                Arrays.asList("phone", "email", "wechatId"),
                Arrays.asList("电话", "邮箱", "微信ID")
            )
        ));
        return guestService.createGuest(guest);
    }

    @PutMapping
    public ResultDomain<TbGuestDTO> updateGuest(TbGuestDTO guest) {
        ValidationUtils.validate(guest, Arrays.asList(
            ValidationUtils.requiredString("name", "姓名"),
            ValidationUtils.atLeastOne(
                Arrays.asList("phone", "email", "wechatId"),
                Arrays.asList("电话", "邮箱", "微信ID")
            )
        ));
        return guestService.updateGuest(guest);
    }

    @DeleteMapping
    public ResultDomain<TbGuestDTO> deleteGuest(@NotNull String userId) {
        return guestService.deleteGuest(userId);
    }

    @GetMapping("/wechat/{wechatId}")
    public ResultDomain<TbGuestDTO> selectGuestByWechat(@PathVariable("wechatId") @NotBlank String wechatId){
        return guestService.selectGuestByWechatId(wechatId);
    }


    @GetMapping("/list")
    public ResultDomain<TbGuestDTO> listGuest(TbGuestDTO filter) {
        return guestService.selectGuestList(filter);
    }

    @PostMapping("/page")
    public ResultDomain<TbGuestDTO> pageGuest(PageRequest<TbGuestDTO> pageRequest) {
        return guestService.selectGuestPage(pageRequest);
    }

    // ========================= 微信小程序用户识别登录 =========================

    @Operation(summary = "微信小程序用户识别登录")
    @PostMapping("/identify")
    public ResultDomain<LoginDomain> identifyUser(@RequestBody LoginParam loginParam, HttpServletRequest request) {
        // 验证参数：必须有wechatId或phone
        if ((loginParam.getWechatId() == null || loginParam.getWechatId().trim().isEmpty()) 
            && (loginParam.getPhone() == null || loginParam.getPhone().trim().isEmpty())) {
            return ResultDomain.failure("微信ID或手机号不能为空");
        }

        // 设置登录类型为微信小程序
        loginParam.setLoginType("wechat_miniprogram");
        
        // 从 request 中提取客户端 IP 并设置到 loginParam
        loginParam.setClientIp(getClientIP(request));

        // 1. 尝试通过AuthService登录（员工）
        ResultDomain<LoginDomain> loginResult = authService.login(loginParam);
        if (loginResult.getSuccess() && loginResult.getData() != null) {
            // 登录成功，是系统员工
            return loginResult;
        }

        // 2. 登录失败，查询/注册来客
        return handleGuestLogin(loginParam);
    }

    /**
     * 处理来客登录：查询或注册来客，构造LoginDomain
     */
    private ResultDomain<LoginDomain> handleGuestLogin(LoginParam loginParam) {
        TbGuestDTO guest = null;

        // 优先用wechatId查询
        if (loginParam.getWechatId() != null && !loginParam.getWechatId().trim().isEmpty()) {
            ResultDomain<TbGuestDTO> guestResult = guestService.selectGuestByWechatId(loginParam.getWechatId());
            if (guestResult.getSuccess() && guestResult.getData() != null) {
                guest = guestResult.getData();
            }
        }

        // wechatId未找到，尝试用phone查询
        if (guest == null && loginParam.getPhone() != null && !loginParam.getPhone().trim().isEmpty()) {
            TbGuestDTO filter = new TbGuestDTO();
            filter.setPhone(loginParam.getPhone());
            ResultDomain<TbGuestDTO> guestResult = guestService.selectGuestOne(filter);
            if (guestResult.getSuccess() && guestResult.getData() != null) {
                guest = guestResult.getData();
                // 如果来客存在但wechatId为空，更新wechatId
                if (guest.getWechatId() == null && loginParam.getWechatId() != null) {
                    TbGuestDTO updateGuest = new TbGuestDTO();
                    updateGuest.setUserId(guest.getUserId());
                    updateGuest.setWechatId(loginParam.getWechatId());
                    guestService.updateGuest(updateGuest);
                    guest.setWechatId(loginParam.getWechatId());
                }
            }
        }

        // 3. 来客不存在，创建新来客
        if (guest == null) {
            TbGuestDTO newGuest = new TbGuestDTO();
            newGuest.setOptsn(IdUtil.getOptsn());
            newGuest.setUserId(IdUtil.generateID());
            newGuest.setWechatId(loginParam.getWechatId());
            newGuest.setPhone(loginParam.getPhone());
            newGuest.setName(loginParam.getUsername() != null ? loginParam.getUsername() : "来客");
            
            ResultDomain<TbGuestDTO> createResult = guestService.createGuest(newGuest);
            if (!createResult.getSuccess()) {
                return ResultDomain.failure("创建来客失败: " + createResult.getMessage());
            }
            guest = createResult.getData();
        }

        // 4. 构造来客的LoginDomain
        return ResultDomain.success("来客登录成功", buildGuestLoginDomain(guest));
    }

    /**
     * 从来客信息构造LoginDomain
     */
    private LoginDomain buildGuestLoginDomain(TbGuestDTO guest) {
        LoginDomain loginDomain = new LoginDomain();

        // 构造TbSysUserDTO，status设为guest
        TbSysUserDTO userDTO = new TbSysUserDTO();
        userDTO.setUserId(guest.getUserId());
        userDTO.setPhone(guest.getPhone());
        userDTO.setEmail(guest.getEmail());
        userDTO.setWechatId(guest.getWechatId());
        userDTO.setStatus("guest");  // 来客特殊状态
        loginDomain.setUser(userDTO);

        // 构造TbSysUserInfoDTO
        TbSysUserInfoDTO userInfoDTO = new TbSysUserInfoDTO();
        userInfoDTO.setUserId(guest.getUserId());
        userInfoDTO.setUsername(guest.getName());
        loginDomain.setUserInfo(userInfoDTO);

        // 设置角色信息
        List<TbSysUserRoleDTO> userRoles = new ArrayList<>();
        TbSysUserRoleDTO userRole = new TbSysUserRoleDTO();
        userRole.setUserId(guest.getUserId());
        userRole.setRoleId("role_guest");
        userRole.setDeptId("dept_root");
        userRoles.add(userRole);
        loginDomain.setUserRoles(userRoles);

        // 获取用户权限信息
        List<TbSysPermissionDTO> userPermissions = new ArrayList<>();
        List<TbSysViewDTO> userViews = new ArrayList<>();
        
        ResultDomain<PermissionVO> permissionsResult = modulePermissionService.getUserPermissions(guest.getUserId());
        if (permissionsResult.getSuccess() && permissionsResult.getDataList() != null) {
            for (PermissionVO permission : permissionsResult.getDataList()) {
                if (permission.getPermissionId() != null) {
                    TbSysPermissionDTO permissionDTO = PermissionVO.toPermissionDTO(permission);
                    if (permissionDTO != null) {
                        userPermissions.add(permissionDTO);
                    }
                }
                if (permission.getViewId() != null) {
                    TbSysViewDTO viewDTO = PermissionVO.toViewDTO(permission);
                    if (viewDTO != null) {
                        userViews.add(viewDTO);
                    }
                }
            }
        }
        loginDomain.setUserPermissions(userPermissions);
        loginDomain.setUserViews(userViews);

        loginDomain.setLoginType("wechat_miniprogram");

        // 生成 JWT Token
        String token = jwtTokenUtil.generateToken(loginDomain);
        loginDomain.setToken(token);

        // 将登录信息存储到 Redis（24小时有效期）
        String loginKey = "login:token:" + token;
        redisService.set(loginKey, JSON.toJSONString(loginDomain), 24, TimeUnit.HOURS);

        // 存储用户登录状态
        String userLoginKey = "login:user:" + guest.getUserId();
        redisService.set(userLoginKey, token, 24, TimeUnit.HOURS);

        return loginDomain;
    }

    /**
     * 获取客户端IP地址
     */
    private String getClientIP(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }
        return ip;
    }
}
