package com.erp.controller;

import com.erp.dto.ApiResponse;
import com.erp.service.DynamicFormService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.regex.Pattern;

@RestController
@RequestMapping("/api/dynamic-form")
@RequiredArgsConstructor
@Slf4j
public class DynamicFormController {

    private final DynamicFormService dynamicFormService;

    private static final Pattern VALID_NAME = Pattern.compile("^[a-zA-Z_][a-zA-Z0-9_]*$");

    // ── POST /save ────────────────────────────────────────────────────────────

    @PostMapping("/save")
    public ResponseEntity<ApiResponse<Object>> saveFormData(
            @RequestAttribute("user_id") String userId,
            @RequestAttribute("company_code") String companyCode,
            @RequestBody Map<String, Object> body,
            HttpServletRequest request) {

        Object screenIdRaw = body.get("screen_id");
        String tableName = (String) body.get("table_name");
        Map<String, Object> data = (Map<String, Object>) body.get("data");

        if (screenIdRaw == null || tableName == null || data == null) {
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("필수 필드가 누락되었습니다. (screenId, tableName, data)"));
        }

        int screenId = ((Number) screenIdRaw).intValue();

        Map<String, Object> formDataWithMeta = new LinkedHashMap<>(data);
        formDataWithMeta.put("created_by", userId);
        formDataWithMeta.put("updated_by", userId);
        formDataWithMeta.put("writer", data.getOrDefault("writer", userId));
        formDataWithMeta.put("screen_id", screenId);

        if (data.containsKey("company_code")) {
            formDataWithMeta.put("company_code", data.get("company_code"));
        } else if (companyCode != null && !"*".equals(companyCode)) {
            formDataWithMeta.put("company_code", companyCode);
        }

        String ipAddress = Optional.ofNullable(request.getHeader("X-Forwarded-For"))
                .orElse(request.getRemoteAddr());

