package com.erp.service;

import com.erp.common.BaseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@Slf4j
public class PopProductionService extends BaseService {

    @Autowired private JdbcTemplate jdbcTemplate;

    /**
     * D-BE1: 작업지시 공정 일괄 생성
     * work_order_process + process_work_result 일괄 생성 (1 트랜잭션)
     */
    @Transactional
    public Map<String, Object> createWorkProcesses(Map<String, Object> params) {
        String companyCode = (String) params.get("company_code");
        String userId = (String) params.get("user_id");
        Object workInstructionId = params.get("work_instruction_id");
        Object routingVersionId = params.get("routing_version_id");
        Object planQty = params.get("plan_qty");

        if (workInstructionId == null || routingVersionId == null) {
            throw new IllegalArgumentException("work_instruction_id와 routing_version_id는 필수입니다.");
        }

        log.info("[pop/production] create-work-processes 요청: companyCode={}, userId={}, work_instruction_id={}, routing_version_id={}",
                companyCode, userId, workInstructionId, routingVersionId);

        // 중복 호출 방지: 이미 생성된 공정이 있는지 확인
        Integer existCount = jdbcTemplate.queryForObject(
                "SELECT COUNT(*) FROM work_order_process WHERE wo_id = ? AND company_code = ?",
                Integer.class,
                workInstructionId, companyCode
        );
        if (existCount != null && existCount > 0) {
            throw new IllegalStateException("이미 공정이 생성된 작업지시입니다.");
        }

        // 1. item_routing_detail + process_mng JOIN (공정 목록 + 공정명)
        List<Map<String, Object>> routingDetails = jdbcTemplate.queryForList(
                "SELECT rd.id, rd.seq_no, rd.process_code, " +
                "COALESCE(pm.process_name, rd.process_code) AS process_name, " +
                "rd.is_required, rd.is_fixed_order, rd.standard_time " +
                "FROM item_routing_detail rd " +
                "LEFT JOIN process_mng pm ON pm.process_code = rd.process_code AND pm.company_code = rd.company_code " +
                "WHERE rd.routing_version_id = ? AND rd.company_code = ? " +
                "ORDER BY CAST(rd.seq_no AS int) NULLS LAST",
                routingVersionId, companyCode
        );

        if (routingDetails.isEmpty()) {
            throw new IllegalArgumentException("라우팅 버전에 등록된 공정이 없습니다.");
        }

        List<Map<String, Object>> processes = new ArrayList<>();
        int totalChecklists = 0;

        for (Map<String, Object> rd : routingDetails) {
            // 2. work_order_process INSERT
            Map<String, Object> wopRow = jdbcTemplate.queryForMap(
                    "INSERT INTO work_order_process (" +
                    "company_code, wo_id, seq_no, process_code, process_name, " +
                    "is_required, is_fixed_order, standard_time, plan_qty, " +
                    "status, routing_detail_id, writer" +
                    ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) " +
                    "RETURNING id",
                    companyCode,
                    workInstructionId,
                    rd.get("seq_no"),
                    rd.get("process_code"),
                    rd.get("process_name"),
                    rd.get("is_required"),
                    rd.get("is_fixed_order"),
                    rd.get("standard_time"),
                    planQty,
                    "waiting",
                    rd.get("id"),
                    userId
            );
            Object wopId = wopRow.get("id");

            // 3. process_work_result INSERT (스냅샷 복사)
            int checklistCount = jdbcTemplate.update(
                    "INSERT INTO process_work_result (" +
                    "company_code, work_order_process_id, " +
                    "source_work_item_id, source_detail_id, " +
                    "work_phase, item_title, item_sort_order, " +
                    "detail_content, detail_type, detail_sort_order, is_required, " +
                    "inspection_code, inspection_method, unit, lower_limit, upper_limit, " +
                    "input_type, lookup_target, display_fields, duration_minutes, " +
                    "status, writer" +
                    ") " +
                    "SELECT pwi.company_code, ?, " +
                    "pwi.id, pwd.id, " +
                    "pwi.work_phase, pwi.title, pwi.sort_order::text, " +
                    "pwd.content, pwd.detail_type, pwd.sort_order::text, pwd.is_required, " +
                    "pwd.inspection_code, pwd.inspection_method, pwd.unit, pwd.lower_limit, pwd.upper_limit, " +
                    "pwd.input_type, pwd.lookup_target, pwd.display_fields, pwd.duration_minutes::text, " +
                    "'pending', ? " +
                    "FROM process_work_item pwi " +
                    "JOIN process_work_item_detail pwd ON pwd.work_item_id = pwi.id AND pwd.company_code = pwi.company_code " +
                    "WHERE pwi.routing_detail_id = ? AND pwi.company_code = ? " +
                    "ORDER BY pwi.sort_order, pwd.sort_order",
                    wopId, userId, rd.get("id"), companyCode
            );

            totalChecklists += checklistCount;

            Map<String, Object> processEntry = new HashMap<>();
            processEntry.put("id", wopId);
            processEntry.put("seq_no", rd.get("seq_no"));
            processEntry.put("process_name", rd.get("process_name"));
            processEntry.put("checklist_count", checklistCount);
            processes.add(processEntry);

            log.info("[pop/production] 공정 생성 완료: wopId={}, processName={}, checklistCount={}",
                    wopId, rd.get("process_name"), checklistCount);
        }

