package com.erp.controller;

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

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
@Slf4j
public class AuthController {

    private final AuthService authService;
    private final JwtTokenProvider jwtTokenProvider;

    /**
     * POST /api/auth/login
     */
    @PostMapping("/login")
    public ResponseEntity<ApiResponse<Map<String, Object>>> login(
            @RequestBody Map<String, Object> body,
            HttpServletRequest request) {
        String userId = (String) body.get("user_id");
        String password = (String) body.get("password");

        if (!StringUtils.hasText(userId) || !StringUtils.hasText(password)) {
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("사용자 ID와 비밀번호를 입력해주세요."));
        }

        Map<String, Object> params = new HashMap<>(body);
        params.put("remote_addr", getRemoteAddr(request));

        Map<String, Object> result = authService.login(params);

        if (Boolean.TRUE.equals(result.get("login_failed"))) {
            return ResponseEntity.status(401)
                    .body(ApiResponse.error((String) result.get("error_reason")));
        }

        return ResponseEntity.ok(ApiResponse.success(result, "로그인 성공"));
    }

    /**
     * POST /api/auth/refresh
     */
    @PostMapping("/refresh")
    public ResponseEntity<ApiResponse<Map<String, Object>>> refresh(HttpServletRequest request) {
        String token = resolveToken(request);
        if (!StringUtils.hasText(token)) {
            return ResponseEntity.status(401).body(ApiResponse.error("토큰이 필요합니다."));
        }

        try {
            Map<String, Object> data = authService.refreshToken(token);
            return ResponseEntity.ok(ApiResponse.success(data, "토큰 갱신 성공"));
        } catch (Exception e) {
            return ResponseEntity.status(401).body(ApiResponse.error("토큰 갱신에 실패했습니다."));
        }
    }

    /**
     * GET /api/auth/me
     */
    @GetMapping("/me")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getCurrentUser(HttpServletRequest request) {
        String token = resolveToken(request);
        if (!StringUtils.hasText(token) || !jwtTokenProvider.validateToken(token)) {
            return ResponseEntity.status(401).body(ApiResponse.error("인증되지 않은 사용자입니다."));
        }

        Map<String, Object> userInfo = authService.getUserInfo(token);
        if (userInfo == null) {
            return ResponseEntity.status(401).body(ApiResponse.error("사용자 정보를 찾을 수 없습니다."));
        }

        return ResponseEntity.ok(ApiResponse.success(userInfo, "사용자 정보 조회 성공"));
    }

    /**
     * GET /api/auth/status
     */
    @GetMapping("/status")
    public ResponseEntity<ApiResponse<Map<String, Object>>> checkAuthStatus(HttpServletRequest request) {
        String token = resolveToken(request);
        Map<String, Object> status = authService.checkAuthStatus(token);
        return ResponseEntity.ok(ApiResponse.success(status, "세션 상태 확인"));
    }

    /**
     * POST /api/auth/logout
     */
    @PostMapping("/logout")
    public ResponseEntity<ApiResponse<Void>> logout(HttpServletRequest request) {
        String token = resolveToken(request);
        if (StringUtils.hasText(token) && jwtTokenProvider.validateToken(token)) {
            try {
                String userId = jwtTokenProvider.getUserId(token);
                authService.logout(userId, getRemoteAddr(request));
            } catch (Exception e) {
                log.warn("로그아웃 처리 중 오류 (무시): {}", e.getMessage());
            }
        }
        return ResponseEntity.ok(ApiResponse.success(null, "로그아웃되었습니다."));
    }

    /**
     * POST /api/auth/switch-company
     */
    @PostMapping("/switch-company")
    public ResponseEntity<ApiResponse<Map<String, Object>>> switchCompany(
            @RequestBody Map<String, Object> body,
            HttpServletRequest request) {
        String token = resolveToken(request);
        if (!StringUtils.hasText(token) || !jwtTokenProvider.validateToken(token)) {
            return ResponseEntity.status(401).body(ApiResponse.error("인증 토큰이 필요합니다."));
        }

        String companyCode = (String) body.get("company_code");
        if (!StringUtils.hasText(companyCode)) {
            return ResponseEntity.badRequest().body(ApiResponse.error("전환할 회사 코드가 필요합니다."));
        }

        try {
            Map<String, Object> result = authService.switchCompany(token, companyCode.trim());
            return ResponseEntity.ok(ApiResponse.success(result, "회사 전환 완료"));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(403).body(ApiResponse.error(e.getMessage()));
        }
    }

    /**
     * POST /api/auth/change-password
     *
     * 본인 비밀번호 변경 (첫 로그인 강제 변경 / 평시 변경 공용).
     * Bearer 토큰에서 user_id 추출 → current_password 검증 → 새 비번 저장 + force_password_change=false.
     */
    @PostMapping("/change-password")
    public ResponseEntity<ApiResponse<Map<String, Object>>> changePassword(
            @RequestBody Map<String, Object> body,
            HttpServletRequest request) {
        String token = resolveToken(request);
        if (!StringUtils.hasText(token) || !jwtTokenProvider.validateToken(token)) {
            return ResponseEntity.status(401).body(ApiResponse.error("인증이 필요합니다."));
        }

        String currentPassword = (String) body.get("current_password");
        String newPassword = (String) body.get("new_password");
        if (!StringUtils.hasText(currentPassword) || !StringUtils.hasText(newPassword)) {
            return ResponseEntity.badRequest().body(ApiResponse.error("현재/새 비밀번호를 모두 입력해주세요."));
        }

        // Defense in depth — 전역 TenantConsistencyGuardFilter 가 이미 잡지만,
        // 비밀번호 변경은 크리티컬하므로 Service 레벨에서도 한 번 더 대조.
        // 테넌트 서브도메인 요청인데 JWT.company_code 와 tenant.company_code 가 다르면 즉시 거부.
        String tenantCompanyCode = (String) request.getAttribute("tenant_company_code");
        String jwtCompanyCode = jwtTokenProvider.getCompanyCode(token);
        if (tenantCompanyCode != null && !tenantCompanyCode.equals(jwtCompanyCode)) {
            log.warn("[ChangePassword] cross-tenant rejected: jwt={}, tenant={}", jwtCompanyCode, tenantCompanyCode);
            return ResponseEntity.status(403).body(ApiResponse.error("로그인한 회사와 접속 도메인이 일치하지 않습니다."));
        }

        try {
            Map<String, Object> data = authService.changePassword(token, currentPassword, newPassword);
            return ResponseEntity.ok(ApiResponse.success(data, "비밀번호가 변경되었습니다."));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(ApiResponse.error(e.getMessage()));
        } catch (Exception e) {
            log.error("비밀번호 변경 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("비밀번호 변경 중 오류가 발생했습니다."));
        }
    }

    /**
     * POST /api/auth/signup
     */
    @PostMapping("/signup")
    public ResponseEntity<ApiResponse<Void>> signup(@RequestBody Map<String, Object> body) {
        String userId = (String) body.get("user_id");
        String password = (String) body.get("password");
        String userName = (String) body.get("user_name");
        String phoneNumber = (String) body.get("phone_number");
        String licenseNumber = (String) body.get("license_number");
        String vehicleNumber = (String) body.get("vehicle_number");

        if (!StringUtils.hasText(userId) || !StringUtils.hasText(password)
                || !StringUtils.hasText(userName) || !StringUtils.hasText(phoneNumber)
                || !StringUtils.hasText(licenseNumber) || !StringUtils.hasText(vehicleNumber)) {
            return ResponseEntity.badRequest().body(ApiResponse.error("필수 입력값이 누락되었습니다."));
        }

        try {
            authService.signupDriver(new HashMap<>(body));
            return ResponseEntity.status(201).body(ApiResponse.success(null, "회원가입이 완료되었습니다."));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(ApiResponse.error(e.getMessage()));
        }
    }

    // ── 내부 유틸 ──────────────────────────────────────────────────────────

    private String resolveToken(HttpServletRequest request) {
        String bearer = request.getHeader("Authorization");
        if (StringUtils.hasText(bearer) && bearer.startsWith("Bearer ")) {
            return bearer.substring(7);
        }
        return null;
    }

    private String getRemoteAddr(HttpServletRequest request) {
        String addr = request.getHeader("X-Forwarded-For");
        if (!StringUtils.hasText(addr)) {
            addr = request.getRemoteAddr();
        }
        return addr != null ? addr : "unknown";
    }
}
