package kr.co.zioinfo.web.controller;

import kr.co.zioinfo.web.model.Member;
import kr.co.zioinfo.web.repository.MemberRepository;
import kr.co.zioinfo.web.security.JwtUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import java.util.*;

@RestController
@RequestMapping("/api/members")
@RequiredArgsConstructor
public class MemberController {

    private final MemberRepository memberRepo;
    private final JwtUtil jwtUtil;
    private final PasswordEncoder passwordEncoder;

    // ── 회원가입 ─────────────────────────────────────────────────
    @PostMapping("/register")
    public ResponseEntity<?> register(@RequestBody Map<String, String> body) {
        String email = body.get("email");
        String name  = body.get("name");
        String pw    = body.get("password");
        String phone = body.getOrDefault("phone", "");
        String company = body.getOrDefault("company", "");

        if (email == null || name == null || pw == null)
            return ResponseEntity.badRequest().body(Map.of("message", "이름, 이메일, 비밀번호는 필수입니다."));

        if (memberRepo.existsByEmail(email))
            return ResponseEntity.status(409).body(Map.of("message", "이미 가입된 이메일입니다."));

        if (pw.length() < 8)
            return ResponseEntity.badRequest().body(Map.of("message", "비밀번호는 8자 이상이어야 합니다."));

        Member m = Member.builder()
                .name(name)
                .email(email)
                .password(passwordEncoder.encode(pw))
                .phone(phone)
                .company(company)
                .role("USER")
                .active(true)
                .build();
        memberRepo.save(m);

        String token = jwtUtil.generate("member:" + m.getEmail());
        return ResponseEntity.ok(buildResponse(m, token));
    }

    // ── 이메일 중복 확인 ─────────────────────────────────────────
    @GetMapping("/check-email")
    public ResponseEntity<?> checkEmail(@RequestParam String email) {
        return ResponseEntity.ok(Map.of("exists", memberRepo.existsByEmail(email)));
    }

    // ── 로그인 ───────────────────────────────────────────────────
    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody Map<String, String> body) {
        String email = body.get("email");
        String pw    = body.get("password");
        return memberRepo.findByEmail(email)
                .filter(m -> m.isActive() && passwordEncoder.matches(pw, m.getPassword()))
                .map(m -> ResponseEntity.ok(buildResponse(m, jwtUtil.generate("member:" + m.getEmail()))))
                .orElse(ResponseEntity.status(401).body(Map.of("message", "이메일 또는 비밀번호가 올바르지 않습니다.")));
    }

    // ── SNS 로그인 (카카오·네이버·구글) ─────────────────────────
    @PostMapping("/social-login")
    public ResponseEntity<?> socialLogin(@RequestBody Map<String, String> body) {
        String provider = body.get("provider");   // kakao | naver | google
        String email    = body.get("email");
        String name     = body.getOrDefault("name", "회원");
        String socialId = body.getOrDefault("id", "");

        if (email == null || email.isBlank())
            return ResponseEntity.badRequest().body(Map.of("message", "SNS 이메일 정보가 없습니다."));

        // 기존 회원이면 로그인, 없으면 자동 가입
        Member m = memberRepo.findByEmail(email).orElseGet(() ->
                memberRepo.save(Member.builder()
                        .name(name)
                        .email(email)
                        .password(passwordEncoder.encode(UUID.randomUUID().toString()))
                        .role("USER")
                        .active(true)
                        .build())
        );

        if (!m.isActive())
            return ResponseEntity.status(403).body(Map.of("message", "비활성화된 계정입니다."));

        String token = jwtUtil.generate("member:" + m.getEmail());
        Map<String, Object> res = buildResponse(m, token);
        res.put("provider", provider);
        return ResponseEntity.ok(res);
    }

    // ── 내 정보 조회 ─────────────────────────────────────────────
    @GetMapping("/me")
    public ResponseEntity<?> getMe(@RequestHeader("Authorization") String authHeader) {
        return extractEmail(authHeader)
                .flatMap(memberRepo::findByEmail)
                .map(m -> ResponseEntity.ok(buildResponse(m, null)))
                .orElse(ResponseEntity.status(401).body(Map.of("message", "인증이 필요합니다.")));
    }

    // ── 내 정보 수정 ─────────────────────────────────────────────
    @PutMapping("/me")
    public ResponseEntity<?> updateMe(@RequestHeader("Authorization") String authHeader,
                                      @RequestBody Map<String, String> body) {
        return extractEmail(authHeader)
                .flatMap(memberRepo::findByEmail)
                .map(m -> {
                    if (body.containsKey("name"))    m.setName(body.get("name"));
                    if (body.containsKey("phone"))   m.setPhone(body.get("phone"));
                    if (body.containsKey("company")) m.setCompany(body.get("company"));
                    if (body.containsKey("password") && body.get("password").length() >= 8)
                        m.setPassword(passwordEncoder.encode(body.get("password")));
                    memberRepo.save(m);
                    return ResponseEntity.ok(buildResponse(m, null));
                })
                .orElse(ResponseEntity.status(401).body(Map.of("message", "인증이 필요합니다.")));
    }

    // ── 내부 유틸 ────────────────────────────────────────────────
    private Optional<String> extractEmail(String authHeader) {
        if (authHeader == null || !authHeader.startsWith("Bearer ")) return Optional.empty();
        String subject = jwtUtil.extractUsername(authHeader.substring(7));
        if (subject == null || !subject.startsWith("member:")) return Optional.empty();
        return Optional.of(subject.substring(7));
    }

    private Map<String, Object> buildResponse(Member m, String token) {
        Map<String, Object> r = new LinkedHashMap<>();
        r.put("id",        m.getId());
        r.put("name",      m.getName());
        r.put("email",     m.getEmail());
        r.put("phone",     m.getPhone());
        r.put("company",   m.getCompany());
        r.put("role",      m.getRole());
        r.put("createdAt", m.getCreatedAt());
        if (token != null) r.put("token", token);
        return r;
    }
}
