hey, here is the code for my app with a few bugs. please revise the code, identify existing fixes to the bugs and issues im about to mention and create new fixes, as the current ones do not fix the issues. bugs:

the test recording button and start sleep recording do not work properly. when either is pressed, (or when the timer for actual sleep button before the recording ends) they immediately stop the recording if there is silence upon the button being pressed. if speech is detected while the recording starts, it transcribes it but doesnt end the transcription until the recording is stopped, which is not what i want. i need it to begin the recording even if it doesnt immediately start with a sound, and begin the transcription when each phrase starts and each phrase ends, but not ending the recording and only the transcription. i need it to create a new cell with the new phrase after a new phrase ends, the phrases being seperated by the detected silence. the recording should only be stopped once the stop recording button is pressed, and then the "good morning" message will show based on all of the phrases said in between the starting and stopping of the recording. also, once the recording is stopped, there is some weird behaviour involving blank cells appearing. the good morning message is also not right. when it slides down, the existing ui elements do not slide down and move out of the way to accomodate for it. they are static, and just go under the message and do not move out of the way. i need this to work, as well as no green background on the good morning message and the text must be black, not white. please evaluate and revise existing methods that attempt to fix these issues, and if you need to, create full blocks. make sure the revised/new blocks are written in their entirety, making it clear where they go in the code, as in the pre exisitng lines that go above/below the revisions/new blocks.

import UIKit
import AVFoundation
import Speech
import BackgroundTasks

struct SleepTalk: Codable {
    let id: UUID
    var phrase: String
    var interpretation: String?
    var audioURL: URL?
    var date: Date
}

class ViewController: UIViewController {
    
    // MARK: - Properties
    
    private var audioEngine: AVAudioEngine?
        private var audioRecorder: AVAudioRecorder?
        private var audioPlayer: AVAudioPlayer?
        private var speechRecognizer: SFSpeechRecognizer?
        private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?
        private var recognitionTask: SFSpeechRecognitionTask?
        private var sleepTalks: [SleepTalk] = [] {
            didSet {
                saveSleepTalks()
            }
        }
    
    private var goodMorningLabel: UILabel?
       private var goodMorningTimer: Timer?
    
    private var nightPhrases: [String] = []
    
    private let tableView = UITableView()
    private let startButton = UIButton(type: .system)
    private let stopButton = UIButton(type: .system)
    private let testButton = UIButton(type: .system)
    private let statusLabel = UILabel()
    private let dateLabel = UILabel()
    
    private var isTestRecording = false
    private var isSleepRecording = false
    private var currentPhraseID: UUID?
    private var backgroundTask: UIBackgroundTaskIdentifier = .invalid
    private var currentSession: [SleepTalk] = []
       private var silenceTimer: Timer?
    private let silenceThreshold: TimeInterval = 5.0
    private var summaryButton: UIButton!
    private var recordingCount = 0
    private var summary: String?

    // MARK: - Lifecycle Methods
    
    override func viewDidLoad() {
            super.viewDidLoad()
            setupUI()
            setupAudioSession()
            setupSpeechRecognizer()
            registerBackgroundTask()
            loadSleepTalks()
        }
        
        private func saveSleepTalks() {
            do {
                let encodedData = try JSONEncoder().encode(sleepTalks)
                UserDefaults.standard.set(encodedData, forKey: "sleepTalks")
            } catch {
                print("Error saving sleep talks: \(error)")
            }
        }
        
        private func loadSleepTalks() {
            if let savedData = UserDefaults.standard.data(forKey: "sleepTalks") {
                do {
                    sleepTalks = try JSONDecoder().decode([SleepTalk].self, from: savedData)
                    tableView.reloadData()
                } catch {
                    print("Error loading sleep talks: \(error)")
                }
            }
        }

    // MARK: - Setup Methods
    
    private func setupUI() {
           view.backgroundColor = .white
           setupButtons()
           setupStatusLabel()
           setupDateLabel()
           setupTableView()
           setupSummaryButton()
           layoutUI()
       }

  

