package kr.co.accura.wtm.domain.timesheet.entity;

import jakarta.persistence.*;
import kr.co.accura.wbx.spring.common.BaseEntity;
import kr.co.accura.wbx.spring.common.BusinessException;
import kr.co.accura.wtm.domain.timesheet.TimesheetStatus;
import lombok.*;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "timesheets", uniqueConstraints = {
    @UniqueConstraint(columnNames = {"user_id", "week_start_date"})
})
@Getter @Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Timesheet extends BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "user_id", nullable = false)
    private Long userId;

    @Column(name = "week_start_date", nullable = false)
    private LocalDate weekStartDate;

    @Column(name = "week_end_date", nullable = false)
    private LocalDate weekEndDate;

    @Enumerated(EnumType.STRING)
    @Column(length = 20)
    @Builder.Default
    private TimesheetStatus status = TimesheetStatus.DRAFT;

    @Column(name = "total_hours", precision = 10, scale = 2)
    @Builder.Default
    private BigDecimal totalHours = BigDecimal.ZERO;

    @Column(name = "submitted_at")
    private LocalDateTime submittedAt;

    @OneToMany(mappedBy = "timesheet", cascade = CascadeType.ALL, orphanRemoval = true)
    @Builder.Default
    private List<TimesheetEntry> entries = new ArrayList<>();

    // Business methods

    public void addEntry(TimesheetEntry entry) {
        entries.add(entry);
        entry.setTimesheet(this);
        recalculateTotal();
    }

    public void submit() {
        if (status != TimesheetStatus.DRAFT && status != TimesheetStatus.REJECTED) {
            throw new BusinessException("DRAFT 또는 REJECTED 상태에서만 제출 가능합니다.");
        }
        this.status = TimesheetStatus.SUBMITTED;
        this.submittedAt = LocalDateTime.now();
    }

    public void recalculateTotal() {
        this.totalHours = entries.stream()
                .map(TimesheetEntry::getHours)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
}
