package com.gnx.telemedicine.service;

import com.gnx.telemedicine.model.Appointment;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.format.DateTimeFormatter;

@Service
@RequiredArgsConstructor
@Slf4j
public class EmailNotificationService {

    private final JavaMailSender mailSender;

    @Async
    public void sendAppointmentConfirmation(Appointment appointment) {
        try {
            // Email to patient
            sendEmail(
                    appointment.getPatient().getUser().getEmail(),
                    "Appointment Confirmation",
                    buildPatientConfirmationMessage(appointment)
            );

            // Email to doctor
            sendEmail(
                    appointment.getDoctor().getUser().getEmail(),
                    "New Appointment Scheduled",
                    buildDoctorNotificationMessage(appointment)
            );

            log.info("Appointment confirmation emails sent for appointment: {}", appointment.getId());
        } catch (Exception e) {
            log.error("Failed to send appointment confirmation emails", e);
        }
    }

    @Async
    public void sendAppointmentCancellation(Appointment appointment) {
        try {
            sendEmail(
                    appointment.getPatient().getUser().getEmail(),
                    "Appointment Cancelled",
                    buildCancellationMessage(appointment)
            );

            sendEmail(
                    appointment.getDoctor().getUser().getEmail(),
                    "Appointment Cancelled",
                    buildCancellationMessage(appointment)
            );

            log.info("Appointment cancellation emails sent for appointment: {}", appointment.getId());
        } catch (Exception e) {
            log.error("Failed to send cancellation emails", e);
        }
    }

    @Async
    public void sendAppointmentConfirmed(Appointment appointment) {
        try {
            // Email to patient
            sendEmail(
                    appointment.getPatient().getUser().getEmail(),
                    "Appointment Confirmed",
                    buildPatientConfirmedMessage(appointment)
            );

            // Email to doctor
            sendEmail(
                    appointment.getDoctor().getUser().getEmail(),
                    "Appointment Confirmed",
                    buildDoctorConfirmedMessage(appointment)
            );

            log.info("Appointment confirmed emails sent for appointment: {}", appointment.getId());
        } catch (Exception e) {
            log.error("Failed to send confirmed emails", e);
        }
    }

    @Async
    public void sendAppointmentCompleted(Appointment appointment) {
        try {
            // Email to patient
            sendEmail(
                    appointment.getPatient().getUser().getEmail(),
                    "Appointment Completed",
                    buildPatientCompletedMessage(appointment)
            );

            // Email to doctor
            sendEmail(
                    appointment.getDoctor().getUser().getEmail(),
                    "Appointment Completed",
                    buildDoctorCompletedMessage(appointment)
            );

            log.info("Appointment completed emails sent for appointment: {}", appointment.getId());
        } catch (Exception e) {
            log.error("Failed to send completed emails", e);
        }
    }

    public void sendEmail(String to, String subject, String text) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setTo(to);
        message.setSubject(subject);
        message.setText(text);
        message.setFrom("support@gnxsoft.com");