       private func updateButtonColors() {
           // Update start button color
           startButton.backgroundColor = isSleepRecording ? .systemBlue : .systemGreen
           startButton.setTitleColor(.white, for: .normal)
           // Update stop button color
           stopButton.backgroundColor = .systemRed
           stopButton.setTitleColor(.white, for: .normal)
           // Update test button color
           testButton.backgroundColor = isTestRecording ? .systemGreen : .systemBlue
           testButton.setTitleColor(.white, for: .normal)
       
        // Ensure color is reset when leaving and returning to a cell
        testButton.addTarget(self, action: #selector(toggleTestRecording), for: .touchUpInside)
        startButton.addTarget(self, action: #selector(startSleepRecording), for: .touchUpInside)
        stopButton.addTarget(self, action: #selector(stopRecording), for: .touchUpInside)
    }


    private func setupStatusLabel() {
        statusLabel.text = "Ready to start"
        statusLabel.font = UIFont.systemFont(ofSize: 16, weight: .regular) // Adjusted font size for clarity
        statusLabel.textAlignment = .center
        statusLabel.textColor = UIColor.darkGray // Subtle color for status label
        statusLabel.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(statusLabel)
    }

    private func setupDateLabel() {
        dateLabel.text = getCurrentDate()
        dateLabel.font = UIFont.systemFont(ofSize: 16, weight: .regular) // Consistent font styling
        dateLabel.textAlignment = .center
        dateLabel.textColor = UIColor.darkGray
        dateLabel.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(dateLabel)
    }

    private func setupTableView() {
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.register(SleepTalkCell.self, forCellReuseIdentifier: "SleepTalkCell")
        tableView.dataSource = self
        tableView.delegate = self
        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = 100
        view.addSubview(tableView)
    }

    private func setupSummaryButton() {
        summaryButton = UIButton(type: .system)
        summaryButton.setTitle("View Summary", for: .normal)
        summaryButton.backgroundColor = .systemPurple
        summaryButton.setTitleColor(.white, for: .normal)
        summaryButton.titleLabel?.font = UIFont.systemFont(ofSize: 18, weight: .semibold) // Adjusted font
        summaryButton.layer.cornerRadius = 8 // Softer corners for consistency
        summaryButton.translatesAutoresizingMaskIntoConstraints = false
        summaryButton.addTarget(self, action: #selector(showSummary), for: .touchUpInside)
        view.addSubview(summaryButton)

        NSLayoutConstraint.activate([
            summaryButton.topAnchor.constraint(equalTo: dateLabel.bottomAnchor, constant: 20),
            summaryButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            summaryButton.widthAnchor.constraint(equalToConstant: 150),
            summaryButton.heightAnchor.constraint(equalToConstant: 50)
        ])
    }

    private func layoutUI() {
        NSLayoutConstraint.activate([
            // Start Button
            startButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
            startButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            startButton.widthAnchor.constraint(equalTo: stopButton.widthAnchor), // Match width of stop button
            startButton.heightAnchor.constraint(equalToConstant: 50),

            // Stop Button
            stopButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
            stopButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
            stopButton.widthAnchor.constraint(equalToConstant: 150),
            stopButton.heightAnchor.constraint(equalToConstant: 50),

            // Test Button
            testButton.topAnchor.constraint(equalTo: startButton.bottomAnchor, constant: 20),
            testButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            testButton.widthAnchor.constraint(equalToConstant: 200),
            testButton.heightAnchor.constraint(equalToConstant: 50),

            // Status Label
            statusLabel.topAnchor.constraint(equalTo: testButton.bottomAnchor, constant: 20),
            statusLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            statusLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
            statusLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),

            // Date Label
            dateLabel.topAnchor.constraint(equalTo: statusLabel.bottomAnchor, constant: 10),
            dateLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            dateLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
            dateLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),

            // Table View
            tableView.topAnchor.constraint(equalTo: summaryButton.bottomAnchor, constant: 20),
            tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
    }

    
    private func setupAudioSession() {
        do {
            try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [.mixWithOthers, .allowBluetooth, .defaultToSpeaker])
            try AVAudioSession.sharedInstance().setActive(true)
        } catch {
            print("Failed to set up audio session: \(error)")
        }
    }

    private func setupSpeechRecognizer() {
        speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))
        speechRecognizer?.delegate = self

        SFSpeechRecognizer.requestAuthorization { [weak self] authStatus in
            DispatchQueue.main.async {
                self?.updateUIForSpeechStatus(authStatus)
            }
        }
    }

    private func updateUIForSpeechStatus(_ status: SFSpeechRecognizerAuthorizationStatus) {
        switch status {
        case .authorized:
            statusLabel.text = "Speech recognition authorized"
            startButton.isEnabled = true
        case .denied:
            statusLabel.text = "Speech recognition authorization denied"
            startButton.isEnabled = false
        case .restricted:
            statusLabel.text = "Speech recognition restricted on this device"
            startButton.isEnabled = false
        case .notDetermined:
            statusLabel.text = "Speech recognition not yet authorized"
            startButton.isEnabled = false
        @unknown default:
            statusLabel.text = "Unknown authorization status"
            startButton.isEnabled = false
        }
    }

    // MARK: - Background Task Management
    
    func registerBackgroundTask() {
        BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.yourapp.sleeprecording", using: nil) { task in
            self.handleAppRefresh(task: task as! BGAppRefreshTask)
        }
    }

    func scheduleAppRefresh() {
        let request = BGAppRefreshTaskRequest(identifier: "com.yourapp.sleeprecording")
        request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) // Fetch no earlier than 15 minutes from now
        
