import Foundation
import Observation
import SwiftData

@Observable
@MainActor
final class ContactsStore: ContactTracking {
    private let modelContext: ModelContext
    private(set) var contacts: [Contact] = []
    var searchQuery: String = ""

    init(modelContext: ModelContext) {
        self.modelContext = modelContext
        fetchContacts()
    }

    func fetchContacts() {
        let descriptor = FetchDescriptor<Contact>(
            sortBy: [SortDescriptor(\.lastSharedDate, order: .reverse)]
        )
        do {
            contacts = try modelContext.fetch(descriptor)
        } catch {
            contacts = []
        }
    }

    var visibleContacts: [Contact] {
        let trimmedQuery = searchQuery.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !trimmedQuery.isEmpty else { return contacts }
        return contacts.filter { contact in
            contact.name.localizedStandardContains(trimmedQuery)
            || contact.company.localizedStandardContains(trimmedQuery)
            || contact.role.localizedStandardContains(trimmedQuery)
            || contact.tags.localizedStandardContains(trimmedQuery)
            || contact.notes.localizedStandardContains(trimmedQuery)
        }
    }
    
    /// Contacts with overdue follow-ups
    var overdueFollowUps: [Contact] {
        contacts.filter { $0.isFollowUpOverdue }
    }
    
    /// Contacts that were received (scanned from others)
    var receivedCards: [Contact] {
        contacts.filter { $0.isReceivedCard }
    }

    func recordShare(for name: String, role: String, company: String, cardLabel: String) {
        // Check if contact already exists
        if let existingContact = contacts.first(where: { $0.name == name && $0.company == company }) {
            existingContact.lastSharedDate = .now
            existingContact.cardLabel = cardLabel
        } else {
            let newContact = Contact(
                name: name,
                role: role,
                company: company,
                avatarSystemName: "person.crop.circle",
                lastSharedDate: .now,
                cardLabel: cardLabel
            )
            modelContext.insert(newContact)
        }
        saveContext()
        fetchContacts()
    }
    
    /// Adds a contact from a received vCard (scanned QR code)
    func addReceivedCard(vCardData: String) {
        let contact = Contact.fromVCard(vCardData)
        modelContext.insert(contact)
        saveContext()
        fetchContacts()
    }
    
    /// Creates a new contact manually
    func createContact(
        name: String,
        role: String = "",
        company: String = "",
        email: String = "",
        phone: String = "",
        notes: String = "",
        tags: String = "",
        followUpDate: Date? = nil,
        contactFields: [ContactField] = [],
        photoData: Data? = nil
    ) {
        let contact = Contact(
            name: name,
            role: role,
            company: company,
            cardLabel: "Manual",
            notes: notes,
            tags: tags,
            followUpDate: followUpDate,
            email: email,
            phone: phone,
            photoData: photoData
        )
        modelContext.insert(contact)
        
        // Add contact fields if provided
        if !contactFields.isEmpty {
            for field in contactFields {
                field.contact = contact
                modelContext.insert(field)
            }
            contact.contactFields = contactFields
        }
        
        saveContext()
        fetchContacts()
    }
    
    /// Updates a contact's notes
    func updateNotes(for contact: Contact, notes: String) {
        contact.notes = notes
        saveContext()
    }
    
    /// Updates a contact's tags
    func updateTags(for contact: Contact, tags: String) {
        contact.tags = tags
        saveContext()
    }
    
    /// Sets or clears a follow-up reminder
    func setFollowUp(for contact: Contact, date: Date?) {
        contact.followUpDate = date
        saveContext()
    }

    func deleteContact(_ contact: Contact) {
        modelContext.delete(contact)
        saveContext()
        fetchContacts()
    }

    func relativeShareDate(for contact: Contact) -> String {
        let formatter = RelativeDateTimeFormatter()
        formatter.unitsStyle = .short
        return formatter.localizedString(for: contact.lastSharedDate, relativeTo: .now)
    }

    private func saveContext() {
        do {
            try modelContext.save()
        } catch {
            // Handle error silently for now
        }
    }
}
