package com.ikon.projectmanagement.mapper;

import com.ikon.projectmanagement.dto.request.*;
import com.ikon.projectmanagement.dto.response.MeetingResponseDTO;
import com.ikon.projectmanagement.entity.Meeting;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class MeetingMapper {

    // ================= DTO TO ENTITY =================

    public Meeting toEntity(MeetingRequestDTO dto) {
        Meeting meeting = new Meeting();

        if (dto.getMeeting() != null) {
            meeting.setTitle(dto.getMeeting().getTitle());
            meeting.setProjectName(dto.getMeeting().getProjectName());
            meeting.setPlace(dto.getMeeting().getPlace());
            meeting.setDate(parseDate(dto.getMeeting().getDate()));
            meeting.setTime(dto.getMeeting().getTime());
            meeting.setDuration(dto.getMeeting().getDuration());
            meeting.setCalledBy(dto.getMeeting().getCalledBy());
        }

        if (dto.getAttendees() != null && dto.getAttendees().getAttendees() != null) {
            meeting.setAttendees(
                    dto.getAttendees().getAttendees().stream()
                            .map(this::toAttendeeEntity)
                            .collect(Collectors.toList())
            );
        }

        if (dto.getAgenda() != null && dto.getAgenda().getAgenda() != null) {
            meeting.setAgenda(
                    dto.getAgenda().getAgenda().stream()
                            .map(this::toAgendaItemEntity)
                            .collect(Collectors.toList())
            );
        }

        if (dto.getDecisions() != null && dto.getDecisions().getDecisions() != null) {
            meeting.setDecisions(dto.getDecisions().getDecisions());
        }

        if (dto.getActions() != null && dto.getActions().getActions() != null) {
            meeting.setActions(
                    dto.getActions().getActions().stream()
                            .map(this::toActionItemEntity)
                            .collect(Collectors.toList())
            );
        }

        if (dto.getOthers() != null) {
            meeting.setNotes(dto.getOthers().getNotes());
        }

        if (dto.getProjectIdentifier() != null) {
            meeting.setProjectIdentifier(dto.getProjectIdentifier());
        }

        meeting.setStatus(dto.getStatus());

        return meeting;
    }

    // ================= UPDATE ENTITY FROM DTO =================

    public void updateEntityFromDTO(Meeting existing, MeetingRequestDTO dto) {

        if (dto.getMeeting() != null) {
            existing.setTitle(dto.getMeeting().getTitle());
            existing.setProjectName(dto.getMeeting().getProjectName());
            existing.setPlace(dto.getMeeting().getPlace());
            existing.setDate(parseDate(dto.getMeeting().getDate()));
            existing.setTime(dto.getMeeting().getTime());
            existing.setDuration(dto.getMeeting().getDuration());
            existing.setCalledBy(dto.getMeeting().getCalledBy());
        }

        if (dto.getAttendees() != null && dto.getAttendees().getAttendees() != null) {
            existing.setAttendees(
                    dto.getAttendees().getAttendees().stream()
                            .map(this::toAttendeeEntity)
                            .collect(Collectors.toList())
            );
        }

        if (dto.getAgenda() != null && dto.getAgenda().getAgenda() != null) {
            existing.setAgenda(
                    dto.getAgenda().getAgenda().stream()
                            .map(this::toAgendaItemEntity)
                            .collect(Collectors.toList())
            );
        }

        if (dto.getDecisions() != null && dto.getDecisions().getDecisions() != null) {
            existing.setDecisions(dto.getDecisions().getDecisions());
        }

        if (dto.getActions() != null && dto.getActions().getActions() != null) {
            existing.setActions(
                    dto.getActions().getActions().stream()
                            .map(this::toActionItemEntity)
                            .collect(Collectors.toList())
            );
        }

        if (dto.getOthers() != null) {
            existing.setNotes(dto.getOthers().getNotes());
        }

        if (dto.getProjectIdentifier() != null) {
            existing.setProjectIdentifier(dto.getProjectIdentifier());
        }

        existing.setStatus(dto.getStatus());
    }

    // ================= ENTITY TO DTO =================

    public MeetingResponseDTO toResponseDTO(Meeting meeting) {
        MeetingResponseDTO dto = new MeetingResponseDTO();

        dto.setId(meeting.getId());

        MeetingDetailsDTO detailsDTO = new MeetingDetailsDTO();
        detailsDTO.setTitle(meeting.getTitle());
        detailsDTO.setProjectName(meeting.getProjectName());
        detailsDTO.setPlace(meeting.getPlace());
        detailsDTO.setDate(formatDate(meeting.getDate()));
        detailsDTO.setTime(meeting.getTime());
        detailsDTO.setDuration(meeting.getDuration());
        detailsDTO.setCalledBy(meeting.getCalledBy());
        dto.setMeeting(detailsDTO);

        AttendeesWrapperDTO attendeesWrapper = new AttendeesWrapperDTO();
        attendeesWrapper.setAttendees(
                meeting.getAttendees() != null
                        ? meeting.getAttendees().stream()
                                .map(this::toAttendeeDTO)
                                .collect(Collectors.toList())
                        : Collections.emptyList()
        );
        dto.setAttendees(attendeesWrapper);

        AgendaWrapperDTO agendaWrapper = new AgendaWrapperDTO();
        agendaWrapper.setAgenda(
                meeting.getAgenda() != null
                        ? meeting.getAgenda().stream()
                                .map(this::toAgendaItemDTO)
                                .collect(Collectors.toList())
                        : Collections.emptyList()
        );
        dto.setAgenda(agendaWrapper);

        DecisionsWrapperDTO decisionsWrapper = new DecisionsWrapperDTO();
        decisionsWrapper.setDecisions(
                meeting.getDecisions() != null
                        ? meeting.getDecisions()
                        : Collections.emptyList()
        );
        dto.setDecisions(decisionsWrapper);

        ActionsWrapperDTO actionsWrapper = new ActionsWrapperDTO();
        actionsWrapper.setActions(
                meeting.getActions() != null
                        ? meeting.getActions().stream()
                                .map(this::toActionItemDTO)
                                .collect(Collectors.toList())
                        : Collections.emptyList()
        );
        dto.setActions(actionsWrapper);

        OthersDTO othersDTO = new OthersDTO();
        othersDTO.setNotes(meeting.getNotes());
        dto.setOthers(othersDTO);

        if (meeting.getProjectIdentifier() != null) {
            dto.setProjectIdentifier(meeting.getProjectIdentifier());
        }

        dto.setStatus(meeting.getStatus());
        dto.setCreatedAt(meeting.getCreatedAt());
        dto.setUpdatedAt(meeting.getUpdatedAt());

        return dto;
    }

    // ================= LIST MAPPING =================

    public List<MeetingResponseDTO> toResponseDTOList(List<Meeting> meetings) {
        return meetings.stream()
                .map(this::toResponseDTO)
                .collect(Collectors.toList());
    }

    // ================= PRIVATE HELPERS =================

    private LocalDate parseDate(String dateStr) {
        if (dateStr == null || dateStr.isBlank()) return null;
        try {
            return LocalDate.parse(dateStr);
        } catch (Exception e) {
            return null;
        }
    }

    private String formatDate(LocalDate date) {
        return date != null ? date.toString() : null;
    }

    private Meeting.Attendee toAttendeeEntity(AttendeeDTO dto) {
        Meeting.Attendee attendee = new Meeting.Attendee();
        attendee.setName(dto.getName());
        attendee.setRole(dto.getRole());
        attendee.setContact(dto.getContact());
        return attendee;
    }

    private AttendeeDTO toAttendeeDTO(Meeting.Attendee attendee) {
        AttendeeDTO dto = new AttendeeDTO();
        dto.setName(attendee.getName());
        dto.setRole(attendee.getRole());
        dto.setContact(attendee.getContact());
        return dto;
    }

    private Meeting.AgendaItem toAgendaItemEntity(AgendaItemDTO dto) {
        Meeting.AgendaItem agendaItem = new Meeting.AgendaItem();
        agendaItem.setItem(dto.getItem());
        agendaItem.setOwner(dto.getOwner());
        return agendaItem;
    }

    private AgendaItemDTO toAgendaItemDTO(Meeting.AgendaItem agendaItem) {
        AgendaItemDTO dto = new AgendaItemDTO();
        dto.setItem(agendaItem.getItem());
        dto.setOwner(agendaItem.getOwner());
        return dto;
    }

    private Meeting.ActionItem toActionItemEntity(ActionItemDTO dto) {
        Meeting.ActionItem actionItem = new Meeting.ActionItem();
        actionItem.setItem(dto.getItem());
        actionItem.setResponsible(dto.getResponsible());
        actionItem.setDueDate(parseDate(dto.getDueDate()));
        return actionItem;
    }

    private ActionItemDTO toActionItemDTO(Meeting.ActionItem actionItem) {
        ActionItemDTO dto = new ActionItemDTO();
        dto.setItem(actionItem.getItem());
        dto.setResponsible(actionItem.getResponsible());
        dto.setDueDate(formatDate(actionItem.getDueDate()));
        return dto;
    }
}