        do {
            try BGTaskScheduler.shared.submit(request)
        } catch {
            print("Could not schedule app refresh: \(error)")
        }
    }

    func handleAppRefresh(task: BGAppRefreshTask) {
        scheduleAppRefresh()
        
        // Start recording in background
        startBackgroundRecording()
        
        task.setTaskCompleted(success: true)
        
        // Add an expiration handler for when the task times out
        task.expirationHandler = {
            // Call the method to stop the background recording if the task expires
            self.stopBackgroundRecording()
            task.setTaskCompleted(success: false)
        }
    }

    private func startBackgroundRecording() {
        if audioEngine == nil {
            startRecording(isTest: false)
        }
    }
    
    

    private func stopBackgroundRecording() {
        if audioEngine != nil {
            stopRecording()
        }
    }
    
    private func handleRecognitionResult(_ result: SFSpeechRecognitionResult?, error: Error?) {
        if let result = result {
            let transcribedText = result.bestTranscription.formattedString

            // Reset silence timer and update UI only if there is speech
            if !transcribedText.isEmpty {
                updateOrCreateSleepTalk(text: transcribedText) // Handle text update in UI
                resetSilenceTimer() // Restart silence detection
            }
        } else if let error = error {
            print("Recognition error: \(error.localizedDescription)")
            // Continue recording, but only stop transcription in case of errors
            recognitionRequest?.endAudio()
        }
    }

    // Set up the silence detection with a timer to manage transcription only
    private func resetSilenceTimer() {
        silenceTimer?.invalidate() // Reset any previous timers
        silenceTimer = Timer.scheduledTimer(withTimeInterval: silenceThreshold, repeats: false) { [weak self] _ in
            self?.endCurrentPhrase() // Stop transcription but NOT the recording
        }
    }

    // Handles ending the current transcription phrase when silence is detected
    private func endCurrentPhrase() {
        print("Ending current transcription phrase")

        if let currentPhrase = currentPhraseID {
            // Add the current phrase to the table (stopping only the transcription part)
            self.addToTable(currentPhrase: currentPhrase)
        }
        currentPhraseID = nil // Reset to allow new transcription
        
        // DO NOT stop the recording
        recognitionRequest?.endAudio() // End the transcription session
    }





    private func addToTable(currentPhrase: UUID) {
        let newPhrase = SleepTalk(id: currentPhrase, phrase: "", interpretation: nil, audioURL: nil, date: Date())
        sleepTalks.append(newPhrase)
        tableView.reloadData() // Add a new entry for each phrase
    }


    private func updateUIForRecordingState(isRecording: Bool, isTest: Bool) {
        startButton.isEnabled = !isRecording
        stopButton.isEnabled = isRecording
        isTestRecording = isTest && isRecording
        isSleepRecording = !isTest && isRecording
        statusLabel.text = isRecording ? (isTest ? "Test recording..." : "Recording sleep talk...") : "Recording stopped."
        currentPhraseID = isRecording ? nil : currentPhraseID
    }
    
   
    // Function to update and wrap the good morning message with a 53-character limit
    // The 53-character limit is only enforced in the updateGoodMorningMessage function
    private func updateGoodMorningMessage(with message: String) {
        let truncatedMessage = String(message.prefix(53)) // Limit to 53 characters

        goodMorningLabel?.removeFromSuperview() // Clear previous message
        goodMorningLabel = UILabel()
        goodMorningLabel?.text = truncatedMessage
        goodMorningLabel?.numberOfLines = 0
        goodMorningLabel?.lineBreakMode = .byWordWrapping
        goodMorningLabel?.frame = CGRect(x: 20, y: 50, width: view.frame.width - 40, height: 100)
        goodMorningLabel?.textAlignment = .center
        goodMorningLabel?.backgroundColor = .clear
        goodMorningLabel?.textColor = .black
        view.addSubview(goodMorningLabel!)
    }
    

    private func setupButtons() {
        [startButton, stopButton, testButton].forEach { button in
            button.layer.removeAllAnimations() // Remove any existing animations
            button.layer.cornerRadius = 8
            button.translatesAutoresizingMaskIntoConstraints = false
            button.titleLabel?.font = UIFont.systemFont(ofSize: 18, weight: .semibold)
            button.titleLabel?.numberOfLines = 2
            button.titleLabel?.textAlignment = .center
            view.addSubview(button)

            // Manually set static colors
            if button == startButton {
                button.backgroundColor = .systemGreen
            } else if button == stopButton {
                button.backgroundColor = .systemRed
            } else if button == testButton {
                button.backgroundColor = .systemBlue
            }
        }

        startButton.setTitle("Start Sleep Recording", for: .normal)
        startButton.setTitleColor(.white, for: .normal)

        stopButton.setTitle("Stop Recording", for: .normal)
        stopButton.setTitleColor(.white, for: .normal)

        testButton.setTitle("Test Recording", for: .normal)
        testButton.setTitleColor(.white, for: .normal)

        // Add targets for buttons
        startButton.addTarget(self, action: #selector(startSleepRecording), for: .touchUpInside)
        stopButton.addTarget(self, action: #selector(stopRecording), for: .touchUpInside)
        testButton.addTarget(self, action: #selector(toggleTestRecording), for: .touchUpInside)
    }




 
    @objc private func stopRecording() {
        print("Stop recording triggered")

        // Stop audio engine and transcription tasks
        audioEngine?.stop()
        audioEngine?.inputNode.removeTap(onBus: 0)
        recognitionRequest?.endAudio()
        audioRecorder?.stop()
        recognitionTask?.cancel()

        // Check for valid phrases to avoid adding empty cells
        if currentPhraseID != nil {
            endCurrentPhrase()
        }

        // Reset tasks
        recognitionTask = nil
        recognitionRequest = nil
        audioEngine = nil
        audioRecorder = nil
        silenceTimer?.invalidate()
        silenceTimer = nil

        // Update UI to reflect the stopped state
        updateUIForRecordingState(isRecording: false, isTest: isTestRecording)

        // Display the Good Morning message after recording
        if !nightPhrases.isEmpty {
            generateGoodMorningMessage(for: nightPhrases)
            DispatchQueue.main.async {
                self.showGoodMorningMessage("Good Morning!")
                self.adjustUIForGoodMorning()
            }
        }

        // Clear phrases after the session
        nightPhrases.removeAll()
    }




    private func animateGoodMorningMessage(with message: String) {
        // Remove any existing good morning label
        view.subviews.forEach { subview in
            if subview is UILabel && subview.tag == 999 {
                subview.removeFromSuperview()
            }
        }

        let goodMorningLabel = UILabel()
        goodMorningLabel.text = message
        goodMorningLabel.font = UIFont.boldSystemFont(ofSize: 24)
        goodMorningLabel.textAlignment = .center
        goodMorningLabel.textColor = .white
        goodMorningLabel.backgroundColor = UIColor(red: 0, green: 0.5, blue: 0.5, alpha: 0.8)
        goodMorningLabel.numberOfLines = 0
        goodMorningLabel.layer.cornerRadius = 10
        goodMorningLabel.clipsToBounds = true
        goodMorningLabel.translatesAutoresizingMaskIntoConstraints = false
        goodMorningLabel.alpha = 0.0
        goodMorningLabel.tag = 999 // Use this tag to identify the label later

        // Ensure it wraps text correctly within the screen bounds
        goodMorningLabel.setContentCompressionResistancePriority(.required, for: .vertical)
        goodMorningLabel.setContentHuggingPriority(.required, for: .vertical)

        view.addSubview(goodMorningLabel)

        NSLayoutConstraint.activate([
            goodMorningLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
            goodMorningLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            goodMorningLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20)
        ])

        UIView.animate(withDuration: 1.0, animations: {
            goodMorningLabel.alpha = 1.0
        }) { _ in
            // Set up a timer to remove the message after 10 seconds
            Timer.scheduledTimer(withTimeInterval: 10.0, repeats: false) { _ in
                UIView.animate(withDuration: 1.0, animations: {
                    goodMorningLabel.alpha = 0.0
                }) { _ in
                    goodMorningLabel.removeFromSuperview()
                }
            }
        }
    }
    
    

    
    // MARK: - Recording Methods
    
    private func showGoodMorningMessage(_ message: String) {
        // Remove any existing good morning label
        goodMorningLabel?.removeFromSuperview()

        // Create the new label with transparent background and black text
        goodMorningLabel = UILabel()
        goodMorningLabel?.text = message
        goodMorningLabel?.font = UIFont.boldSystemFont(ofSize: 24)
        goodMorningLabel?.textAlignment = .center
        goodMorningLabel?.numberOfLines = 0
        goodMorningLabel?.textColor = .black // Set text to black
        goodMorningLabel?.backgroundColor = .clear // Set background to transparent
        goodMorningLabel?.translatesAutoresizingMaskIntoConstraints = false

        // Add label to the view
        view.addSubview(goodMorningLabel!)

        // Add layout constraints to position the label
        NSLayoutConstraint.activate([
            goodMorningLabel!.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
            goodMorningLabel!.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            goodMorningLabel!.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20)
        ])

   
      

        // Animate the good morning message
        UIView.animate(withDuration: 1.0, animations: {
            self.goodMorningLabel?.alpha = 1.0
        }) { _ in
            // Set a timer to hide the message after a few seconds
            Timer.scheduledTimer(withTimeInterval: 10.0, repeats: false) { _ in
                UIView.animate(withDuration: 1.0, animations: {
                    self.goodMorningLabel?.alpha = 0.0
                }) { _ in
                    self.goodMorningLabel?.removeFromSuperview()
                }
            }
        }

        // Force UI refresh right after the label is added
        DispatchQueue.main.async {
            self.view.setNeedsLayout()
            self.view.layoutIfNeeded() // Forces the UI to adjust immediately
        }
    }
    
    private func adjustUIForGoodMorning() {
        // Slide the UI elements down without affecting their opacity
        UIView.animate(withDuration: 0.5) {
            // Adjust the y value as needed for how much you want the elements to slide down
            self.startButton.transform = CGAffineTransform(translationX: 0, y: 150)
            self.stopButton.transform = CGAffineTransform(translationX: 0, y: 150)
            self.testButton.transform = CGAffineTransform(translationX: 0, y: 150)
            self.summaryButton.transform = CGAffineTransform(translationX: 0, y: 150)

            // Apply layout changes after moving
            self.view.layoutIfNeeded()
        }

        // Clear previous label if it exists
        goodMorningLabel?.removeFromSuperview()

        // Create and configure the Good Morning label
        goodMorningLabel = UILabel()
        goodMorningLabel?.text = "Good Morning!"
        goodMorningLabel?.font = UIFont.boldSystemFont(ofSize: 24)
        goodMorningLabel?.textAlignment = .center
        goodMorningLabel?.textColor = .black // Ensure the text is black
        goodMorningLabel?.backgroundColor = .clear // Set background to transparent
        goodMorningLabel?.alpha = 0 // Start invisible before animation
        view.addSubview(goodMorningLabel!)

        // Position the label in the center of the screen
        goodMorningLabel?.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            goodMorningLabel!.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            goodMorningLabel!.centerYAnchor.constraint(equalTo: view.centerYAnchor)
        ])

        // Fade in the Good Morning label
        UIView.animate(withDuration: 0.5) {
            self.goodMorningLabel?.alpha = 1
        }
    }







    
    @objc private func startSleepRecording() {
        statusLabel.text = "Will start recording in 30 minutes..."
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) { // 30 minutes delay
            self.startRecording(isTest: false)
            self.scheduleAppRefresh()
        }
    }

    @objc private func toggleTestRecording() {
        if isTestRecording {
            stopRecording()
            testButton.setTitle("Test Recording", for: .normal)
        } else {
            // Only start the recording if it is not already running
            startRecording(isTest: true)
            testButton.setTitle("Stop Test", for: .normal)
        }
        // Toggle the test recording flag
        isTestRecording = !isTestRecording
    }

    private func startRecording(isTest: Bool) {
        print("Starting recording, isTest: \(isTest)")

        guard let speechRecognizer = speechRecognizer, speechRecognizer.isAvailable else {
            statusLabel.text = "Speech recognizer is unavailable"
            return
        }

        if audioEngine == nil {
            audioEngine = AVAudioEngine()
        }
        recognitionRequest = SFSpeechAudioBufferRecognitionRequest()

        let inputNode = audioEngine!.inputNode
        let recordingFormat = inputNode.outputFormat(forBus: 0)
        inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, when in
            self.recognitionRequest?.append(buffer)
        }

        do {
            try audioEngine!.start() // Start recording without transcription yet
        } catch {
            print("Audio engine couldn't start because of an error: \(error)")
            return
        }

        // Start recognition task but don't process phrases until speech is detected
        recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest!) { result, error in
            if let result = result {
                self.handleRecognitionResult(result, error: error)
            } else if let error = error {
                print("Recognition error: \(error)")
            }
        }

        // Ensure UI updates are done on the main thread
        DispatchQueue.main.async {
            self.updateUIForRecordingState(isRecording: true, isTest: isTest)
        }
    

        
        audioEngine = AVAudioEngine()
        guard let audioEngine = audioEngine else {
            statusLabel.text = "Failed to initialize audio engine"
            return
        }

        let audioFilename = getDocumentsDirectory().appendingPathComponent("\(Date().timeIntervalSince1970).m4a")

        let settings = [
            AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
            AVSampleRateKey: 44100,
            AVNumberOfChannelsKey: 2,
            AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
        ]

        do {
            audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings)
            audioRecorder?.delegate = self
            audioRecorder?.isMeteringEnabled = true
            audioRecorder?.record()

            recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
            guard let recognitionRequest = recognitionRequest else {
                statusLabel.text = "Unable to create speech recognition request"
                return
            }

            recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { [weak self] result, error in
                self?.handleRecognitionResult(result, error: error)
            }

            let inputNode = audioEngine.inputNode
            let recordingFormat = inputNode.outputFormat(forBus: 0)
            inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, when in
                recognitionRequest.append(buffer)
            }

            audioEngine.prepare()
            try audioEngine.start()

            // Timer to check silence by analyzing audio levels
            silenceTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] _ in
                self?.checkForSilence()  // Ensure silence is properly detected
            }

            print("Recording successfully started")  // Log after starting the recording
        } catch {
            print("Audio recording failed: \(error.localizedDescription)")
            statusLabel.text = "Audio recording failed"
        }
    }


    private func checkForSilence() {
        guard let audioRecorder = audioRecorder else { return }

        audioRecorder.updateMeters()
        let audioLevel = audioRecorder.averagePower(forChannel: 0)
        
        // Only trigger stop if silence is detected for the entire threshold period
        if audioLevel < -40 {  // Threshold for detecting silence (adjustable)
            print("Silence detected. Stopping recording.")
            silenceTimer?.invalidate()
            stopRecording()  // Stop recording after confirmed silence
        } else {
            print("Audio detected. Resetting silence timer.")  // Log when audio is still being detected
            resetSilenceTimer()  // Reset the timer if there is still audio
        }
    }


    
    
    private func endCurrentPhraseDueToSilence() {
        // End the current phrase and start a new one
        if let lastPhrase = currentSession.last?.phrase, !lastPhrase.isEmpty {
            print("Ending phrase due to silence: \(lastPhrase)")
            // Save or process the phrase
            // Optionally reset the recognitionRequest or start a new one
        }
    }

    private func handleSilence() {
        // Stop current recording
        stopRecording()

        // Process the current phrase if available
        if let currentID = currentPhraseID, let index = sleepTalks.firstIndex(where: { $0.id == currentID }) {
            let sleepTalk = sleepTalks[index]
            nightPhrases.append(sleepTalk.phrase)
        }
        
        // Create a new entry for the next phrase and start a new recording
        currentPhraseID = nil
        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
            self.startRecording(isTest: self.isTestRecording)
        }
    }



    // MARK: - LLM Integration
    
    private func updateOrCreateSleepTalk(text: String) {
            if let currentID = currentPhraseID, let index = sleepTalks.firstIndex(where: { $0.id == currentID }) {
                // Update existing phrase
                sleepTalks[index].phrase = text
            } else {
                // Create new phrase
                let newID = UUID()
                currentPhraseID = newID
                let audioURL = audioRecorder?.url // Save the audio URL
                let newSleepTalk = SleepTalk(id: newID, phrase: text, interpretation: nil, audioURL: audioURL, date: Date())
                sleepTalks.append(newSleepTalk)
            }
            
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }
        }
    
    func sendToLLM(text: String, id: UUID) {
        let apiUrl = URL(string: "https://openrouter.ai/api/v1/chat/completions")!
        
        var request = URLRequest(url: apiUrl)
        request.httpMethod = "POST"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("Bearer \(APIKeys.openRouterKey)", forHTTPHeaderField: "Authorization")
        request.addValue("Your-App-Name", forHTTPHeaderField: "HTTP-Referer")

        let prompt = """
        Analyze the following sleep talk phrase and provide two things:
        1. A brief interpretation of the sleep talk. This interpretation does not have to be under 53 characters.
        2. A witty 'Good Morning' message referencing the sleep talk. The message should be under 53 characters long (the brief interpretation of the singular sleep talk phrases can be any length though). When writing a good morning message, do not include anything other than the message, as if it was a text message. Do not include quotation marks either.

        Sleep talk: "\(text)"
        """

        let requestBody: [String: Any] = [
            "model": "openai/gpt-3.5-turbo",
            "messages": [
                ["role": "system", "content": "You are an AI assistant specialized in interpreting sleep talk and generating personalized good morning messages."],
                ["role": "user", "content": prompt]
            ]
        ]

        request.httpBody = try? JSONSerialization.data(withJSONObject: requestBody)

        let task = URLSession.shared.dataTask(with: request) { [weak self] (data, response, error) in
            DispatchQueue.main.async {
                if let error = error {
                    print("API request error: \(error)")
                    self?.updateInterpretation(for: id, with: "Error: Unable to analyze")
                    self?.animateGoodMorningMessage(with: "Good morning! Hope you had a restful night.")
                    return
                }

                guard let data = data else {
                    print("No data received from API")
                    self?.updateInterpretation(for: id, with: "Error: No data received")
                    self?.animateGoodMorningMessage(with: "Good morning! Hope you had a restful night.")
                    return
                }

                do {
                    if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
                       let choices = json["choices"] as? [[String: Any]],
                       let firstChoice = choices.first,
                       let message = firstChoice["message"] as? [String: Any],
                       let content = message["content"] as? String {

                        // Split the response into analysis and good morning message
                        let parts = content.split(separator: "\n", maxSplits: 1)
                        let interpretation = parts.first?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "No interpretation available."
                        let goodMorningMessage = parts.last?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "Good morning! Hope you had a restful night."

                        // Update UI with AI-generated results
                        self?.updateInterpretation(for: id, with: interpretation)
                        
                        // New code snippet: Animate the good morning message
                        self?.animateGoodMorningMessage(with: goodMorningMessage)
                    } else {
                        self?.updateInterpretation(for: id, with: "Error: Invalid response format")
                        self?.animateGoodMorningMessage(with: "Good morning! Hope you had a restful night.")
                    }
                } catch {
                    print("JSON parsing error: \(error)")
                    self?.updateInterpretation(for: id, with: "Error: Unable to parse response")
                    self?.animateGoodMorningMessage(with: "Good morning! Hope you had a restful night.")
                }
            }
        }

        task.resume()
    }
    
    
    private func generateGoodMorningMessage(for phrases: [String]) {
        let allPhrases = phrases.joined(separator: "\n")
        let prompt = """
        Based on the following sleep talk phrases from last night, generate a witty and engaging 'Good Morning' message. The message should be under 53 characters long and reference the overall theme or a standout phrase from the night's sleep talk.

        Sleep talk phrases:
        \(allPhrases)
        """

        let apiUrl = URL(string: "https://openrouter.ai/api/v1/chat/completions")!
        
        var request = URLRequest(url: apiUrl)
        request.httpMethod = "POST"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("Bearer \(APIKeys.openRouterKey)", forHTTPHeaderField: "Authorization")
        request.addValue("Your-App-Name", forHTTPHeaderField: "HTTP-Referer")

        let requestBody: [String: Any] = [
            "model": "openai/gpt-3.5-turbo",
            "messages": [
                ["role": "system", "content": "You are an AI assistant specialized in generating witty good morning messages based on sleep talk."],
                ["role": "user", "content": prompt]
            ]
        ]

        request.httpBody = try? JSONSerialization.data(withJSONObject: requestBody)

        let task = URLSession.shared.dataTask(with: request) { [weak self] (data, response, error) in
            DispatchQueue.main.async {
                if let error = error {
                    print("API request error: \(error)")
                    self?.animateGoodMorningMessage(with: "Good morning! Hope you had interesting dreams.")
                    return
                }

                guard let data = data else {
                    print("No data received from API")
                    self?.animateGoodMorningMessage(with: "Good morning! Your night was full of mysteries.")
                    return
                }

                do {
                    if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
                       let choices = json["choices"] as? [[String: Any]],
                       let firstChoice = choices.first,
                       let message = firstChoice["message"] as? [String: Any],
                       let content = message["content"] as? String {

                        let goodMorningMessage = content.trimmingCharacters(in: .whitespacesAndNewlines)
                        self?.animateGoodMorningMessage(with: goodMorningMessage)
                    } else {
                        self?.animateGoodMorningMessage(with: "Good morning! Your night was full of untold stories.")
                    }
                } catch {
                    print("JSON parsing error: \(error)")
                    self?.animateGoodMorningMessage(with: "Good morning! Your dreams were beyond words.")
                }
            }
        }

        task.resume()
    }

    private func updateInterpretation(for id: UUID, with interpretation: String) {
            if let index = sleepTalks.firstIndex(where: { $0.id == id }) {
                sleepTalks[index].interpretation = interpretation
                DispatchQueue.main.async {
                    self.tableView.reloadData()
                    // If DetailViewController is currently presented, update its interpretation label
                    if let detailVC = self.presentedViewController as? DetailViewController {
                        detailVC.updateInterpretation(id: id, interpretation: interpretation)
                    }
                }
            }
        }
    
    

    
    private func incrementRecordingCount() {
        recordingCount += 1
        if recordingCount % 15 == 0 {
            generateSummary()
        }
    }

    private func generateSummary() {
        let allPhrases = sleepTalks.map { $0.phrase }.joined(separator: "\n")
        let prompt = """
        Analyze the following sleep talk phrases and provide a summary:
        \(allPhrases)

        Please provide a summary that includes:
        1. Common themes or topics
        2. Overall emotional state or mood
        3. Any recurring patterns or unusual observations
        4. Potential insights into the speaker's subconscious thoughts
        5. Suggestions for improving sleep quality based on the sleep talk content
        """

        let apiUrl = URL(string: "https://openrouter.ai/api/v1/chat/completions")!
        var request = URLRequest(url: apiUrl)
        request.httpMethod = "POST"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("Bearer \(APIKeys.openRouterKey)", forHTTPHeaderField: "Authorization")
        request.addValue("Your-App-Name", forHTTPHeaderField: "HTTP-Referer")

        let requestBody: [String: Any] = [
            "model": "openai/gpt-3.5-turbo",
            "messages": [
                ["role": "system", "content": "You are an AI assistant specialized in analyzing sleep talk patterns."],
                ["role": "user", "content": prompt]
            ]
        ]

        request.httpBody = try? JSONSerialization.data(withJSONObject: requestBody)

        let task = URLSession.shared.dataTask(with: request) { [weak self] (data, response, error) in
            DispatchQueue.main.async {
                if let error = error {
                    print("API request error: \(error)")
                    self?.summary = "Error: Unable to generate summary"
                    return
                }

                guard let data = data else {
                    print("No data received from API")
                    self?.summary = "Error: No data received"
                    return
                }

                do {
                    if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
                       let choices = json["choices"] as? [[String: Any]],
                       let firstChoice = choices.first,
                       let message = firstChoice["message"] as? [String: Any],
                       let summaryText = message["content"] as? String {
                        self?.summary = summaryText
                    } else {
                        self?.summary = "Error: Invalid response format"
                    }
                } catch {
                    print("JSON parsing error: \(error)")
                    self?.summary = "Error: Unable to parse response"
                }
            }
        }

        task.resume()
    }

    func deleteSleepTalk(id: UUID) {
        if let index = sleepTalks.firstIndex(where: { $0.id == id }) {
            sleepTalks.remove(at: index)
            // Reload the table view to reflect the deletion
            tableView.reloadData()
        } else {
            print("Unable to delete: No sleep talk entry found with the given ID.")
        }
    }
    
    @objc private func showSummary() {
        let summaryVC = SummaryViewController(summary: summary ?? "No summary available yet.")
        let navController = UINavigationController(rootViewController: summaryVC)
        present(navController, animated: true, completion: nil)
    }
        // MARK: - Helper Methods
        
        private func getDocumentsDirectory() -> URL {
            FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        }
        
        private func getCurrentDate() -> String {
            let dateFormatter = DateFormatter()
            dateFormatter.dateStyle = .medium
            dateFormatter.timeStyle = .short
            return dateFormatter.string(from: Date())
        }
}

    // MARK: - UITableViewDataSource & UITableViewDelegate

