package com.lesingle.modules.biz.contest.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lesingle.common.enums.ErrorCode;
import com.lesingle.common.enums.PublishStatus;
import com.lesingle.common.exception.BusinessException;
import com.lesingle.common.result.PageResult;
import com.lesingle.common.result.Result;
import com.lesingle.common.util.SecurityUtil;
import com.lesingle.modules.biz.contest.dto.CreateNoticeDto;
import com.lesingle.modules.biz.contest.entity.BizContestNotice;
import com.lesingle.modules.biz.contest.service.IContestNoticeService;
import com.lesingle.security.annotation.RequirePermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.List;
import java.util.Map;

@Tag(name = "活动公告")
@RestController
@RequestMapping("/contests/notices")
@RequiredArgsConstructor
public class ContestNoticeController {

    private final IContestNoticeService noticeService;

    /**
     * 解析日期时间字符串，兼容 ISO 格式（带毫秒和 Z 时区标记）
     */
    private LocalDateTime parseDateTime(String dateTime) {
        if (!StringUtils.hasText(dateTime)) {
            return null;
        }
        // 尝试 ISO 格式（yyyy-MM-dd'T'HH:mm:ss.SSSZ 或 yyyy-MM-dd'T'HH:mm:ss'Z'）
        try {
            // 处理带 Z 的 ISO 格式
            if (dateTime.endsWith("Z")) {
                return LocalDateTime.parse(dateTime.substring(0, dateTime.length() - 1));
            }
            // 处理带毫秒的格式
            if (dateTime.contains(".") && dateTime.indexOf(".") + 4 == dateTime.length()) {
                return LocalDateTime.parse(dateTime.substring(0, dateTime.indexOf(".")));
            }
            return LocalDateTime.parse(dateTime);
        } catch (Exception e) {
            // 尝试空格分隔格式
            try {
                return LocalDateTime.parse(dateTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            } catch (Exception ex) {
                return null;
            }
        }
    }

    @PostMapping
    @RequirePermission("notice:create")
    @Operation(summary = "创建公告")
    public Result<BizContestNotice> create(@Valid @RequestBody CreateNoticeDto dto) {
        BizContestNotice notice = new BizContestNotice();
        notice.setContestId(dto.getContestId());
        notice.setTitle(dto.getTitle());
        notice.setContent(dto.getContent());
        notice.setNoticeType(dto.getNoticeType());
        notice.setPriority(dto.getPriority());
        if (StringUtils.hasText(dto.getPublishTime())) {
            notice.setPublishTime(parseDateTime(dto.getPublishTime()));
        }
        // 设置当前租户 ID（租户隔离）
        notice.setTenantId(SecurityUtil.getCurrentTenantId());
        noticeService.save(notice);
        return Result.success(notice);
    }

    @GetMapping("/contest/{contestId}")
    @RequirePermission("notice:read")
    @Operation(summary = "查询活动下的公告列表")
    public Result<List<BizContestNotice>> findByContest(@PathVariable Long contestId) {
        Long tenantId = SecurityUtil.getCurrentTenantId();
        List<BizContestNotice> list = noticeService.list(
                new LambdaQueryWrapper<BizContestNotice>()
                        .eq(BizContestNotice::getContestId, contestId)
                        .eq(BizContestNotice::getTenantId, tenantId)
                        .orderByDesc(BizContestNotice::getCreateTime));
        noticeService.fillContestInfo(list);
        return Result.success(list);
    }

    @GetMapping
    @RequirePermission("notice:read")
    @Operation(summary = "分页查询公告列表")
    public Result<PageResult<BizContestNotice>> findAll(
            @RequestParam(defaultValue = "1") Long page,
            @RequestParam(defaultValue = "10") Long pageSize,
            @RequestParam(required = false) String title,
            @RequestParam(required = false) String status) {
        Long tenantId = SecurityUtil.getCurrentTenantId();
        LambdaQueryWrapper<BizContestNotice> wrapper = new LambdaQueryWrapper<BizContestNotice>()
                .eq(BizContestNotice::getTenantId, tenantId)  // 租户隔离
                .like(StringUtils.hasText(title), BizContestNotice::getTitle, title);

        // 发布状态过滤
        if (PublishStatus.PUBLISHED.getValue().equals(status)) {
            wrapper.isNotNull(BizContestNotice::getPublishTime);
        } else if (PublishStatus.UNPUBLISHED.getValue().equals(status)) {
            wrapper.isNull(BizContestNotice::getPublishTime);
        }

        wrapper.orderByDesc(BizContestNotice::getCreateTime);
        Page<BizContestNotice> result = noticeService.page(new Page<>(page, pageSize), wrapper);
        noticeService.fillContestInfo(result.getRecords());
        return Result.success(PageResult.from(result));
    }

    @GetMapping("/{id}")
    @RequirePermission("notice:read")
    @Operation(summary = "查询公告详情")
    public Result<BizContestNotice> findDetail(@PathVariable Long id) {
        BizContestNotice notice = noticeService.getById(id);
        if (notice != null) {
            noticeService.fillContestInfo(Collections.singletonList(notice));
        }
        return Result.success(notice);
    }

    @PatchMapping("/{id}")
    @RequirePermission("notice:update")
    @Operation(summary = "更新公告（部分字段；publishTime 为 null 或空串表示取消发布并写入数据库 NULL）")
    public Result<Void> update(@PathVariable Long id, @RequestBody Map<String, Object> body) {
        Long tenantId = SecurityUtil.getCurrentTenantId();
        BizContestNotice existing = noticeService.getOne(
                new LambdaQueryWrapper<BizContestNotice>()
                        .eq(BizContestNotice::getId, id)
                        .eq(BizContestNotice::getTenantId, tenantId));
        if (existing == null) {
            throw BusinessException.of(ErrorCode.NOT_FOUND, "公告不存在");
        }

        LambdaUpdateWrapper<BizContestNotice> uw = new LambdaUpdateWrapper<>();
        uw.eq(BizContestNotice::getId, id);
        uw.eq(BizContestNotice::getTenantId, tenantId);

        boolean hasUpdate = false;
        if (body.containsKey("title")) {
            Object v = body.get("title");
            if (v != null) {
                uw.set(BizContestNotice::getTitle, String.valueOf(v));
                hasUpdate = true;
            }
        }
        if (body.containsKey("content")) {
            Object v = body.get("content");
            if (v != null) {
                uw.set(BizContestNotice::getContent, String.valueOf(v));
                hasUpdate = true;
            }
        }
        if (body.containsKey("noticeType")) {
            Object v = body.get("noticeType");
            if (v != null) {
                uw.set(BizContestNotice::getNoticeType, String.valueOf(v));
                hasUpdate = true;
            }
        }
        if (body.containsKey("priority")) {
            Object v = body.get("priority");
            if (v instanceof Number) {
                uw.set(BizContestNotice::getPriority, ((Number) v).intValue());
                hasUpdate = true;
            }
        }
        if (body.containsKey("contestId")) {
            Object v = body.get("contestId");
            if (v instanceof Number) {
                uw.set(BizContestNotice::getContestId, ((Number) v).longValue());
                hasUpdate = true;
            }
        }
        // 仅当请求体包含 publishTime 键时才改发布时间：null / 空串 = 取消发布（必须写入 SQL NULL）
        if (body.containsKey("publishTime")) {
            Object v = body.get("publishTime");
            if (v == null || (v instanceof String && !StringUtils.hasText((String) v))) {
                uw.set(BizContestNotice::getPublishTime, null);
                hasUpdate = true;
            } else if (v instanceof String && StringUtils.hasText((String) v)) {
                LocalDateTime pt = parseDateTime((String) v);
                if (pt != null) {
                    uw.set(BizContestNotice::getPublishTime, pt);
                    hasUpdate = true;
                }
            }
        }

        if (!hasUpdate) {
            return Result.success();
        }
        noticeService.getBaseMapper().update(null, uw);
        return Result.success();
    }

    @DeleteMapping("/{id}")
    @RequirePermission("notice:delete")
    @Operation(summary = "删除公告")
    public Result<Void> remove(@PathVariable Long id) {
        noticeService.removeById(id);
        return Result.success();
    }
}
