package encounter

import (
	"fmt"
	"time"

	"service/internal/interfaces/satusehat"
)

// MapRequestToFHIR mengubah EncounterRequest (DTO internal) menjadi objek Payload FHIR.
// Penggunaan FHIRPayload (.Set dan .Append) akan memudahkan penulisan dan maintenance JSON yang kompleks.
func MapRequestToFHIR(req EncounterRequest) satusehat.FHIRPayload {
	payload := satusehat.NewFHIRPayload("Encounter").
		Set("status", req.Status).
		Set("class", map[string]interface{}{
			"system":  "http://terminology.hl7.org/CodeSystem/v3-ActCode",
			"code":    req.Class,
			"display": getClassDisplay(req.Class),
		}).
		Set("subject", map[string]interface{}{
			"reference": "Patient/" + req.PatientID,
			"display":   req.PatientName,
		})

	if req.OrganizationID != "" {
		payload.Set("serviceProvider", map[string]interface{}{
			"reference": "Organization/" + req.OrganizationID,
		})

		if req.EncounterID != "" {
			payload.Append("identifier", map[string]interface{}{
				"system": "http://sys-ids.kemkes.go.id/encounter/" + req.OrganizationID,
				"value":  req.EncounterID,
			})
		}
	}

	if req.EpisodeOfCareID != "" {
		payload.Append("episodeOfCare", map[string]interface{}{
			"reference": "EpisodeOfCare/" + req.EpisodeOfCareID,
		})
	}

	if req.PractitionerID != "" {
		payload.Append("participant", map[string]interface{}{
			"type": []map[string]interface{}{
				{
					"coding": []map[string]interface{}{
						{
							"system":  "http://terminology.hl7.org/CodeSystem/v3-ParticipationType",
							"code":    "ATND",
							"display": "attender",
						},
					},
				},
			},
			"individual": map[string]interface{}{
				"reference": "Practitioner/" + req.PractitionerID,
				"display":   req.PractitionerName,
			},
		})
	}

	if req.LocationID != "" {
		payload.Append("location", map[string]interface{}{
			"location": map[string]interface{}{
				"reference": "Location/" + req.LocationID,
				"display":   req.LocationName,
			},
		})
	}

	period := map[string]interface{}{
		"start": req.PeriodStart.Format(time.RFC3339),
	}
	if req.PeriodEnd != nil {
		period["end"] = req.PeriodEnd.Format(time.RFC3339)
	}
	payload.Set("period", period)

	payload.Append("statusHistory", map[string]interface{}{
		"status": req.Status,
		"period": period,
	})

	return payload
}

// MapPendaftaranToRequest mengubah data database t_pendaftaran menjadi EncounterRequest
func MapPendaftaranToRequest(dbData PendaftaranDB, organizationID string, patientIHS string, practitionerIHS string) EncounterRequest {
	// Penentuan status encounter
	status := "arrived"
	if dbData.Batal.Valid && dbData.Batal.String == "Y" {
		status = "cancelled"
	} else if dbData.KeluarPoly.Valid {
		status = "finished"
	} else if dbData.MasukPoly.Valid {
		status = "in-progress"
	}

	// Waktu mulai
	periodStart := time.Now()
	if dbData.MasukPoly.Valid {
		periodStart = dbData.MasukPoly.Time
	} else if dbData.JamReg.Valid {
		periodStart = dbData.JamReg.Time
	}

	var periodEnd *time.Time
	if dbData.KeluarPoly.Valid {
		periodEnd = &dbData.KeluarPoly.Time
	}

	return EncounterRequest{
		EncounterID:      fmt.Sprintf("%d", dbData.IdxDaftar),
		OrganizationID:   organizationID,
		PatientID:        patientIHS,                     // Hasil pemetaan/pencarian IHS
		PatientName:      "Pasien " + dbData.NoMR.String, // Fallback Name
		PractitionerID:   practitionerIHS,                // Hasil pemetaan/pencarian IHS
		PractitionerName: dbData.DokterNameHFIS.String,
		LocationID:       fmt.Sprintf("%d", dbData.KdPoly.Int64), // Catatan: Anda harus me-mapping ini ke IHS Location ID
		LocationName:     dbData.PoliNameHFIS.String,
		Status:           status,
		Class:            "AMB", // Default: Rawat Jalan (Ambulatory)
		PeriodStart:      periodStart,
		PeriodEnd:        periodEnd,
	}
}

func getClassDisplay(code string) string {
	switch code {
	case "AMB":
		return "ambulatory"
	case "IMP":
		return "inpatient encounter"
	case "EMER":
		return "emergency"
	default:
		return "ambulatory"
	}
}