extension ViewController: UITableViewDataSource, UITableViewDelegate {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return sleepTalks.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "SleepTalkCell", for: indexPath) as? SleepTalkCell else {
            fatalError("Unable to dequeue SleepTalkCell")
        }
        
        let sleepTalk = sleepTalks[indexPath.row]
        cell.configure(with: sleepTalk)
        cell.playButton.tag = indexPath.row
        cell.playButton.addTarget(self, action: #selector(playAudio), for: .touchUpInside)
        
        return cell
    }

        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            let sleepTalk = sleepTalks[indexPath.row]
            let detailVC = DetailViewController(sleepTalk: sleepTalk)
            let navController = UINavigationController(rootViewController: detailVC)
            present(navController, animated: true, completion: nil)
            tableView.deselectRow(at: indexPath, animated: true)
        }
        
        @objc func playAudio(sender: UIButton) {
            let index = sender.tag
            guard index >= 0 && index < sleepTalks.count else {
                print("Invalid index. Cannot find audio file.")
                return
            }
            
            if let audioURL = sleepTalks[index].audioURL {
                print("Attempting to play audio file at URL: \(audioURL)")
                if FileManager.default.fileExists(atPath: audioURL.path) {
                    do {
                        audioPlayer = try AVAudioPlayer(contentsOf: audioURL)
                        print("Audio player initialized with file: \(audioURL.lastPathComponent)")
                        audioPlayer?.play()
                        if let audioPlayer = audioPlayer, audioPlayer.isPlaying {
                            print("Audio playback started successfully.")
                        } else {
                            print("Audio playback failed to start.")
                        }
                    } catch {
                        print("Failed to play audio: \(error.localizedDescription)")
                    }
                } else {
                    print("Audio file does not exist at path: \(audioURL.path)")
                }
            } else {
                print("No audio file URL available for this entry.")
            }
        }
    }

    // MARK: - SFSpeechRecognizerDelegate



