package com.zioinfo.mall.schedule;

import com.zioinfo.mall.schedule.mapper.ScheduleMapper;
import com.zioinfo.mall.store.MallStore;
import com.zioinfo.mall.store.mapper.StoreMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 스케줄 서비스 — 가용 슬롯·당일배송 마감 판정·서지프라이싱 계산.
 *
 * <p>당일배송 가능 여부는 매장 로컬타임 기준 same_day_cutoff와 비교한다.
 */
@Service
@RequiredArgsConstructor
public class ScheduleService {

    private final ScheduleMapper mapper;
    private final StoreMapper storeMapper;

    /**
     * 매장/날짜 가용 슬롯 조회. 응답에 당일배송 가능 여부와 서지 배수 포함.
     */
    public Map<String, Object> availability(Long storeId, LocalDate date) {
        MallStore store = storeMapper.findById(storeId);
        if (store == null) {
            throw new RuntimeException("ERR-SCH-404: 매장을 찾을 수 없습니다");
        }
        List<MallScheduleSlot> slots = mapper.findSlots(storeId, date);
        boolean blocked = false;
        BigDecimal surge = BigDecimal.ONE;
        MallHoliday holiday = mapper.findHoliday(date, storeId);
        if (holiday != null) {
            blocked = Boolean.TRUE.equals(holiday.getBlocked());
            if (holiday.getSurgeMultiplier() != null) surge = holiday.getSurgeMultiplier();
        }
        Map<String, Object> out = new LinkedHashMap<>();
        out.put("storeId", storeId);
        out.put("date", date);
        out.put("blocked", blocked);
        out.put("surgeMultiplier", surge);
        out.put("sameDayAvailable", isSameDayAvailable(store, date));
        out.put("sameDayCutoff", store.getSameDayCutoff());
        out.put("slots", slots);
        return out;
    }

    /** 당일배송 마감 판정 — 매장 로컬타임 < cutoff 이면 당일 가능. */
    public boolean isSameDayAvailable(MallStore store, LocalDate date) {
        try {
            ZoneId zone = ZoneId.of(store.getTimezone() == null ? "America/New_York" : store.getTimezone());
            ZonedDateTime now = ZonedDateTime.now(zone);
            if (!date.equals(now.toLocalDate())) {
                return date.isAfter(now.toLocalDate());  // 미래 날짜는 항상 가능
            }
            String cutoff = store.getSameDayCutoff() == null ? "12:00" : store.getSameDayCutoff();
            LocalTime cut = LocalTime.parse(cutoff.length() == 5 ? cutoff : "12:00");
            return now.toLocalTime().isBefore(cut);
        } catch (Exception e) {
            return false;
        }
    }

    /** 서지 배수 조회(주문 가격 계산용). */
    public BigDecimal surgeMultiplier(Long storeId, LocalDate date) {
        MallHoliday h = mapper.findHoliday(date, storeId);
        if (h != null && h.getSurgeMultiplier() != null) return h.getSurgeMultiplier();
        return BigDecimal.ONE;
    }

    public MallScheduleSlot createSlot(MallScheduleSlot s) {
        mapper.insertSlot(s);
        return mapper.findSlot(s.getId());
    }

    public List<MallHoliday> holidays() {
        return mapper.findHolidays();
    }

    public MallHoliday upsertHoliday(MallHoliday h) {
        mapper.upsertHoliday(h);
        return mapper.findHoliday(h.getHolidayDate(), h.getStoreId());
    }
}
