package com.healthcare.ohctech.controller;

import com.healthcare.ohctech.dto.TreatmentInternalExternalDto;
import com.healthcare.ohctech.entity.*;
import com.healthcare.ohctech.repository.EmployeeAppointmentRepo;
import com.healthcare.ohctech.service.impl.AuthServiceImpl;
import com.healthcare.ohctech.service.impl.TreatmentServiceImpl;
import com.healthcare.ohctech.util.PaginationUtil;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/treatments")
public class TreatmentController {

    @Autowired
    private TreatmentServiceImpl treatmentServiceImpl;

    @Autowired
    private EmployeeAppointmentRepo employeeAppointmentRepo;

    @Autowired
    private AuthServiceImpl authServiceImpl;

    @GetMapping("/{appointmentId}")
    public ResponseEntity<?> getTreatmentsByAppointmentId(@PathVariable Long appointmentId) {
        List<Treatment> treatments = treatmentServiceImpl.getTreatmentByAppointmentId(appointmentId);
        List<TreatmentExternal> treatmentExternals = treatmentServiceImpl.getTreatmentExternalsByAppointmentId(appointmentId);

        Map<String, Object> response = new LinkedHashMap<>();

        List<Map<String, Object>> internalTreatments = new ArrayList<>();
        for (Treatment treatment : treatments) {
            Map<String, Object> treatmentData = new LinkedHashMap<>();
            treatmentData.put("id", treatment.getId());
            treatmentData.put("appointmentId", treatment.getEmployeeAppointment() != null ? treatment.getEmployeeAppointment().getId() : null);
            treatmentData.put("item", mapItem(treatment.getItem()));
            treatmentData.put("frequency", mapMedicineFrequency(treatment.getMedicineFrequency()));
            treatmentData.put("timing", mapMedicineTiming(treatment.getMedicineTiming()));
            treatmentData.put("dosageCategory", mapRouteOfAdministration(treatment.getRouteOfAdministration()));
            treatmentData.put("forDays", treatment.getForDays());
            treatmentData.put("dosage", treatment.getDosage());
            treatmentData.put("itemQty", treatment.getItemQty());
            treatmentData.put("itemBatchNo", treatment.getItemBatchNo());
            treatmentData.put("issuedQty", treatment.getIssuedQty());
            treatmentData.put("issueBy", treatment.getIssueBy());
            treatmentData.put("isDisplay", treatment.getIsDisplay());
            treatmentData.put("groupItemId", treatment.getGroupItemId());
            treatmentData.put("followupId", treatment.getFollowupId());
            treatmentData.put("modifiedBy", treatment.getModifiedBy());
            treatmentData.put("lastModified", treatment.getLastModified());
            internalTreatments.add(treatmentData);
        }

        List<Map<String, Object>> externalTreatments = new ArrayList<>();
        for (TreatmentExternal treatmentExternal : treatmentExternals) {
            Map<String, Object> treatmentExternalData = new LinkedHashMap<>();
            treatmentExternalData.put("id", treatmentExternal.getId());
            treatmentExternalData.put("appointmentId", treatmentExternal.getEmployeeAppointment() != null ? treatmentExternal.getEmployeeAppointment().getId() : null);
            treatmentExternalData.put("item", treatmentExternal.getItemName());
            treatmentExternalData.put("frequency", treatmentExternal.getFrequency());
            treatmentExternalData.put("forDays", treatmentExternal.getForDays());
            treatmentExternalData.put("itemQty", treatmentExternal.getItemQty());
            treatmentExternalData.put("dosage", treatmentExternal.getDosage());
            treatmentExternalData.put("timing", mapMedicineTiming(treatmentExternal.getMedicineTiming()));
            treatmentExternalData.put("dosageCategory", mapRouteOfAdministration(treatmentExternal.getRouteOfAdministration()));
            treatmentExternalData.put("followupId", treatmentExternal.getFollowupId());
            treatmentExternalData.put("modifiedBy", treatmentExternal.getModifiedBy());
            treatmentExternalData.put("lastModified", treatmentExternal.getLastModified());
            externalTreatments.add(treatmentExternalData);
        }

        response.put("treatments", internalTreatments);
        response.put("treatmentExternals", externalTreatments);

        return new ResponseEntity<>(response, HttpStatus.OK);
    }

    private Map<String, Object> mapItem(Item item) {
        Map<String, Object> itemMap = new LinkedHashMap<>();
        if (item != null) {
            itemMap.put("id", item.getId());
            itemMap.put("label", item.getItemName());
        } else {
            itemMap.put("id", null);
            itemMap.put("label", " ");
        }
        return itemMap;
    }

    private Map<String, Object> mapMedicineFrequency(MedicineFrequency frequency) {
        Map<String, Object> frequencyMap = new LinkedHashMap<>();
        if (frequency != null) {
            frequencyMap.put("id", frequency.getId());
            frequencyMap.put("label", frequency.getMedicineFrequency());
        } else {
            frequencyMap.put("id", null);
            frequencyMap.put("label", " ");
        }
        return frequencyMap;
    }

    private Map<String, Object> mapMedicineTiming(MedicineTiming timing) {
        Map<String, Object> timingMap = new LinkedHashMap<>();
        if (timing != null) {
            timingMap.put("id", timing.getId());
            timingMap.put("label", timing.getMedicineTiming());
        } else {
            timingMap.put("id", null);
            timingMap.put("label", " ");
        }
        return timingMap;
    }

    private Map<String, Object> mapRouteOfAdministration(RouteOfAdministration route) {
        Map<String, Object> routeMap = new LinkedHashMap<>();
        if (route != null) {
            routeMap.put("id", route.getId());
            routeMap.put("label", route.getDosageCategory());
        } else {
            routeMap.put("id", null);
            routeMap.put("label", " ");
        }
        return routeMap;
    }


