package com.moka.gdtauto.controller;

import com.moka.gdtauto.annotation.AuthUser;
import com.moka.gdtauto.common.Result;
import com.moka.gdtauto.entity.SysUser;
import com.moka.gdtauto.entity.TencentAdsAuth;
import com.moka.gdtauto.service.TencentAdsAuthService;
import com.moka.gdtauto.service.SysUserService;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.List;


/**
 * 腾讯广告OAuth授权控制器
 * 使用Marketing API SDK进行OAuth授权
 * 
 * @author moka
 * @since 2026-02-03
 */
@Tag(name = "OAuth授权管理", description = "腾讯广告账户OAuth2.0授权与Token管理")
@Slf4j
@RestController
@RequestMapping("/api/gdt/auth")
@RequiredArgsConstructor
public class TencentAdsAuthController {

    private final TencentAdsAuthService authService;
    private final SysUserService sysUserService;

    /**
     * 获取授权URL
     * 第一步：调用此接口获取授权链接，然后引导用户到该链接进行授权
     * 
     * @param redirectUri 回调地址（授权成功后腾讯会回调这个地址）
     * @param state 状态参数（用于防止CSRF攻击，可选）
     * @return 授权URL
     * 
     * 使用示例：
     * GET /api/auth/authorize-url?redirectUri=http://your-domain.com/callback&state=random_state
     */
    @Operation(
        summary = "获取OAuth授权URL",
        description = "OAuth2.0授权流程第一步：生成腾讯广告平台的授权链接，引导用户到该链接完成授权"
    )
    @GetMapping("/authorize-url")
    public Result<String> getAuthorizationUrl(
        @AuthUser SysUser sysUser
    ) {
        try {
            String authUrl = authService.getAuthorizationUrl(sysUser.getJobNumber());
            return Result.success(authUrl, "获取授权URL成功")
                    .withUsage("请将用户引导到此URL进行授权");
        } catch (Exception e) {
            log.error("获取授权URL失败", e);
            return Result.fail("获取授权URL失败：" + e.getMessage());
        }
    }

    /**
     * 授权回调处理
     * 第二步：用户在腾讯广告平台授权后，会回调到这个接口
     * 这个接口使用SDK获取access_token和refresh_token
     * 
     * @param authorizationCode 授权码（腾讯回调时携带）
     * @param state 状态参数
     * @param redirectUri 回调地址（必须与第一步的redirectUri一致）
     * @return 授权结果
     * 
     * 使用示例：
     * GET /api/auth/callback?authorization_code=xxx&redirect_uri=http://your-domain.com/callback&state=random_state
     */
    @Operation(
        summary = "OAuth授权回调处理",
        description = "OAuth2.0授权流程第二步：接收腾讯广告平台的授权回调，使用authorization_code换取access_token和refresh_token，并保存到数据库"
    )
    @GetMapping("/callback")
    public Result<TencentAdsAuth> callback(
            @Parameter(description = "授权码，由腾讯广告平台回调时携带", required = true, example = "auth_code_example_123456")
            @RequestParam("authorization_code") String authorizationCode,
            @Parameter(description = "状态参数，用于校验请求合法性", example = "工号")
            @RequestParam(required = false) String state) {
        try {
            String jobNumber = state;
            SysUser user = sysUserService.getByJobNumber(jobNumber);
            if (user == null) {
                return Result.fail("用户不存在");
            }
            TencentAdsAuth auth = authService.getAccessToken(authorizationCode, state);
            return Result.success(auth, "授权成功,已保存token信息")
                    .withNote("token会自动维护，无需手动刷新");
        } catch (Exception e) {
            log.error("授权失败", e);
            return Result.fail("授权失败：" + e.getMessage());
        }
    }

    @GetMapping("ok")
    public String oAuthOK() {
        return "OK";
    }
    

    /**
     * 手动刷新访问令牌
     * 使用SDK的OAuth API刷新token
     * 注意：正常情况下，定时任务会自动刷新，不需要手动调用
     * 
     * @param id 
     * @return 刷新结果
     * 
     * 使用示例：
     * POST /api/auth/refresh?id=123456
     */
    @Operation(
        summary = "手动刷新Access Token",
        description = "使用refresh_token刷新access_token。正常情况下，系统会通过定时任务自动刷新，此接口仅用于手动触发或紧急处理"
    )
    @PostMapping("/refresh")
    public Result<TencentAdsAuth> refreshToken(
            @Parameter(description = "ID", required = true, example = "1234567890")
            @RequestParam Long id) {
        try {
            TencentAdsAuth auth = authService.refreshAccessToken(id);
            return Result.success(auth, "刷新令牌成功");
        } catch (Exception e) {
            log.error("刷新令牌失败", e);
            return Result.<TencentAdsAuth>fail("刷新令牌失败：" + e.getMessage())
                    .withNote("如果refresh_token也过期，需要重新授权");
        }
    }

    /**
     * 查询账户授权信息
     * 
     * @param id 账户ID
     * @return 授权信息
     * 
     * 使用示例：
     * GET /api/auth/info?id=123456
     */
    @Operation(
        summary = "查询账户授权信息",
        description = "根据账户ID查询该账户的OAuth授权信息，包括access_token、refresh_token、过期时间等"
    )
    @GetMapping("/info")
    public Result<TencentAdsAuth> getAuthInfo(
            @Parameter(description = "ID", required = true, example = "1234567890")
            @RequestParam Long id) {
        try {
            TencentAdsAuth auth = authService.getById(id);
            if (auth != null) {
                return Result.success(auth, "查询成功");
            } else {
                return Result.<TencentAdsAuth>fail("未找到授权信息")
                        .withNote("请先进行授权");
            }
        } catch (Exception e) {
            log.error("查询授权信息失败", e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 获取所有有效的授权信息
     * 
     * @return 授权信息列表
     * 
     * 使用示例：
     * GET /api/auth/list
     */
    @Operation(
        summary = "查询所有有效授权",
        description = "获取所有已授权且处于有效状态的账户列表，用于管理和监控已授权账户"
    )
    @GetMapping("/list")
    public Result<List<TencentAdsAuth>> listAuths(@AuthUser SysUser sysUser) {
        try {
            List<TencentAdsAuth> auths = authService.listValidAuths(sysUser.getJobNumber());
            return Result.success(auths, "查询成功")
                    .withCount(auths.size());
        } catch (Exception e) {
            log.error("查询授权列表失败", e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    
    
    /**
     * 查询即将过期token（用于监控）
     * 
     * @return 即将过期的授权信息列表
     * 
     * 使用示例：
     * GET /api/auth/expiring
     */
    @Operation(
        summary = "查询即将过期Token",
        description = "查询即将过期（30分钟内）的access_token列表，用于监控和预警。系统定时任务会自动刷新这些token"
    )
    @GetMapping("/expiring")
    public Result<List<TencentAdsAuth>> listExpiringAuths() {
        try {
            List<TencentAdsAuth> auths = authService.listExpiringAuths();
            return Result.success(auths, "查询成功")
                    .withCount(auths.size())
                    .withNote("定时任务会自动刷新这些token");
        } catch (Exception e) {
            log.error("查询即将过期token失败", e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }
}