extension ViewController: SFSpeechRecognizerDelegate {
    func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) {
        startButton.isEnabled = available
        statusLabel.text = available ? "Speech recognizer is available" : "Speech recognizer is not available"
        if !available {
            print("Speech recognizer is currently unavailable.")
        }
    }

    func startSpeechRecognition(audioURL: URL) {
        if FileManager.default.fileExists(atPath: audioURL.path) {
            let recognitionRequest = SFSpeechURLRecognitionRequest(url: audioURL)
            speechRecognizer?.recognitionTask(with: recognitionRequest) { result, error in
                if let error = error {
                    print("Speech recognition failed: \(error.localizedDescription)")
                } else if let result = result {
                    print("Speech recognition result: \(result.bestTranscription.formattedString)")
                }
            }
        } else {
            print("Audio file does not exist at path: \(audioURL.path)")
        }
    }
}

    // MARK: - AVAudioRecorderDelegate

    extension ViewController: AVAudioRecorderDelegate {
        func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
            if !flag {
                stopRecording()
            }
        }
    }

    // MARK: - SleepTalkCell

class SleepTalkCell: UITableViewCell {
    private let phraseLabel = UILabel()
    private let dateLabel = UILabel()
    let playButton = UIButton(type: .system)
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupUI()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // Inside SleepTalkCell class
    private func setupUI() {
        [phraseLabel, dateLabel, playButton].forEach {
            contentView.addSubview($0)
            $0.translatesAutoresizingMaskIntoConstraints = false
        }
        
        phraseLabel.numberOfLines = 0
        
        playButton.setTitle("Play", for: .normal)
        playButton.setTitleColor(.white, for: .normal) // Set text color to white
        playButton.backgroundColor = .systemBlue // Initial color
        playButton.layer.cornerRadius = 10 // Rounded corners
        playButton.clipsToBounds = true // Ensure corner radius is applied
        
        NSLayoutConstraint.activate([
            phraseLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8),
            phraseLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
            phraseLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16),
            
            dateLabel.topAnchor.constraint(equalTo: phraseLabel.bottomAnchor, constant: 8),
            dateLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
            dateLabel.trailingAnchor.constraint(equalTo: playButton.leadingAnchor, constant: -8),
            dateLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8),
            
