package com.zioinfo.kintex.auction;

import com.zioinfo.kintex.auction.dto.AuctionDtos.BoqLine;

import java.util.ArrayList;
import java.util.List;

/**
 * F035 물량서(BOQ) 자동산출 — 부스 설계 데이터(면적·둘레·부스수·유틸리티 주문)에서
 * 공사 물량 라인을 <b>규칙 기반</b>으로 집계하는 순수 함수(단위 테스트 대상, DB·스프링 미의존).
 *
 * <p><b>산식은 단순 명료(면적·주문 합산 기반)</b> — 각 라인은 산출 근거({@code basis})를 함께 표기한다.
 * 금액(단가)은 산출하지 않는다 — BOQ 는 <b>물량(수량)</b> 산출서이며, 단가·금액은 응찰 업체가 견적서로 채운다.
 *
 * <ul>
 *   <li>구조: 시스템 골조 = 바닥면적(1:1) · 벽체 파티션 = 둘레 × 높이</li>
 *   <li>바닥: 바닥 마감재 = 바닥면적(1:1)</li>
 *   <li>조명: LED 조명기구 = ⌈면적 / 9㎡⌉ (9㎡당 1등)</li>
 *   <li>전기: 분전반·전기 인입 = 부스 수(1실당 1)</li>
 *   <li>설비: 급배수·네트워크 인입 = 유틸리티 신청 건수(있을 때만)</li>
 * </ul>
 */
public final class BoqCalc {

    /** 기본 부스 높이(㎡ 데이터에 높이 미지정 시). */
    static final double DEFAULT_HEIGHT_M = 3.5;
    /** 조명 밀도 — 9㎡당 1등. */
    static final double LIGHT_AREA_PER_FIXTURE = 9.0;

    private BoqCalc() {
    }

    /**
     * 물량 라인 산출. area/perimeter/height 는 M2 부스 폴리곤(㎡·m) 집계값, utilityOrderCount 는 M4 유틸리티 주문 수.
     * boothCount==0 또는 area<=0 이면 빈 리스트(설계 미확정) — 서비스가 안내 note 를 붙인다.
     */
    public static List<BoqLine> compute(double areaM2, double perimeterM, int boothCount,
                                        double heightM, int utilityOrderCount) {
        List<BoqLine> lines = new ArrayList<>();
        long area = Math.round(areaM2);
        if (boothCount <= 0 || area <= 0) {
            return lines;
        }
        // 둘레 미확보 시 정사각형 근사(4√면적)로 폴백 — 벽체 물량 근거를 명시.
        boolean perimeterEstimated = perimeterM <= 0;
        double perimeter = perimeterEstimated ? 4.0 * Math.sqrt(areaM2) : perimeterM;
        double height = heightM > 0 ? heightM : DEFAULT_HEIGHT_M;
        long wall = Math.round(perimeter * height);
        long lights = (long) Math.ceil(areaM2 / LIGHT_AREA_PER_FIXTURE);
        String pBasis = perimeterEstimated
                ? "둘레(근사 " + Math.round(perimeter) + "m) × 높이 " + trimNum(height) + "m"
                : "둘레 " + Math.round(perimeter) + "m × 높이 " + trimNum(height) + "m";

        int seq = 0;
        lines.add(new BoqLine(++seq, "구조", "시스템 부스 골조(알루미늄 프로파일)", "㎡", area,
                "바닥면적 " + area + "㎡ 기준(1:1)"));
        lines.add(new BoqLine(++seq, "구조", "벽체·파티션", "㎡", wall, pBasis));
        lines.add(new BoqLine(++seq, "바닥", "바닥 마감재(데코타일/카펫)", "㎡", area,
                "바닥면적 " + area + "㎡ 기준(1:1)"));
        lines.add(new BoqLine(++seq, "조명", "LED 조명기구", "EA", lights,
                "9㎡당 1등 기준(면적 " + area + "㎡)"));
        lines.add(new BoqLine(++seq, "전기", "분전반·전기 인입", "식", boothCount,
                "부스 " + boothCount + "실 × 1분전반"));
        if (utilityOrderCount > 0) {
            lines.add(new BoqLine(++seq, "설비", "급배수·네트워크 인입", "식", utilityOrderCount,
                    "유틸리티 신청 " + utilityOrderCount + "건 기준"));
        }
        return lines;
    }

    /** 소수 0이면 정수로 표기(3.5 → "3.5", 4.0 → "4"). */
    private static String trimNum(double v) {
        if (v == Math.floor(v)) {
            return String.valueOf((long) v);
        }
        return String.valueOf(Math.round(v * 10.0) / 10.0);
    }
}
