package com.kamco.cd.training.log.dto;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.kamco.cd.training.common.utils.interfaces.JsonFormatDttm;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDate;
import java.time.ZonedDateTime;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

public class AuditLogDto {

  @Schema(name = "AuditLogBasic", description = "감사로그 기본 정보")
  @Getter
  public static class Basic {

    @JsonIgnore private final Long id;
    private final Long userUid;
    private final EventType eventType;
    private final EventStatus eventStatus;
    private final String menuUid;
    private final String ipAddress;
    private final String requestUri;
    private final String requestBody;
    private final Long errorLogUid;

    @JsonFormatDttm private final ZonedDateTime createdDttm;

    public Basic(
        Long id,
        Long userUid,
        EventType eventType,
        EventStatus eventStatus,
        String menuUid,
        String ipAddress,
        String requestUri,
        String requestBody,
        Long errorLogUid,
        ZonedDateTime createdDttm) {
      this.id = id;
      this.userUid = userUid;
      this.eventType = eventType;
      this.eventStatus = eventStatus;
      this.menuUid = menuUid;
      this.ipAddress = ipAddress;
      this.requestUri = requestUri;
      this.requestBody = requestBody;
      this.errorLogUid = errorLogUid;
      this.createdDttm = createdDttm;
    }
  }

  @Schema(name = "AuditCommon", description = "목록 공통")
  @Getter
  @AllArgsConstructor
  public static class AuditCommon {

    private int readCount;
    private int cudCount;
    private int printCount;
    private int downloadCount;
    private Long totalCount;
  }

  @Schema(name = "DailyAuditList", description = "일자별 목록")
  @Getter
  public static class DailyAuditList extends AuditCommon {

    private final String baseDate;

    public DailyAuditList(
        int readCount,
        int cudCount,
        int printCount,
        int downloadCount,
        Long totalCount,
        String baseDate) {
      super(readCount, cudCount, printCount, downloadCount, totalCount);
      this.baseDate = baseDate;
    }
  }

  @Schema(name = "MenuAuditList", description = "메뉴별 목록")
  @Getter
  public static class MenuAuditList extends AuditCommon {

    private final String menuId;
    private final String menuName;

    public MenuAuditList(
        String menuId,
        String menuName,
        int readCount,
        int cudCount,
        int printCount,
        int downloadCount,
        Long totalCount) {
      super(readCount, cudCount, printCount, downloadCount, totalCount);
      this.menuId = menuId;
      this.menuName = menuName;
    }
  }

  @Schema(name = "UserAuditList", description = "사용자별 목록")
  @Getter
  public static class UserAuditList extends AuditCommon {

    private final Long accountId;
    private final String loginId;
    private final String username;

    public UserAuditList(
        Long accountId,
        String loginId,
        String username,
        int readCount,
        int cudCount,
        int printCount,
        int downloadCount,
        Long totalCount) {
      super(readCount, cudCount, printCount, downloadCount, totalCount);
      this.accountId = accountId;
      this.loginId = loginId;
      this.username = username;
    }
  }

  @Schema(name = "AuditDetail", description = "감사 로그 상세 공통")
  @Getter
  @AllArgsConstructor
  public static class AuditDetail {

    private Long logId;
    private EventType eventType;
    private LogDetail detail;
  }

  @Schema(name = "DailyDetail", description = "일자별 로그 상세")
  @Getter
  public static class DailyDetail extends AuditDetail {

    private final String userName;
    private final String loginId;
    private final String menuName;
    private final String logDateTime;

    public DailyDetail(
        Long logId,
        String userName,
        String loginId,
        String menuName,
        EventType eventType,
        String logDateTime,
        LogDetail detail) {
      super(logId, eventType, detail);
      this.userName = userName;
      this.loginId = loginId;
      this.menuName = menuName;
      this.logDateTime = logDateTime;
    }
  }

  @Schema(name = "MenuDetail", description = "메뉴별 로그 상세")
  @Getter
  public static class MenuDetail extends AuditDetail {

    private final String logDateTime;
    private final String userName;
    private final String loginId;

    public MenuDetail(
        Long logId,
        String logDateTime,
        String userName,
        String loginId,
        EventType eventType,
        LogDetail detail) {
      super(logId, eventType, detail);
      this.logDateTime = logDateTime;
      this.userName = userName;
      this.loginId = loginId;
    }
  }

  @Schema(name = "UserDetail", description = "사용자별 로그 상세")
  @Getter
  public static class UserDetail extends AuditDetail {

    private final String logDateTime;
    private final String menuNm;

    public UserDetail(
        Long logId, String logDateTime, String menuNm, EventType eventType, LogDetail detail) {
      super(logId, eventType, detail);
      this.logDateTime = logDateTime;
      this.menuNm = menuNm;
    }
  }

  @Getter
  @Setter
  @AllArgsConstructor
  public static class LogDetail {

    String serviceName;
    String parentMenuName;
    String menuName;
    String menuUrl;
    String menuDescription;
    Long sortOrder;
    boolean used;
  }

  @Schema(name = "searchReq", description = "일자별 로그 검색 요청")
  @Getter
  @Setter
  @NoArgsConstructor
  @AllArgsConstructor
  public static class searchReq {

    // 페이징 파라미터
    private int page = 0;
    private int size = 20;
    private String sort;

    public Pageable toPageable() {
      if (sort != null && !sort.isEmpty()) {
        String[] sortParams = sort.split(",");
        String property = sortParams[0];
        Sort.Direction direction =
            sortParams.length > 1 ? Sort.Direction.fromString(sortParams[1]) : Sort.Direction.ASC;
        return PageRequest.of(page, size, Sort.by(direction, property));
      }
      return PageRequest.of(page, size);
    }
  }

  @Getter
  @Setter
  public static class DownloadReq {

    UUID uuid;
    LocalDate startDate;
    LocalDate endDate;
    String searchValue;
    String menuId;
    String requestUri;
  }

  @Getter
  @Setter
  @AllArgsConstructor
  public static class DownloadRes {

    String name;
    String employeeNo;
    @JsonFormatDttm ZonedDateTime downloadDttm;
  }
}