    @GetMapping
    public ResponseEntity<?> getAllTreatments(@RequestParam(required = false) Integer page,
                                              @RequestParam(required = false) Integer size,
                                              @RequestParam(required = false) String sortBy,
                                              @RequestParam(required = false) String sortOrder) {
        Pageable pageable = PaginationUtil.getPageableWithDefaults(page, size, sortBy, sortOrder);
        Page<Treatment> treatmentPage = treatmentServiceImpl.getAllTreatments(pageable);
        Page<TreatmentExternal> treatmentExternalPage = treatmentServiceImpl.getAllTreatmentExternals(pageable);

        Map<Long, Map<String, List<Map<String, Object>>>> combinedTreatmentsMap = new LinkedHashMap<>();

        for (Treatment treatment : treatmentPage.getContent()) {
            Long appointmentId = treatment.getEmployeeAppointment() != null ? treatment.getEmployeeAppointment().getId() : null;

            if (appointmentId != null) {
                combinedTreatmentsMap
                        .computeIfAbsent(appointmentId, k -> new LinkedHashMap<>())
                        .computeIfAbsent("Internal", k -> new ArrayList<>())
                        .add(createInternalTreatmentMap(treatment));
            }
        }

        for (TreatmentExternal treatmentExternal : treatmentExternalPage.getContent()) {
            Long appointmentId = treatmentExternal.getEmployeeAppointment() != null ? treatmentExternal.getEmployeeAppointment().getId() : null;

            if (appointmentId != null) {
                combinedTreatmentsMap
                        .computeIfAbsent(appointmentId, k -> new LinkedHashMap<>())
                        .computeIfAbsent("External", k -> new ArrayList<>())
                        .add(createExternalTreatmentMap(treatmentExternal));
            }
        }

        Map<String, Object> response = new LinkedHashMap<>();
        response.put("combinedTreatments", combinedTreatmentsMap);

        return new ResponseEntity<>(response, HttpStatus.OK);
    }

    private Map<String, Object> createInternalTreatmentMap(Treatment treatment) {
        Map<String, Object> treatmentData = new LinkedHashMap<>();
        treatmentData.put("id", treatment.getId());
        treatmentData.put("appointmentId", treatment.getEmployeeAppointment() != null ? treatment.getEmployeeAppointment().getId() : null);
        treatmentData.put("item", mapItem(treatment.getItem()));
        treatmentData.put("frequency", mapMedicineFrequency(treatment.getMedicineFrequency()));
        treatmentData.put("timing", mapMedicineTiming(treatment.getMedicineTiming()));
        treatmentData.put("dosageCategory", mapRouteOfAdministration(treatment.getRouteOfAdministration()));
        treatmentData.put("forDays", treatment.getForDays());
        treatmentData.put("dosage", treatment.getDosage());
        treatmentData.put("itemQty", treatment.getItemQty());
        treatmentData.put("itemBatchNo", treatment.getItemBatchNo());
        treatmentData.put("issuedQty", treatment.getIssuedQty());
        treatmentData.put("issueBy", treatment.getIssueBy());
        treatmentData.put("isDisplay", treatment.getIsDisplay());
        treatmentData.put("groupItemId", treatment.getGroupItemId());
        treatmentData.put("followupId", treatment.getFollowupId());
        treatmentData.put("modifiedBy", treatment.getModifiedBy());
        treatmentData.put("lastModified", treatment.getLastModified());
        return treatmentData;
    }

    private Map<String, Object> createExternalTreatmentMap(TreatmentExternal treatmentExternal) {
        Map<String, Object> treatmentExternalData = new LinkedHashMap<>();
        treatmentExternalData.put("id", treatmentExternal.getId());
        treatmentExternalData.put("appointmentId", treatmentExternal.getEmployeeAppointment() != null ? treatmentExternal.getEmployeeAppointment().getId() : null);
        treatmentExternalData.put("itemName", treatmentExternal.getItemName());
        treatmentExternalData.put("frequency", treatmentExternal.getFrequency());
        treatmentExternalData.put("forDays", treatmentExternal.getForDays());
        treatmentExternalData.put("itemQty", treatmentExternal.getItemQty());
        treatmentExternalData.put("dosage", treatmentExternal.getDosage());
        treatmentExternalData.put("timing", mapMedicineTiming(treatmentExternal.getMedicineTiming()));
        treatmentExternalData.put("dosageCategory", mapRouteOfAdministration(treatmentExternal.getRouteOfAdministration()));
        treatmentExternalData.put("followupId", treatmentExternal.getFollowupId());
        treatmentExternalData.put("modifiedBy", treatmentExternal.getModifiedBy());
        treatmentExternalData.put("lastModified", treatmentExternal.getLastModified());
        return treatmentExternalData;
    }

    @PostMapping
    public ResponseEntity<?> addTreatment(@Valid @RequestBody TreatmentInternalExternalDto treatmentInternalExternalDto) {
        Long userId = authServiceImpl.getCurrentUserId();
        treatmentServiceImpl.addTreatmentOrExternal(treatmentInternalExternalDto, userId);
        return new ResponseEntity<>(HttpStatus.CREATED);
    }

    @PutMapping("/{appointmentId}")
    public ResponseEntity<?> updateTreatment(@Valid @RequestBody TreatmentInternalExternalDto treatmentInternalExternalDto) {
        Long userId = authServiceImpl.getCurrentUserId();
        treatmentServiceImpl.updateTreatmentOrExternal(treatmentInternalExternalDto, userId);
        return new ResponseEntity<>(HttpStatus.OK);
    }

}