        try {
            Object result = dynamicFormService.saveFormData(screenId, tableName, formDataWithMeta, ipAddress);
            return ResponseEntity.ok(ApiResponse.success(result, "데이터가 성공적으로 저장되었습니다."));
        } catch (Exception e) {
            log.error("폼 데이터 저장 실패: {}", e.getMessage(), e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error(e.getMessage() != null ? e.getMessage() : "데이터 저장에 실패했습니다."));
        }
    }

    // ── POST /save-enhanced ───────────────────────────────────────────────────

    @PostMapping("/save-enhanced")
    public ResponseEntity<ApiResponse<Object>> saveFormDataEnhanced(
            @RequestAttribute("user_id") String userId,
            @RequestAttribute("company_code") String companyCode,
            @RequestBody Map<String, Object> body) {

        Object screenIdRaw = body.get("screen_id");
        String tableName = (String) body.get("table_name");
        Map<String, Object> data = (Map<String, Object>) body.get("data");

        if (screenIdRaw == null || tableName == null || data == null) {
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("필수 필드가 누락되었습니다. (screenId, tableName, data)"));
        }

        int screenId = ((Number) screenIdRaw).intValue();

        Map<String, Object> formDataWithMeta = new LinkedHashMap<>(data);
        formDataWithMeta.put("created_by", userId);
        formDataWithMeta.put("updated_by", userId);
        formDataWithMeta.put("writer", data.getOrDefault("writer", userId));
        formDataWithMeta.put("screen_id", screenId);

        if (data.containsKey("company_code")) {
            formDataWithMeta.put("company_code", data.get("company_code"));
        } else if (companyCode != null && !"*".equals(companyCode)) {
            formDataWithMeta.put("company_code", companyCode);
        }

        try {
            Object result = dynamicFormService.saveFormDataEnhanced(screenId, tableName, formDataWithMeta);
            return ResponseEntity.ok(ApiResponse.success(result, "데이터가 성공적으로 저장되었습니다."));
        } catch (Exception e) {
            log.error("개선된 폼 데이터 저장 실패: {}", e.getMessage(), e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error(e.getMessage() != null ? e.getMessage() : "데이터 저장에 실패했습니다."));
        }
    }

    // ── PUT /update-field ─────────────────────────────────────────────────────

    @PutMapping("/update-field")
    public ResponseEntity<ApiResponse<Object>> updateFieldValue(
            @RequestAttribute("user_id") String userId,
            @RequestAttribute("company_code") String companyCode,
            @RequestBody Map<String, Object> body) {

        String tableName = (String) body.get("table_name");
        String keyField = (String) body.get("key_field");
        Object keyValue = body.get("key_value");
        String updateField = (String) body.get("update_field");
        Object updateValue = body.get("update_value");

        if (tableName == null || keyField == null || keyValue == null
                || updateField == null || updateValue == null) {
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("필수 필드가 누락되었습니다. (tableName, keyField, keyValue, updateField, updateValue)"));
        }

        if (!VALID_NAME.matcher(tableName).matches()
                || !VALID_NAME.matcher(keyField).matches()
                || !VALID_NAME.matcher(updateField).matches()) {
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("유효하지 않은 테이블명 또는 컬럼명입니다."));
        }

        try {
            Map<String, Object> result = dynamicFormService.updateFieldValue(
                    tableName, keyField, keyValue, updateField, updateValue, companyCode, userId);
            return ResponseEntity.ok(ApiResponse.success(result, "필드 값이 업데이트되었습니다."));
        } catch (Exception e) {
            log.error("[updateFieldValue] 실패: {}", e.getMessage(), e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error(e.getMessage() != null ? e.getMessage() : "필드 업데이트에 실패했습니다."));
        }
    }

    // ── PUT /{id} ─────────────────────────────────────────────────────────────

    @PutMapping("/{id}")
    public ResponseEntity<ApiResponse<Object>> updateFormData(
            @PathVariable String id,
            @RequestAttribute("user_id") String userId,
            @RequestAttribute("company_code") String companyCode,
            @RequestBody Map<String, Object> body) {

        String tableName = (String) body.get("table_name");
        Map<String, Object> data = (Map<String, Object>) body.get("data");

        if (tableName == null || data == null) {
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("필수 필드가 누락되었습니다. (tableName, data)"));
        }

        Map<String, Object> formDataWithMeta = new LinkedHashMap<>(data);
        formDataWithMeta.put("updated_by", userId);
        formDataWithMeta.put("writer", data.getOrDefault("writer", userId));
        formDataWithMeta.put("updated_at", new java.util.Date());

        try {
            Map<String, Object> result = dynamicFormService.updateFormData(id, tableName, formDataWithMeta);
            return ResponseEntity.ok(ApiResponse.success(result, "데이터가 성공적으로 업데이트되었습니다."));
        } catch (Exception e) {
            log.error("폼 데이터 업데이트 실패: {}", e.getMessage(), e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error(e.getMessage() != null ? e.getMessage() : "데이터 업데이트에 실패했습니다."));
        }
    }

    // ── PATCH /{id}/partial ───────────────────────────────────────────────────

    @PatchMapping("/{id}/partial")
    public ResponseEntity<ApiResponse<Object>> updateFormDataPartial(
            @PathVariable String id,
            @RequestAttribute("user_id") String userId,
            @RequestAttribute("company_code") String companyCode,
            @RequestBody Map<String, Object> body) {

        String tableName = (String) body.get("table_name");
        Map<String, Object> originalData = (Map<String, Object>) body.get("original_data");
        Map<String, Object> newData = (Map<String, Object>) body.get("new_data");

        if (tableName == null || originalData == null || newData == null) {
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("필수 필드가 누락되었습니다. (tableName, originalData, newData)"));
        }

        Map<String, Object> newDataWithMeta = new LinkedHashMap<>(newData);
        newDataWithMeta.put("updated_by", userId);
        newDataWithMeta.put("writer", newData.getOrDefault("writer", userId));

        try {
            Map<String, Object> result = dynamicFormService.updateFormDataPartial(
                    id, tableName, originalData, newDataWithMeta);
            return ResponseEntity.ok(ApiResponse.success(result, "데이터가 성공적으로 업데이트되었습니다."));
        } catch (Exception e) {
            log.error("부분 업데이트 실패: {}", e.getMessage(), e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error(e.getMessage() != null ? e.getMessage() : "데이터 업데이트에 실패했습니다."));
        }
    }

    // ── DELETE /{id} ──────────────────────────────────────────────────────────

    @DeleteMapping("/{id}")
    public ResponseEntity<ApiResponse<Void>> deleteFormData(
            @PathVariable String id,
            @RequestAttribute("user_id") String userId,
            @RequestAttribute("company_code") String companyCode,
            @RequestBody(required = false) Map<String, Object> body) {

        if (body == null) body = new HashMap<>();
        String tableName = (String) body.get("table_name");
        Object screenIdRaw = body.get("screen_id");

        if (tableName == null) {
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("필수 필드가 누락되었습니다. (tableName)"));
        }

        Integer screenId = screenIdRaw != null
                ? Integer.parseInt(screenIdRaw.toString())
                : null;

        try {
            dynamicFormService.deleteFormData(id, tableName, companyCode, userId, screenId);
            return ResponseEntity.ok(ApiResponse.success(null, "데이터가 성공적으로 삭제되었습니다."));
        } catch (Exception e) {
            log.error("폼 데이터 삭제 실패: {}", e.getMessage(), e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error(e.getMessage() != null ? e.getMessage() : "데이터 삭제에 실패했습니다."));
        }
    }

    // ── GET /list ─────────────────────────────────────────────────────────────

    @GetMapping("/list")
    public ResponseEntity<ApiResponse<Object>> getFormDataListAll(
            @RequestParam(required = false) Integer screenId,
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "") String search,
            @RequestParam(defaultValue = "created_at") String sortBy,
            @RequestParam(defaultValue = "desc") String sortOrder) {
        try {
            Map<String, Object> params = new LinkedHashMap<>();
            params.put("page", page);
            params.put("size", size);
            params.put("search", search.isEmpty() ? null : search);
            params.put("sort_by", sortBy);
            params.put("sort_order", sortOrder);
            int sid = (screenId != null) ? screenId : 0;
            Map<String, Object> result = dynamicFormService.getFormDataList(sid, params);
            return ResponseEntity.ok(ApiResponse.success(result));
        } catch (Exception e) {
            log.error("폼 데이터 목록 조회 실패: {}", e.getMessage(), e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error(e.getMessage() != null ? e.getMessage() : "데이터 조회에 실패했습니다."));
        }
    }

    // ── GET /screen/{screenId} ────────────────────────────────────────────────

    @GetMapping("/screen/{screenId}")
    public ResponseEntity<ApiResponse<Object>> getFormDataList(
            @PathVariable int screenId,
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "") String search,
            @RequestParam(defaultValue = "created_at") String sortBy,
            @RequestParam(defaultValue = "desc") String sortOrder) {

        try {
            Map<String, Object> params = new LinkedHashMap<>();
            params.put("page", page);
            params.put("size", size);
            params.put("search", search.isEmpty() ? null : search);
            params.put("sort_by", sortBy);
            params.put("sort_order", sortOrder);

            Map<String, Object> result = dynamicFormService.getFormDataList(screenId, params);
            return ResponseEntity.ok(ApiResponse.success(result));
        } catch (Exception e) {
            log.error("폼 데이터 목록 조회 실패: {}", e.getMessage(), e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error(e.getMessage() != null ? e.getMessage() : "데이터 조회에 실패했습니다."));
        }
    }

    // ── GET /table/{tableName}/columns ────────────────────────────────────────

    @GetMapping("/table/{tableName}/columns")
    public ResponseEntity<ApiResponse<Object>> getTableColumns(@PathVariable String tableName) {
        try {
            List<Map<String, Object>> columns = dynamicFormService.getTableColumns(tableName);
            Map<String, Object> data = new LinkedHashMap<>();
            data.put("table_name", tableName);
            data.put("columns", columns);
            return ResponseEntity.ok(ApiResponse.success(data));
        } catch (Exception e) {
            log.error("테이블 컬럼 정보 조회 실패: {}", e.getMessage(), e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error(e.getMessage() != null ? e.getMessage() : "테이블 정보 조회에 실패했습니다."));
        }
    }

    // ── GET /table/{tableName}/primary-keys ───────────────────────────────────

    @GetMapping("/table/{tableName}/primary-keys")
    public ResponseEntity<ApiResponse<Object>> getTablePrimaryKeys(@PathVariable String tableName) {
        if (tableName == null || tableName.isEmpty()) {
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("테이블명이 누락되었습니다."));
        }

        try {
            List<String> primaryKeys = dynamicFormService.getTablePrimaryKeys(tableName);
            return ResponseEntity.ok(ApiResponse.success(primaryKeys, "기본키 조회가 완료되었습니다."));
        } catch (Exception e) {
            log.error("기본키 조회 실패: {}", e.getMessage(), e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error(e.getMessage() != null ? e.getMessage() : "기본키 조회에 실패했습니다."));
        }
    }

    // ── POST /validate ────────────────────────────────────────────────────────

    @PostMapping("/validate")
    public ResponseEntity<ApiResponse<Object>> validateFormData(
            @RequestBody Map<String, Object> body) {

        String tableName = (String) body.get("table_name");
        Map<String, Object> data = (Map<String, Object>) body.get("data");

        if (tableName == null || data == null) {
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("필수 필드가 누락되었습니다. (tableName, data)"));
        }

        try {
            Map<String, Object> result = dynamicFormService.validateFormData(tableName, data);
            return ResponseEntity.ok(ApiResponse.success(result));
        } catch (Exception e) {
            log.error("폼 데이터 검증 실패: {}", e.getMessage(), e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error(e.getMessage() != null ? e.getMessage() : "데이터 검증에 실패했습니다."));
        }
    }

    // ── GET /location-history/{tripId} ────────────────────────────────────────

    @GetMapping("/location-history/{tripId}")
    public ResponseEntity<ApiResponse<Object>> getLocationHistory(
            @PathVariable String tripId,
            @RequestAttribute("company_code") String companyCode,
            @RequestParam(required = false) String userId,
            @RequestParam(required = false) String startDate,
            @RequestParam(required = false) String endDate,
            @RequestParam(required = false) Integer limit) {

        try {
            Map<String, Object> params = new LinkedHashMap<>();
            params.put("company_code", companyCode);
            params.put("trip_id", tripId);
            if (userId != null) params.put("user_id", userId);
            if (startDate != null) params.put("start_date", startDate);
            if (endDate != null) params.put("end_date", endDate);
            params.put("limit", limit != null ? limit : 1000);

            List<Map<String, Object>> result = dynamicFormService.getLocationHistory(params);

            Map<String, Object> response = new LinkedHashMap<>();
            response.put("success", true);
            response.put("data", result);
            response.put("count", result.size());
            return ResponseEntity.ok(ApiResponse.success(response));
        } catch (Exception e) {
            log.error("[getLocationHistory] 실패: {}", e.getMessage(), e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error(e.getMessage() != null ? e.getMessage() : "위치 이력 조회에 실패했습니다."));
        }
    }

    // ── POST /location-history ────────────────────────────────────────────────

    @PostMapping("/location-history")
    public ResponseEntity<ApiResponse<Object>> saveLocationHistory(
            @RequestAttribute("user_id") String loginUserId,
            @RequestAttribute("company_code") String companyCode,
            @RequestBody Map<String, Object> body) {

        Double latitude = body.get("latitude") != null ? ((Number) body.get("latitude")).doubleValue() : null;
        Double longitude = body.get("longitude") != null ? ((Number) body.get("longitude")).doubleValue() : null;

        if (latitude == null || longitude == null) {
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("필수 필드가 누락되었습니다. (latitude, longitude)"));
        }

        String userId = body.containsKey("user_id") ? (String) body.get("user_id") : loginUserId;

        Map<String, Object> params = new LinkedHashMap<>();
        params.put("user_id", userId);
        params.put("company_code", companyCode);
        params.put("latitude", latitude);
        params.put("longitude", longitude);
        params.put("accuracy", body.get("accuracy"));
        params.put("altitude", body.get("altitude"));
        params.put("speed", body.get("speed"));
        params.put("heading", body.get("heading"));
        params.put("trip_id", body.get("trip_id"));
        params.put("trip_status", body.getOrDefault("trip_status", "active"));
        params.put("departure", body.get("departure"));
        params.put("arrival", body.get("arrival"));
        params.put("departure_name", body.get("departure_name"));
        params.put("destination_name", body.get("destination_name"));
        params.put("recorded_at", body.getOrDefault("recorded_at", new java.util.Date().toInstant().toString()));
        params.put("vehicle_id", body.get("vehicle_id"));

        try {
            Map<String, Object> result = dynamicFormService.saveLocationHistory(params);
            return ResponseEntity.ok(ApiResponse.success(result, "위치 이력이 저장되었습니다."));
        } catch (Exception e) {
            log.error("[saveLocationHistory] 실패: {}", e.getMessage(), e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error(e.getMessage() != null ? e.getMessage() : "위치 이력 저장에 실패했습니다."));
        }
    }

    // ── GET /{id} ─────────────────────────────────────────────────────────────

    @GetMapping("/{id}")
    public ResponseEntity<ApiResponse<Object>> getFormData(@PathVariable int id) {
        try {
            Map<String, Object> data = dynamicFormService.getFormData(id);
            if (data == null) {
                return ResponseEntity.status(404)
                        .body(ApiResponse.error("데이터를 찾을 수 없습니다."));
            }
            return ResponseEntity.ok(ApiResponse.success(data));
        } catch (Exception e) {
            log.error("폼 데이터 단건 조회 실패: {}", e.getMessage(), e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error(e.getMessage() != null ? e.getMessage() : "데이터 조회에 실패했습니다."));
        }
    }
}