            playButton.centerYAnchor.constraint(equalTo: dateLabel.centerYAnchor),
            playButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16),
            playButton.widthAnchor.constraint(equalToConstant: 60)
        ])
        
      
    }

    func configure(with sleepTalk: SleepTalk) {
        phraseLabel.text = sleepTalk.phrase
        
        let dateFormatter = DateFormatter()
        dateFormatter.dateStyle = .medium
        dateFormatter.timeStyle = .short
        dateLabel.text = dateFormatter.string(from: sleepTalk.date)
        
        if let audioURL = sleepTalk.audioURL {
            if FileManager.default.fileExists(atPath: audioURL.path) {
                print("Audio file exists and is ready to be played.")
            } else {
                print("Audio file is missing at path: \(audioURL.path)")
            }
        } else {
            print("No audio file available for this entry.")
        }
    }
    
    private func startButtonColorFluctuation(for button: UIButton, baseColor: UIColor) {
        let animation = CAKeyframeAnimation(keyPath: "backgroundColor")
        animation.values = [
            baseColor.cgColor,
            baseColor.withAlphaComponent(0.8).cgColor,
            baseColor.withAlphaComponent(0.6).cgColor,
            baseColor.withAlphaComponent(0.8).cgColor,
            baseColor.cgColor
        ]
        animation.keyTimes = [0, 0.25, 0.5, 0.75, 1]
        animation.duration = 2.0
        animation.repeatCount = .infinity
        button.layer.add(animation, forKey: "backgroundColorAnimation")
    }
}
    // MARK: - DetailViewController

