package com.caliverse.admin.scheduler.polling.service;

import com.caliverse.admin.domain.entity.log.LogAction;
import com.caliverse.admin.domain.entity.log.LogStatus;
import com.caliverse.admin.domain.service.UserGameSessionService;
import com.caliverse.admin.dynamodb.service.DynamodbMailService;
import com.caliverse.admin.dynamodb.service.DynamodbService;
import com.caliverse.admin.global.common.annotation.BusinessProcess;
import com.caliverse.admin.global.component.manager.BusinessProcessIdManager;
import com.caliverse.admin.mongodb.service.BusinessLogService;
import com.caliverse.admin.scheduler.CommonScheduler;
import com.caliverse.admin.scheduler.entity.SchedulerType;
import com.caliverse.admin.domain.entity.LandOwnerChange;
import com.caliverse.admin.domain.request.LandRequest;
import com.caliverse.admin.domain.service.LandService;
import com.caliverse.admin.dynamodb.service.DynamodbLandService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class LandOwnerChangesScheduler extends CommonScheduler {

    private final LandService landService;
    private final DynamodbLandService dynamodbLandService;
    private final DynamodbMailService dynamodbMailService;
    private final UserGameSessionService userGameSessionService;

    public LandOwnerChangesScheduler(LandService landService,
                                     DynamodbLandService dynamodbLandService,
                                     DynamodbMailService dynamodbMailService,
                                     UserGameSessionService userGameSessionService,
                                     BusinessLogService businessLogService,
                                     BusinessProcessIdManager processIdManager) {
        super(businessLogService, processIdManager);
        this.landService = landService;
        this.dynamodbLandService = dynamodbLandService;
        this.dynamodbMailService = dynamodbMailService;
        this.userGameSessionService = userGameSessionService;
    }

    @Override
    protected void executeInternal() {
        executeWithProcessId(LogAction.SCHEDULE_LAND_OWNER_CHANGE, this::executeLogic);

    }

    private void executeLogic() {
        List<LandOwnerChange> scheduleList = landService.getScheduleLandOwnerChangesList();

        LocalDateTime startTime = LocalDateTime.now();
        List<Long> processedIds = new ArrayList<>();
        List<Integer> processedLandIds = new ArrayList<>();

        try {
            scheduleList.forEach(landOwnerChange -> {
                LandOwnerChange.CHANGE_STATUS status = landOwnerChange.getStatus();
                LocalDateTime reserve_dt = landOwnerChange.getReservationDt();
                int landId = landOwnerChange.getLandId();
                String guid = landOwnerChange.getUserGuid();

                LocalDateTime now = LocalDateTime.now();

                if (status.equals(LandOwnerChange.CHANGE_STATUS.WAIT) && reserve_dt.isBefore(now)) {
                    LandRequest landRequest = LandRequest.builder()
                            .landId(landId)
                            .landName(landOwnerChange.getLandName())
                            .buildingId(landOwnerChange.getBuildingId())
                            .buildingName(landOwnerChange.getBuildingName())
                            .userGuid(guid)
                            .userName(landOwnerChange.getUserName())
                            .build();

                    //유저킥
                    userGameSessionService.kickUserSession(guid, "land owner changes");

                    //랜드정보 처리
                    dynamodbLandService.ChangesLandOwner(landRequest);

                    Map map = new HashMap<>();
                    map.put("id", landOwnerChange.getId());
                    map.put("status", LandOwnerChange.CHANGE_STATUS.FINISH);
                    landService.updateLandOwnedChangeStatus(map);

                    //우편
                    dynamodbMailService.insertLandChangesMail(landRequest);

                    processedIds.add(landOwnerChange.getId());
                    processedLandIds.add(landId);

                    log.info("Land owner change processed successfully: id={}, landId={}, userGuid={}",
                            landOwnerChange.getId(), landId, guid);
                }
            });

            if (!processedIds.isEmpty()) {
                businessLogService.logScheduler(
                        LogStatus.SUCCESS,
                        String.format("토지 소유자 변경 스케줄 처리 완료: %d건 처리", processedIds.size()),
                        "LAND_OWNER_CHANGES_SCHEDULER",
                        startTime,
                        LocalDateTime.now(),
                        Map.of(
                                "totalScheduleCount", scheduleList.size(),
                                "processedCount", processedIds.size(),
                                "processedIds", processedIds,
                                "processedLandIds", processedLandIds
                        )
                );

                log.info("Land owner changes scheduler completed: {} items processed out of {} total",
                        processedIds.size(), scheduleList.size());
            }
        }catch(Exception e){
            log.error("Land owner changes scheduler failed", e);
            throw e;
        }
    }

    @Override
    public SchedulerType getSchedulerType() {
        return SchedulerType.LAND_OWNER_CHANGES;
    }
}
