package gc.mda.kcg.master;

import gc.mda.kcg.permission.annotation.RequirePermission;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;

import java.util.List;

/**
 * 마스터 데이터 통합 컨트롤러.
 * 코드 마스터, 어구 유형, 함정, 선박 허가 조회/관리 API 제공.
 */
@RestController
@RequiredArgsConstructor
public class MasterDataController {

    private final CodeMasterRepository codeMasterRepository;
    private final GearTypeRepository gearTypeRepository;
    private final PatrolShipRepository patrolShipRepository;
    private final VesselPermitRepository vesselPermitRepository;

    // ========================================================================
    // 코드 마스터 (인증만, 권한 불필요)
    // ========================================================================

    @GetMapping("/api/codes")
    public List<CodeMaster> listCodes(@RequestParam String group) {
        return codeMasterRepository.findByGroupCodeAndIsActiveTrueOrderBySortOrder(group);
    }

    @GetMapping("/api/codes/{codeId}/children")
    public List<CodeMaster> listChildren(@PathVariable String codeId) {
        return codeMasterRepository.findByParentIdOrderBySortOrder(codeId);
    }

    // ========================================================================
    // 어구 유형 (조회: 인증만 / 생성·수정: admin:system-config)
    // ========================================================================

    @GetMapping("/api/gear-types")
    public List<GearType> listGearTypes() {
        return gearTypeRepository.findByIsActiveTrueOrderByDisplayOrder();
    }

    @GetMapping("/api/gear-types/{gearCode}")
    public GearType getGearType(@PathVariable String gearCode) {
        return gearTypeRepository.findById(gearCode)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND,
                        "어구 유형을 찾을 수 없습니다: " + gearCode));
    }

    @PostMapping("/api/gear-types")
    @RequirePermission(resource = "admin:system-config", operation = "CREATE")
    public GearType createGearType(@RequestBody GearType gearType) {
        if (gearTypeRepository.existsById(gearType.getGearCode())) {
            throw new ResponseStatusException(HttpStatus.CONFLICT,
                    "이미 존재하는 어구 코드입니다: " + gearType.getGearCode());
        }
        return gearTypeRepository.save(gearType);
    }

    @PutMapping("/api/gear-types/{gearCode}")
    @RequirePermission(resource = "admin:system-config", operation = "UPDATE")
    public GearType updateGearType(@PathVariable String gearCode, @RequestBody GearType gearType) {
        if (!gearTypeRepository.existsById(gearCode)) {
            throw new ResponseStatusException(HttpStatus.NOT_FOUND,
                    "어구 유형을 찾을 수 없습니다: " + gearCode);
        }
        gearType.setGearCode(gearCode);
        return gearTypeRepository.save(gearType);
    }

    // ========================================================================
    // 함정 (patrol 권한)
    // ========================================================================

    @GetMapping("/api/patrol-ships")
    @RequirePermission(resource = "patrol:patrol-route", operation = "READ")
    public List<PatrolShip> listPatrolShips() {
        return patrolShipRepository.findByIsActiveTrueOrderByShipCode();
    }

    @PatchMapping("/api/patrol-ships/{id}/status")
    @RequirePermission(resource = "patrol:patrol-route", operation = "UPDATE")
    public PatrolShip updatePatrolShipStatus(
            @PathVariable Long id,
            @RequestBody PatrolShipStatusRequest request
    ) {
        PatrolShip ship = patrolShipRepository.findById(id)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND,
                        "함정을 찾을 수 없습니다: " + id));

        if (request.status() != null) ship.setCurrentStatus(request.status());
        if (request.lat() != null) ship.setCurrentLat(request.lat());
        if (request.lon() != null) ship.setCurrentLon(request.lon());
        if (request.zoneCode() != null) ship.setCurrentZoneCode(request.zoneCode());
        if (request.fuelPct() != null) ship.setFuelPct(request.fuelPct());

        return patrolShipRepository.save(ship);
    }

    // ========================================================================
    // 선박 허가 (vessel 권한)
    // ========================================================================

    @GetMapping("/api/vessel-permits")
    // 인증된 사용자 모두 접근 가능 (메뉴 권한이 아닌 공통 마스터 데이터)
    public Page<VesselPermit> listVesselPermits(
            @RequestParam(required = false) String flag,
            @RequestParam(required = false) String permitStatus,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "20") int size
    ) {
        PageRequest pageable = PageRequest.of(page, size);
        if (flag != null) {
            return vesselPermitRepository.findByFlagCountry(flag, pageable);
        }
        if (permitStatus != null) {
            return vesselPermitRepository.findByPermitStatus(permitStatus, pageable);
        }
        return vesselPermitRepository.findAll(pageable);
    }

    @GetMapping("/api/vessel-permits/{mmsi}")
    // 인증된 사용자 모두 접근 가능 (메뉴 권한이 아닌 공통 마스터 데이터)
    public VesselPermit getVesselPermit(@PathVariable String mmsi) {
        return vesselPermitRepository.findByMmsi(mmsi)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND,
                        "선박 허가 정보를 찾을 수 없습니다: " + mmsi));
    }

    // ========================================================================
    // 내부 DTO
    // ========================================================================

    record PatrolShipStatusRequest(
            String status,
            Double lat,
            Double lon,
            String zoneCode,
            Integer fuelPct
    ) {}
}