// MARK: - DetailViewController

class DetailViewController: UIViewController {
    var sleepTalk: SleepTalk
    
    private let phraseLabel = UILabel()
    private let interpretationLabel = UILabel()
    private let dateLabel = UILabel()
    private let playButton = UIButton(type: .system)
    private let deleteButton = UIButton(type: .system)
    private var audioPlayer: AVAudioPlayer?

    init(sleepTalk: SleepTalk) {
        self.sleepTalk = sleepTalk
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        setupUI()
        
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Close", style: .plain, target: self, action: #selector(dismissVC))
    }
    
    private func startHueFluctuation(for button: UIButton, baseColor: UIColor, hueColors: [UIColor]) {
        let smoothHueColors = hueColors + [hueColors.first!] // Ensure a complete cycle back to the start color

        // Create a CAKeyframeAnimation for the background color
        let animation = CAKeyframeAnimation(keyPath: "backgroundColor")
        animation.values = smoothHueColors.map { $0.cgColor }
        animation.keyTimes = Array(0..<smoothHueColors.count).map { NSNumber(value: Double($0) / Double(smoothHueColors.count - 1)) }
        
        animation.duration = 3.0 // Adjust for smoothness
        animation.repeatCount = .infinity
        button.layer.add(animation, forKey: "hueFluctuation")
    }

   

    
    // Inside DetailViewController class
    private func setupUI() {
        [phraseLabel, interpretationLabel, dateLabel, playButton, deleteButton].forEach {
            view.addSubview($0)
            $0.translatesAutoresizingMaskIntoConstraints = false
        }
        
        phraseLabel.text = "Phrase: \(sleepTalk.phrase)"
        phraseLabel.numberOfLines = 0

        updateInterpretationLabel()
        
        let dateFormatter = DateFormatter()
        dateFormatter.dateStyle = .medium
        dateFormatter.timeStyle = .short
        dateLabel.text = dateFormatter.string(from: sleepTalk.date)
        
        playButton.setTitle("Play Audio", for: .normal)
        playButton.setTitleColor(.white, for: .normal)
        playButton.backgroundColor = .systemBlue
        playButton.layer.cornerRadius = 10
        playButton.clipsToBounds = true
        playButton.addTarget(self, action: #selector(playButtonTapped), for: .touchUpInside)
        
        deleteButton.setTitle("Delete", for: .normal)
        deleteButton.setTitleColor(.white, for: .normal)
        deleteButton.backgroundColor = .systemRed
        deleteButton.layer.cornerRadius = 10
        deleteButton.clipsToBounds = true
        deleteButton.addTarget(self, action: #selector(deleteButtonTapped), for: .touchUpInside)
        
        NSLayoutConstraint.activate([
            phraseLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
            phraseLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            phraseLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),

            interpretationLabel.topAnchor.constraint(equalTo: phraseLabel.bottomAnchor, constant: 20),
            interpretationLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            interpretationLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),

            dateLabel.topAnchor.constraint(equalTo: interpretationLabel.bottomAnchor, constant: 20),
            dateLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            dateLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),

            playButton.topAnchor.constraint(equalTo: dateLabel.bottomAnchor, constant: 20),
            playButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            playButton.widthAnchor.constraint(equalToConstant: 100),
            playButton.heightAnchor.constraint(equalToConstant: 50),

            deleteButton.topAnchor.constraint(equalTo: playButton.bottomAnchor, constant: 20),
            deleteButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            deleteButton.widthAnchor.constraint(equalToConstant: 100),
            deleteButton.heightAnchor.constraint(equalToConstant: 50)
        ])
        
