//
//  ContactManager.swift
//  Padel Tournament
//
//  Created by Razmig Sarkissian on 19/09/2023.
//

import Foundation
import SwiftUI
import MessageUI
import LeStorage

enum ContactManagerError: LocalizedError {
    case mailFailed
    case mailNotSent //no network no error
    case messageFailed
    case messageNotSent //no network no error
}

enum ContactType: Identifiable {
    case mail(date: Date?, recipients: [String]?, bccRecipients: [String]?, body: String?, subject: String?, tournamentBuild: TournamentBuild?)
    case message(date: Date?, recipients: [String]?, body: String?, tournamentBuild: TournamentBuild?)
    
    var id: Int {
        switch self {
        case .message: return 0
        case .mail: return 1
        }
    }
}

extension ContactType {
    static let defaultCustomMessage: String = "Il est conseillé de vous présenter 10 minutes avant de jouer.\nMerci de me confirmer votre présence avec votre nom et de prévenir votre partenaire."
    static let defaultAvailablePaymentMethods: String = "Règlement possible par chèque ou espèces."

    static func callingCustomMessage(source: String? = nil, tournament: Tournament?, startDate: Date?, roundLabel: String) -> String {
        let tournamentCustomMessage = source ?? DataStore.shared.user.summonsMessageBody ?? defaultCustomMessage
        let clubName = tournament?.clubName ?? ""

        var text = tournamentCustomMessage
        let date = startDate ?? tournament?.startDate ?? Date()

        if let tournament {
            text = text.replacingOccurrences(of: "#titre", with: tournament.tournamentTitle(.short))
            text = text.replacingOccurrences(of: "#prix", with: tournament.entryFeeMessage)
        }
        
        text = text.replacingOccurrences(of: "#club", with: clubName)
        text = text.replacingOccurrences(of: "#manche", with: roundLabel.lowercased())
        text = text.replacingOccurrences(of: "#jour", with: "\(date.formatted(Date.FormatStyle().weekday(.wide).day().month(.wide)))")
        text = text.replacingOccurrences(of: "#horaire", with: "\(date.formatted(Date.FormatStyle().hour().minute()))")
        
        let signature = DataStore.shared.user.summonsMessageSignature ?? DataStore.shared.user.defaultSignature()

        text = text.replacingOccurrences(of: "#signature", with: signature)
        return text
    }
    
    static func callingMessage(tournament: Tournament?, startDate: Date?, roundLabel: String, matchFormat: MatchFormat?, reSummon: Bool = false) -> String {
        
        let useFullCustomMessage = DataStore.shared.user.summonsUseFullCustomMessage

        if useFullCustomMessage {
            return callingCustomMessage(tournament: tournament, startDate: startDate, roundLabel: roundLabel)
        }

        let date = startDate ?? tournament?.startDate ?? Date()

        let clubName = tournament?.clubName ?? ""
        let message = DataStore.shared.user.summonsMessageBody ?? defaultCustomMessage
        let signature = DataStore.shared.user.summonsMessageSignature ?? DataStore.shared.user.defaultSignature()

        let localizedCalled = "convoqué" + (tournament?.tournamentCategory == .women ? "e" : "") + "s"
                
        var entryFeeMessage: String? {
            (DataStore.shared.user.summonsDisplayEntryFee) ? tournament?.entryFeeMessage : nil
        }
        
        var computedMessage: String {
            [entryFeeMessage, message].compacted().map { $0.trimmed }.joined(separator: "\n\n")
        }
        
        let intro = reSummon ? "Suite à des forfaits, vous êtes finalement" : "Vous êtes"

        if let tournament {
            return "Bonjour,\n\n\(intro) \(localizedCalled) pour jouer en  \(roundLabel.lowercased()) du \(tournament.tournamentTitle(.short)) au \(clubName) le \(date.formatted(Date.FormatStyle().weekday(.wide).day().month(.wide))) à \(date.formatted(Date.FormatStyle().hour().minute())).\n\n" + computedMessage + "\n\n\(signature)"
        } else {
            return "Bonjour,\n\n\(intro) \(localizedCalled) \(roundLabel) au \(clubName) le \(date.formatted(Date.FormatStyle().weekday(.wide).day().month(.wide))) à \(date.formatted(Date.FormatStyle().hour().minute())).\n\nMerci de confirmer en répondant à ce message et de prévenir votre partenaire !\n\n\(signature)"
        }
    }
}


struct MessageComposeView: UIViewControllerRepresentable {
    typealias Completion = (_ result: MessageComposeResult) -> Void

    static var canSendText: Bool { MFMessageComposeViewController.canSendText() }
        
    let recipients: [String]?
    let body: String?
    let completion: Completion?
    
    func makeUIViewController(context: Context) -> UIViewController {
        guard Self.canSendText else {
            let errorView = ContentUnavailableView("Aucun compte de messagerie", systemImage: "xmark", description: Text("Aucun compte de messagerie n'est configuré sur cet appareil."))
            return UIHostingController(rootView: errorView)
        }
        
        let controller = MFMessageComposeViewController()
        controller.messageComposeDelegate = context.coordinator
        controller.recipients = recipients
        controller.body = body
        
        return controller
    }
    
    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
    
    func makeCoordinator() -> Coordinator {
        Coordinator(completion: self.completion)
    }
    
    class Coordinator: NSObject, MFMessageComposeViewControllerDelegate {
        private let completion: Completion?

        public init(completion: Completion?) {
            self.completion = completion
        }
        
        public func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
            controller.dismiss(animated: true, completion: {
                self.completion?(result)
            })
        }
    }
}

struct MailComposeView: UIViewControllerRepresentable {
    typealias Completion = (_ result: MFMailComposeResult) -> Void

    static var canSendMail: Bool {
        if let mailURL = URL(string: "mailto:?to=jap@padelclub.com") {
            let mailConfigured = UIApplication.shared.canOpenURL(mailURL)
            return mailConfigured && MFMailComposeViewController.canSendMail()
        } else {
            return MFMailComposeViewController.canSendMail()
        }
    }
        
    let recipients: [String]?
    let bccRecipients: [String]?
    let body: String?
    let subject: String?
    var attachmentURL: URL?
    let completion: Completion?
    
    func makeUIViewController(context: Context) -> UIViewController {
        guard Self.canSendMail else {
            let errorView = ContentUnavailableView("Aucun compte mail", systemImage: "xmark", description: Text("Aucun compte mail n'est configuré sur cet appareil."))
            return UIHostingController(rootView: errorView)
        }
        
        let controller = MFMailComposeViewController()
        controller.mailComposeDelegate = context.coordinator
        controller.setToRecipients(recipients)
        controller.setBccRecipients(bccRecipients)
        if let attachmentURL {
            do {
                let attachmentData = try Data(contentsOf: attachmentURL)
                controller.addAttachmentData(attachmentData, mimeType: "application/zip", fileName: "backup.zip")
            } catch {
                print("Could not attach file: \(error)")
            }
        }
        
        if let body {
            controller.setMessageBody(body, isHTML: false)
        }
        if let subject {
            controller.setSubject(subject)
        }

        return controller
    }
    
    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
    
    func makeCoordinator() -> Coordinator {
        Coordinator(completion: self.completion)
    }
    
    class Coordinator: NSObject, MFMailComposeViewControllerDelegate {
        private let completion: Completion?

        public init(completion: Completion?) {
            self.completion = completion
        }
        
        public func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
            controller.dismiss(animated: true, completion: {
                self.completion?(result)
            })
        }
    }
}
