package com.liquidnet.service.platform.controller.A_fskfsfs.diagnostic;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.dto.param.PerformancePartnerVo;
import com.liquidnet.service.kylin.dto.vo.partner.KylinTicketPartnerVo;
import com.liquidnet.service.kylin.dto.vo.partner.KylinTicketTimesPartnerVo;
import com.liquidnet.service.kylin.entity.KylinPerformanceStatus;
import com.liquidnet.service.kylin.entity.KylinTicketRelations;
import com.liquidnet.service.kylin.entity.KylinTicketStatus;
import com.liquidnet.service.kylin.entity.KylinTicketTimeRelation;
import com.liquidnet.service.kylin.mapper.KylinPerformanceStatusMapper;
import com.liquidnet.service.kylin.mapper.KylinTicketRelationsMapper;
import com.liquidnet.service.kylin.mapper.KylinTicketStatusMapper;
import com.liquidnet.service.kylin.mapper.KylinTicketTimeRelationMapper;
import com.liquidnet.service.platform.controller.A_fskfsfs.diagnostic.vo.PerformanceDiagnosticVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

@Api(tags = "平台-演出诊断")
@RestController
@RequestMapping("platform/diagnostic")
public class PerformanceDiagnosticController {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private KylinPerformanceStatusMapper performanceStatusMapper;

    @Autowired
    private KylinTicketTimeRelationMapper ticketTimeRelationMapper;

    @Autowired
    private KylinTicketStatusMapper ticketStatusMapper;

    @Autowired
    private KylinTicketRelationsMapper ticketRelationsMapper;