        startHueFluctuation(for: playButton, baseColor: .systemBlue, hueColors: [.systemBlue, .systemCyan, .systemTeal, .systemBlue])
        startHueFluctuation(for: deleteButton, baseColor: .systemRed, hueColors: [.systemRed, .systemPink, .systemOrange, .systemRed])
    }
    
    
    private func updateInterpretationLabel() {
        interpretationLabel.text = "Interpretation: \(sleepTalk.interpretation ?? "Analyzing...")"
        interpretationLabel.numberOfLines = 0
        
        if sleepTalk.interpretation == nil {
            if let viewController = presentingViewController as? ViewController {
                viewController.sendToLLM(text: sleepTalk.phrase, id: sleepTalk.id)
            }
        }
    }
    
    func updateInterpretation(id: UUID, interpretation: String) {
        if id == sleepTalk.id {
            sleepTalk.interpretation = interpretation
            updateInterpretationLabel()
        }
    }
    
    @objc private func dismissVC() {
        dismiss(animated: true, completion: nil)
    }
    
    @objc func playButtonTapped() {
        if let audioURL = sleepTalk.audioURL {
            print("Attempting to play audio from URL: \(audioURL)")
            
            if FileManager.default.fileExists(atPath: audioURL.path) {
                do {
                    try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
                    try AVAudioSession.sharedInstance().setActive(true)
                    
                    audioPlayer = try AVAudioPlayer(contentsOf: audioURL)
                    audioPlayer?.prepareToPlay()
                    audioPlayer?.play()
                    print("Audio playback started")
                } catch {
                    print("Failed to play audio: \(error.localizedDescription)")
                }
            } else {
                print("Audio file does not exist at path: \(audioURL.path)")
            }
        } else {
            print("No audio file available for this entry.")
        }
    }

    @objc func deleteButtonTapped() {
        let alert = UIAlertController(title: "Delete Phrase", message: "Are you sure you want to delete this phrase?", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
        alert.addAction(UIAlertAction(title: "Delete", style: .destructive, handler: { [weak self] _ in
            self?.deleteSleepTalk()
        }))
        present(alert, animated: true, completion: nil)
    }

    private func deleteSleepTalk() {
        if let viewController = presentingViewController as? ViewController {
            viewController.deleteSleepTalk(id: sleepTalk.id)
            dismiss(animated: true, completion: nil)
        }
    }

    private func startButtonColorFluctuation(for button: UIButton, baseColor: UIColor) {
        let animation = CAKeyframeAnimation(keyPath: "backgroundColor")
        animation.values = [
            baseColor.cgColor,
            baseColor.withAlphaComponent(0.8).cgColor,
            baseColor.withAlphaComponent(0.6).cgColor,
            baseColor.withAlphaComponent(0.8).cgColor,
            baseColor.cgColor
        ]
        animation.keyTimes = [0, 0.25, 0.5, 0.75, 1]
        animation.duration = 2.0
        animation.repeatCount = .infinity
        button.layer.add(animation, forKey: "backgroundColorAnimation")
    }
}
// MARK: - SummaryViewController

class SummaryViewController: UIViewController {
    private let summaryTextView = UITextView()
    private let summary: String

    init(summary: String) {
        self.summary = summary
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        setupUI()

        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Close", style: .plain, target: self, action: #selector(dismissVC))
    }

    private func setupUI() {
        view.addSubview(summaryTextView)
        summaryTextView.translatesAutoresizingMaskIntoConstraints = false
        summaryTextView.isEditable = false
        summaryTextView.font = UIFont.systemFont(ofSize: 16)
        summaryTextView.text = summary

        NSLayoutConstraint.activate([
            summaryTextView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
            summaryTextView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            summaryTextView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
            summaryTextView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20)
        ])
    }

    @objc private func dismissVC() {
        dismiss(animated: true, completion: nil)
    }
}