package com.mosquito.project.controller;

import com.mosquito.project.dto.ShortenResponse;
import com.mosquito.project.dto.ApiResponse;
import com.mosquito.project.persistence.entity.UserInviteEntity;
import com.mosquito.project.service.ShortLinkService;
import com.mosquito.project.service.PosterRenderService;
import com.mosquito.project.service.ShareConfigService;
import com.mosquito.project.persistence.repository.UserInviteRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/v1/me")
public class UserExperienceController {

    private static final Logger log = LoggerFactory.getLogger(UserExperienceController.class);

    private final ShortLinkService shortLinkService;
    private final UserInviteRepository userInviteRepository;
    private final PosterRenderService posterRenderService;
    private final ShareConfigService shareConfigService;
    private final com.mosquito.project.persistence.repository.UserRewardRepository userRewardRepository;

    public UserExperienceController(ShortLinkService shortLinkService, UserInviteRepository userInviteRepository,
                                    PosterRenderService posterRenderService, ShareConfigService shareConfigService,
                                    com.mosquito.project.persistence.repository.UserRewardRepository userRewardRepository) {
        this.shortLinkService = shortLinkService;
        this.userInviteRepository = userInviteRepository;
        this.posterRenderService = posterRenderService;
        this.shareConfigService = shareConfigService;
        this.userRewardRepository = userRewardRepository;
    }

    @GetMapping("/invitation-info")
    public ResponseEntity<ApiResponse<ShortenResponse>> getInvitationInfo(
        @RequestParam Long activityId,
        @RequestParam Long userId,
        @RequestParam(required = false, defaultValue = "default") String template
    ) {
        String shareUrl = shareConfigService.buildShareUrl(activityId, userId, template, null);
        var e = shortLinkService.create(shareUrl);
        ShortenResponse payload = new ShortenResponse(e.getCode(), "/r/" + e.getCode(), e.getOriginalUrl());
        return ResponseEntity.ok(ApiResponse.success(payload));
    }

    @GetMapping("/share-meta")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getShareMeta(
        @RequestParam Long activityId,
        @RequestParam Long userId,
        @RequestParam(required = false, defaultValue = "default") String template
    ) {
        Map<String, Object> meta = shareConfigService.getShareMeta(activityId, userId, template);
        return ResponseEntity.ok(ApiResponse.success(meta));
    }

    @GetMapping("/invited-friends")
    public ResponseEntity<ApiResponse<List<FriendDto>>> getInvitedFriends(
        @RequestParam Long activityId,
        @RequestParam Long userId,
        @RequestParam(defaultValue = "0") int page,
        @RequestParam(defaultValue = "20") int size
    ) {
        List<UserInviteEntity> all = userInviteRepository.findByActivityIdAndInviterUserId(activityId, userId);
        int from = Math.max(0, page * Math.max(1, size));
        if (from >= all.size()) {
            return ResponseEntity.ok(ApiResponse.success(List.of()));
        }
        int to = Math.min(all.size(), from + size);
        List<FriendDto> result = all.subList(from, to).stream()
            .map(e -> new FriendDto("用户" + e.getInviteeUserId(), maskPhone("1380000" + String.format("%04d", e.getInviteeUserId() % 10000)), e.getStatus()))
            .collect(Collectors.toList());
        return ResponseEntity.ok(ApiResponse.success(result));
    }

    @GetMapping(value = "/poster/image", produces = MediaType.IMAGE_PNG_VALUE)
    public ResponseEntity<byte[]> getPosterImage(
        @RequestParam Long activityId,
        @RequestParam Long userId,
        @RequestParam(required = false, defaultValue = "default") String template
    ) {
        try {
            byte[] image = posterRenderService.renderPoster(activityId, userId, template);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.IMAGE_PNG);
            headers.setCacheControl("max-age=3600");
            return new ResponseEntity<>(image, headers, HttpStatus.OK);
        } catch (Exception ex) {
            log.error("Failed to generate poster image", ex);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

    @GetMapping(value = "/poster/html", produces = MediaType.TEXT_HTML_VALUE)
    public ResponseEntity<String> getPosterHtml(
        @RequestParam Long activityId,
        @RequestParam Long userId,
        @RequestParam(required = false, defaultValue = "default") String template
    ) {
        try {
            String html = posterRenderService.renderPosterHtml(activityId, userId, template);
            return ResponseEntity.ok()
                .contentType(MediaType.TEXT_HTML)
                .header("Cache-Control", "max-age=3600")
                .body(html);
        } catch (Exception ex) {
            log.error("Failed to generate poster HTML", ex);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

    @GetMapping(value = "/poster/config")
    public ResponseEntity<ApiResponse<PosterConfigDto>> getPosterConfig(
        @RequestParam(required = false, defaultValue = "default") String template
    ) {
        PosterConfigDto config = new PosterConfigDto();
        config.setTemplate(template);
        config.setImageUrl("/api/v1/me/poster/image?activityId={activityId}&userId={userId}&template=" + template);
        config.setHtmlUrl("/api/v1/me/poster/html?activityId={activityId}&userId={userId}&template=" + template);
        return ResponseEntity.ok(ApiResponse.success(config));
    }

    @GetMapping("/rewards")
    public ResponseEntity<ApiResponse<List<RewardDto>>> getRewards(
        @RequestParam Long activityId,
        @RequestParam Long userId,
        @RequestParam(defaultValue = "0") int page,
        @RequestParam(defaultValue = "20") int size
    ) {
        var all = userRewardRepository.findByActivityIdAndUserIdOrderByCreatedAtDesc(activityId, userId);
        int from = Math.max(0, page * Math.max(1, size));
        if (from >= all.size()) {
            return ResponseEntity.ok(ApiResponse.success(java.util.List.of()));
        }
        int to = Math.min(all.size(), from + size);
        var list = all.subList(from, to).stream()
            .map(e -> new RewardDto(e.getType(), e.getPoints(), e.getCreatedAt().toString()))
            .collect(java.util.stream.Collectors.toList());
        return ResponseEntity.ok(ApiResponse.success(list));
    }

    public static class FriendDto {
        private String nickname;
        private String maskedPhone;
        private String status;

        public FriendDto(String nickname, String maskedPhone, String status) {
            this.nickname = nickname;
            this.maskedPhone = maskedPhone;
            this.status = status;
        }
        public String getNickname() { return nickname; }
        public String getMaskedPhone() { return maskedPhone; }
        public String getStatus() { return status; }
    }

    public static class RewardDto {
        private String type;
        private int points;
        private String createdAt;

        public RewardDto(String type, int points, String createdAt) {
            this.type = type;
            this.points = points;
            this.createdAt = createdAt;
        }
        public String getType() { return type; }
        public int getPoints() { return points; }
        public String getCreatedAt() { return createdAt; }
    }

    public static class PosterConfigDto {
        private String template;
        private String imageUrl;
        private String htmlUrl;

        public String getTemplate() { return template; }
        public void setTemplate(String template) { this.template = template; }
        public String getImageUrl() { return imageUrl; }
        public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; }
        public String getHtmlUrl() { return htmlUrl; }
        public void setHtmlUrl(String htmlUrl) { this.htmlUrl = htmlUrl; }
    }

    private String maskPhone(String phone) {
        if (phone == null || phone.length() < 7) return "**********";
        return phone.substring(0, 3) + "****" + phone.substring(phone.length() - 4);
    }
}