        log.info("[pop/production] create-work-processes 완료: companyCode={}, work_instruction_id={}, total_processes={}, total_checklists={}",
                companyCode, workInstructionId, processes.size(), totalChecklists);

        Map<String, Object> result = new HashMap<>();
        result.put("processes", processes);
        result.put("total_processes", processes.size());
        result.put("total_checklists", totalChecklists);
        return result;
    }

    /**
     * D-BE2: 타이머 API (시작/일시정지/재시작)
     */
    public Map<String, Object> controlTimer(Map<String, Object> params) {
        String companyCode = (String) params.get("company_code");
        Object workOrderProcessId = params.get("work_order_process_id");
        String action = (String) params.get("action");

        if (workOrderProcessId == null || action == null) {
            throw new IllegalArgumentException("work_order_process_id와 action은 필수입니다.");
        }

        if (!List.of("start", "pause", "resume").contains(action)) {
            throw new IllegalArgumentException("action은 start, pause, resume 중 하나여야 합니다.");
        }

        log.info("[pop/production] timer 요청: companyCode={}, work_order_process_id={}, action={}",
                companyCode, workOrderProcessId, action);

        List<Map<String, Object>> rows = switch (action) {
            case "start" -> jdbcTemplate.queryForList(
                    "UPDATE work_order_process " +
                    "SET started_at = CASE WHEN started_at IS NULL THEN NOW()::text ELSE started_at END, " +
                    "status = CASE WHEN status = 'waiting' THEN 'in_progress' ELSE status END, " +
                    "updated_date = NOW() " +
                    "WHERE id = ? AND company_code = ? " +
                    "RETURNING id, started_at, status",
                    workOrderProcessId, companyCode
            );
            case "pause" -> jdbcTemplate.queryForList(
                    "UPDATE work_order_process " +
                    "SET paused_at = NOW()::text, " +
                    "updated_date = NOW() " +
                    "WHERE id = ? AND company_code = ? AND paused_at IS NULL " +
                    "RETURNING id, paused_at",
                    workOrderProcessId, companyCode
            );
            case "resume" -> jdbcTemplate.queryForList(
                    "UPDATE work_order_process " +
                    "SET total_paused_time = (" +
                    "COALESCE(total_paused_time::int, 0) + EXTRACT(EPOCH FROM NOW() - paused_at::timestamp)::int" +
                    ")::text, " +
                    "paused_at = NULL, " +
                    "updated_date = NOW() " +
                    "WHERE id = ? AND company_code = ? AND paused_at IS NOT NULL " +
                    "RETURNING id, total_paused_time",
                    workOrderProcessId, companyCode
            );
            default -> throw new IllegalArgumentException("알 수 없는 action: " + action);
        };

        if (rows.isEmpty()) {
            throw new IllegalArgumentException("대상 공정을 찾을 수 없거나 현재 상태에서 수행할 수 없습니다.");
        }

        log.info("[pop/production] timer 완료: action={}, work_order_process_id={}", action, workOrderProcessId);

        Map<String, Object> result = new HashMap<>(rows.get(0));
        return result;
    }
}