        mailSender.send(message);
    }

    private String buildPatientConfirmationMessage(Appointment appointment) {
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MMMM dd, yyyy");
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("hh:mm a");

        return String.format("""
            Dear %s %s,
            
            Your appointment has been confirmed!
            
            Doctor: Dr. %s %s
            Specialization: %s
            Date: %s
            Time: %s
            Duration: %d minutes
            
            Please arrive 10 minutes early for check-in.
            
            If you need to cancel or reschedule, please contact us at least 24 hours in advance.
            
            Best regards,
            GNX Soft LTD
            """,
                appointment.getPatient().getUser().getFirstName(),
                appointment.getPatient().getUser().getLastName(),
                appointment.getDoctor().getUser().getFirstName(),
                appointment.getDoctor().getUser().getLastName(),
                appointment.getDoctor().getSpecialization(),
                appointment.getScheduledDate().format(dateFormatter),
                appointment.getScheduledTime().format(timeFormatter),
                appointment.getDurationMinutes()
        );
    }

    private String buildDoctorNotificationMessage(Appointment appointment) {
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MMMM dd, yyyy");
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("hh:mm a");

        return String.format("""
            Dear Dr. %s %s,
            
            A new appointment has been scheduled.
            
            Patient: %s %s
            Date: %s
            Time: %s
            Duration: %d minutes
            
            Please review your schedule accordingly.
            
            Best regards,
            GNX Soft LTD
            """,
                appointment.getDoctor().getUser().getFirstName(),
                appointment.getDoctor().getUser().getLastName(),
                appointment.getPatient().getUser().getFirstName(),
                appointment.getPatient().getUser().getLastName(),
                appointment.getScheduledDate().format(dateFormatter),
                appointment.getScheduledTime().format(timeFormatter),
                appointment.getDurationMinutes()
        );
    }

    private String buildCancellationMessage(Appointment appointment) {
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MMMM dd, yyyy");
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("hh:mm a");

        return String.format("""
            Dear User,
            
            The following appointment has been cancelled:
            
            Date: %s
            Time: %s
            
            If you have any questions, please contact support.
            
            Best regards,
            GNX Soft LTD
            """,
                appointment.getScheduledDate().format(dateFormatter),
                appointment.getScheduledTime().format(timeFormatter)
        );
    }

    private String buildPatientConfirmedMessage(Appointment appointment) {
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MMMM dd, yyyy");
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("hh:mm a");

        return String.format("""
            Dear %s %s,
            
            Your appointment has been confirmed!
            
            Doctor: Dr. %s %s
            Specialization: %s
            Date: %s
            Time: %s
            Duration: %d minutes
            
            Your appointment is now confirmed. Please prepare for your consultation and arrive on time.
            
            If you need to cancel or reschedule, please contact us at least 24 hours in advance.
            
            Best regards,
            GNX Soft LTD
            """,
                appointment.getPatient().getUser().getFirstName(),
                appointment.getPatient().getUser().getLastName(),
                appointment.getDoctor().getUser().getFirstName(),
                appointment.getDoctor().getUser().getLastName(),
                appointment.getDoctor().getSpecialization(),
                appointment.getScheduledDate().format(dateFormatter),
                appointment.getScheduledTime().format(timeFormatter),
                appointment.getDurationMinutes()
        );
    }

    private String buildDoctorConfirmedMessage(Appointment appointment) {
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MMMM dd, yyyy");
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("hh:mm a");

        return String.format("""
            Dear Dr. %s %s,
            
            An appointment has been confirmed.
            
            Patient: %s %s
            Date: %s
            Time: %s
            Duration: %d minutes
            
            Please ensure you are prepared for this consultation.
            
            Best regards,
            GNX Soft LTD
            """,
                appointment.getDoctor().getUser().getFirstName(),
                appointment.getDoctor().getUser().getLastName(),
                appointment.getPatient().getUser().getFirstName(),
                appointment.getPatient().getUser().getLastName(),
                appointment.getScheduledDate().format(dateFormatter),
                appointment.getScheduledTime().format(timeFormatter),
                appointment.getDurationMinutes()
        );
    }

    private String buildPatientCompletedMessage(Appointment appointment) {
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MMMM dd, yyyy");
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("hh:mm a");

        return String.format("""
            Dear %s %s,
            
            Your appointment has been marked as completed.
            
            Doctor: Dr. %s %s
            Specialization: %s
            Date: %s
            Time: %s
            
            Thank you for using our telemedicine platform. We hope your consultation was helpful.
            
            If you have any follow-up questions or need to schedule another appointment, please don't hesitate to contact us.
            
            Best regards,
            GNX Soft LTD
            """,
                appointment.getPatient().getUser().getFirstName(),
                appointment.getPatient().getUser().getLastName(),
                appointment.getDoctor().getUser().getFirstName(),
                appointment.getDoctor().getUser().getLastName(),
                appointment.getDoctor().getSpecialization(),
                appointment.getScheduledDate().format(dateFormatter),
                appointment.getScheduledTime().format(timeFormatter)
        );
    }

    private String buildDoctorCompletedMessage(Appointment appointment) {
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MMMM dd, yyyy");
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("hh:mm a");

        return String.format("""
            Dear Dr. %s %s,
            
            The following appointment has been marked as completed.
            
            Patient: %s %s
            Date: %s
            Time: %s
            
            Thank you for your service. Please ensure all documentation and notes are complete.
            
            Best regards,
            GNX Soft LTD
            """,
                appointment.getDoctor().getUser().getFirstName(),
                appointment.getDoctor().getUser().getLastName(),
                appointment.getPatient().getUser().getFirstName(),
                appointment.getPatient().getUser().getLastName(),
                appointment.getScheduledDate().format(dateFormatter),
                appointment.getScheduledTime().format(timeFormatter)
        );
    }

    @Async
    public void sendDataSubjectRequestCompletionEmail(String to, String requestType) {
        try {
            sendEmail(
                    to,
                    "Data Subject Request Completed",
                    buildDataSubjectRequestCompletionMessage(requestType)
            );
            log.info("Data subject request completion email sent to: {}", to);
        } catch (Exception e) {
            log.error("Failed to send data subject request completion email", e);
        }
    }

    @Async
    public void sendDataPortabilityEmail(String to, java.util.Map<String, Object> data) {
        try {
            // In production, you would attach the data as a JSON file
            sendEmail(
                    to,
                    "Your Data Export - GDPR Data Portability",
                    buildDataPortabilityMessage(data)
            );
            log.info("Data portability email sent to: {}", to);
        } catch (Exception e) {
            log.error("Failed to send data portability email", e);
        }
    }

    private String buildDataSubjectRequestCompletionMessage(String requestType) {
        return String.format("""
            Dear User,
            
            Your data subject request (%s) has been completed.
            
            You can access your data through the platform or download it from the link provided in your account.
            
            If you have any questions or concerns, please contact our support team.
            
            Best regards,
            GNX Soft LTD - Privacy Team
            """, requestType);
    }

    private String buildDataPortabilityMessage(java.util.Map<String, Object> data) {
        return """
            Dear User,
            
            Your data export is ready for download.
            
            This export contains all your personal data stored in our system, including:
            - User profile information
            - Patient records (if applicable)
            - Appointments
            - Medical records
            - Prescriptions
            
            You can download your data from your account dashboard.
            
            The data is provided in JSON format, which is machine-readable and portable.
            
            If you have any questions about your data export, please contact our support team.
            
            Best regards,
            GNX Soft LTD - Privacy Team
            """;
    }

    @Async
    public void sendPasswordResetEmail(String to, String resetToken, String firstName) {
        try {
            sendEmail(
                    to,
                    "Password Reset Request",
                    buildPasswordResetMessage(firstName, resetToken)
            );
            log.info("Password reset email sent to: {}", to);
        } catch (Exception e) {
            log.error("Failed to send password reset email", e);
        }
    }

    private String buildPasswordResetMessage(String firstName, String resetToken) {
        // In production, this would be a proper URL to your frontend reset password page
        String resetUrl = "http://localhost:4200/reset-password?token=" + resetToken;
        
        return String.format("""
            Dear %s,
            
            We received a request to reset your password for your telemedicine account.
            
            To reset your password, please click on the following link:
            %s
            
            This link will expire in 1 hour for security reasons.
            
            If you did not request a password reset, please ignore this email. Your password will remain unchanged.
            
            For security reasons, never share this link with anyone.
            
            If you have any questions or concerns, please contact our support team at support@gnxsoft.com.
            
            Best regards,
            GNX Soft LTD - Security Team
            """, firstName != null ? firstName : "User", resetUrl);
    }
}