    @GetMapping("/performance")
    @ApiOperation("查询演出所有场次、票种状态及诊断信息")
    public ResponseDto<PerformanceDiagnosticVo> analyzePerformance(@RequestParam String performanceId) {
        PerformanceDiagnosticVo result = new PerformanceDiagnosticVo();
        result.setPerformanceId(performanceId);

        // 1. Fetch Performance Mongo Data
        PerformancePartnerVo performanceVo = mongoTemplate.findOne(
                Query.query(Criteria.where("performancesId").is(performanceId)),
                PerformancePartnerVo.class,
                PerformancePartnerVo.class.getSimpleName());

        if (performanceVo != null) {
            result.setTitle(performanceVo.getTitle());
            result.setAuditStatus(performanceVo.getAuditStatus());
            result.setMongoStatus(performanceVo.getStatus());
            result.setMerchantId(performanceVo.getMerchantId());
        }

        // 2. Fetch Performance MySQL Status
        KylinPerformanceStatus perfStatus = performanceStatusMapper.selectOne(
                Wrappers.lambdaQuery(KylinPerformanceStatus.class).eq(KylinPerformanceStatus::getPerformanceId,
                        performanceId));
        if (perfStatus != null) {
            result.setMysqlStatus(perfStatus.getStatus());
            result.setPerformanceOnline(perfStatus.getStatus() == 9);
        }

        // 3. Find Sessions (Ticket Times) via MySQL Relation
        List<KylinTicketTimeRelation> timeRelations = ticketTimeRelationMapper.selectList(
                Wrappers.lambdaQuery(KylinTicketTimeRelation.class).eq(KylinTicketTimeRelation::getPerformanceId,
                        performanceId));

        List<PerformanceDiagnosticVo.SessionDiagnosticVo> sessionList = new ArrayList<>();

        for (KylinTicketTimeRelation timeRel : timeRelations) {
            PerformanceDiagnosticVo.SessionDiagnosticVo sessionVo = new PerformanceDiagnosticVo.SessionDiagnosticVo();
            sessionVo.setTimesId(timeRel.getTimesId());
            sessionVo.setPerformanceId(performanceId);

            // Fetch Session Mongo Data
            KylinTicketTimesPartnerVo timeVo = mongoTemplate.findOne(
                    Query.query(Criteria.where("ticketTimesId").is(timeRel.getTimesId())),
                    KylinTicketTimesPartnerVo.class,
                    KylinTicketTimesPartnerVo.class.getSimpleName());

            if (timeVo != null) {
                sessionVo.setTitle(timeVo.getTitle());
                sessionVo.setUseStart(timeVo.getUseStart());
                sessionVo.setUseEnd(timeVo.getUseEnd());
                sessionVo.setStatus(timeVo.getStatus());
            }

            // 4. Find Tickets for Session via MySQL Relation
            List<KylinTicketRelations> ticketRelations = ticketRelationsMapper.selectList(
                    Wrappers.lambdaQuery(KylinTicketRelations.class).eq(KylinTicketRelations::getTimesId,
                            timeRel.getTimesId()));

            List<PerformanceDiagnosticVo.TicketDiagnosticVo> ticketList = new ArrayList<>();
            for (KylinTicketRelations ticketRel : ticketRelations) {
                PerformanceDiagnosticVo.TicketDiagnosticVo ticketVo = new PerformanceDiagnosticVo.TicketDiagnosticVo();
                String ticketId = ticketRel.getTicketId();
                ticketVo.setTicketsId(ticketId);

                // Fetch Ticket Mongo Data
                KylinTicketPartnerVo ticketDoc = mongoTemplate.findOne(
                        Query.query(Criteria.where("ticketsId").is(ticketId)),
                        KylinTicketPartnerVo.class,
                        KylinTicketPartnerVo.class.getSimpleName());

                if (ticketDoc != null) {
                    ticketVo.setTitle(ticketDoc.getTitle());
                    ticketVo.setPrice(ticketDoc.getPrice());
                    ticketVo.setMongoStatus(ticketDoc.getStatus());
                    ticketVo.setSaleTimeStart(ticketDoc.getTimeStart());
                    ticketVo.setSaleTimeEnd(ticketDoc.getTimeEnd());
                    ticketVo.setCreatedAt(ticketDoc.getCreatedAt());
                    ticketVo.setViewersNumber(ticketDoc.getViewersNumber());
                }

                // Fetch Ticket MySQL Data
                KylinTicketStatus tickStatus = ticketStatusMapper.selectOne(
                        Wrappers.lambdaQuery(KylinTicketStatus.class).eq(KylinTicketStatus::getTicketId, ticketId));

                if (tickStatus != null) {
                    ticketVo.setMysqlStatus(tickStatus.getStatus());
                    ticketVo.setOnline(tickStatus.getStatus() == 9);
                    ticketVo.setDeleted(tickStatus.getStatus() == -1);
                }

                // --- Diagnostic Logic ---

                // 1. Can Delete?
                // Logic per KylinTicketsPartnerServiceImpl: Performance Status must be 0
                // (Unsubmitted) OR 4 (Rejected).
                boolean canDelete = false;
                StringBuilder cannotDeleteReason = new StringBuilder();
                if (perfStatus == null) {
                    cannotDeleteReason.append("演出MySQL状态不存在; ");
                } else {
                    if (perfStatus.getStatus() == 0 || perfStatus.getStatus() == 4) {
                        canDelete = true;
                    } else {
                        cannotDeleteReason.append("演出状态非[未提交/被拒绝] (当前状态: ").append(perfStatus.getStatus())
                                .append("); ");
                    }
                }
                // Check if ticket is already online? (Usually strict on performance status
                // determines it)
                ticketVo.setCanDelete(canDelete);
                ticketVo.setCannotDeleteReason(canDelete ? "" : cannotDeleteReason.toString());

                // 2. Can Edit?
                // Logic per updateTicket: Performance auditStats must NOT be 0.
                boolean canEdit = true;
                StringBuilder cannotEditReason = new StringBuilder();
                if (performanceVo == null || performanceVo.getAuditStatus() == null
                        || performanceVo.getAuditStatus() == 0) {
                    canEdit = false;
                    cannotEditReason.append("演出Mongo状态(AuditStatus)为0或空; ");
                }
                ticketVo.setCanEdit(canEdit);
                ticketVo.setCannotEditReason(canEdit ? "" : cannotEditReason.toString());

                // 3. Is Visible To User? (Front-end)
                // Requires Performance Online (9) AND Ticket Online (9).
                boolean isVisible = false;
                StringBuilder notVisibleReason = new StringBuilder();
                if (perfStatus != null && perfStatus.getStatus() != 9) {
                    notVisibleReason.append("演出未上线 (MySQL状态: ").append(perfStatus.getStatus()).append("); ");
                }
                if (tickStatus != null && tickStatus.getStatus() != 9) {
                    notVisibleReason.append("票种未上线 (MySQL状态: ").append(tickStatus.getStatus()).append("); ");
                }
                if (notVisibleReason.length() == 0) {
                    isVisible = true;
                }
                ticketVo.setVisibleToUser(isVisible);
                ticketVo.setNotVisibleReason(notVisibleReason.toString());

                // 4. Is Saleable?
                // Visible + Time Range.
                boolean isSaleable = isVisible;
                StringBuilder notSaleableReason = new StringBuilder();
                if (!isVisible) {
                    isSaleable = false;
                    notSaleableReason.append("票种前台不可见; ");
                } else if (ticketDoc != null) {
                    LocalDateTime now = LocalDateTime.now();
                    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    try {
                        LocalDateTime start = LocalDateTime.parse(ticketDoc.getTimeStart(), dtf);
                        LocalDateTime end = LocalDateTime.parse(ticketDoc.getTimeEnd(), dtf);
                        if (now.isBefore(start)) {
                            isSaleable = false;
                            notSaleableReason.append("未到开售时间 (Start: ").append(ticketDoc.getTimeStart()).append("); ");
                        } else if (now.isAfter(end)) {
                            isSaleable = false;
                            notSaleableReason.append("已过售卖时间 (End: ").append(ticketDoc.getTimeEnd()).append("); ");
                        }
                    } catch (Exception e) {
                        isSaleable = false;
                        notSaleableReason.append("时间格式解析错误; ");
                    }
                }
                // Stock check excluded as no DAO available yet. user can infer from "Visible"
                // and "Online".

                ticketVo.setSaleable(isSaleable);
                ticketVo.setNotSaleableReason(isSaleable ? "" : notSaleableReason.toString());

                ticketList.add(ticketVo);
            }
            sessionVo.setTickets(ticketList);
            sessionList.add(sessionVo);
        }

        result.setSessions(sessionList);
        return ResponseDto.success(result);
    }
}
