import Foundation

extension Content {

    func saveToDisk() throws {
        guard storage.contentScope != nil else {
            print("Storage not initialized, not saving content")
            return
        }

        var failedSaves = 0
        failedSaves += pages.count { !storage.save(pageMetadata: $0.pageFile, for: $0.id) }
        failedSaves += posts.count { !storage.save(post: $0.postFile, for: $0.id) }
        failedSaves += tags.count { !storage.save(tagMetadata: $0.file, for: $0.id) }
        failedSaves.increment(!storage.save(settings: settings.file))

        let fileDescriptions: [FileDescriptions] = files.sorted().compactMap { file in
            guard !file.english.isEmpty || !file.german.isEmpty else {
                return nil
            }
            return FileDescriptions(
                fileId: file.id,
                german: file.german.nonEmpty,
                english: file.english.nonEmpty)
        }

        failedSaves.increment(!storage.save(fileDescriptions: fileDescriptions))
        failedSaves.increment(!storage.save(tagOverview: tagOverview?.file))

        let externalFileList = files.filter { $0.isExternallyStored }.map { $0.id }
        failedSaves.increment(!storage.save(externalFileList: externalFileList))

        if failedSaves > 0 {
            print("Save partially failed with \(failedSaves) errors")
        }
    }

    func removeUnlinkedFiles() -> Bool {
        var success = true
        if !storage.deletePostFiles(notIn: posts.map { $0.id }) {
            success = false
        }
        if !storage.deletePageFiles(notIn: pages.map { $0.id }) {
            success = false
        }
        if !storage.deleteTagFiles(notIn: tags.map { $0.id }) {
            success = false
        }
        if !storage.deleteFileResources(notIn: files.map { $0.id }) {
            success = false
        }
        return success
    }
}

private extension Page {

    var pageFile: PageFile {
        .init(isDraft: isDraft,
              externalLink: externalLink,
              tags: tags.map { $0.id },
              hideDate: hideDate ? true : nil,
              createdDate: createdDate,
              startDate: startDate,
              endDate: hasEndDate ? endDate : nil,
              german: german.pageFile,
              english: english.pageFile,
              requiredFiles: requiredFiles.nonEmpty?.map { $0.id }.sorted())
    }
}

private extension LocalizedPage {

    var pageFile: LocalizedPageFile {
        .init(url: urlString,
              title: title,
              linkPreviewImage: linkPreviewImage?.id,
              linkPreviewTitle: linkPreviewTitle,
              linkPreviewDescription: linkPreviewDescription,
              lastModifiedDate: lastModified,
              originalURL: originalUrl,
              hideTitle: hideTitle ? true : nil)
    }
}


private extension Post {

    var postFile: PostFile {
        .init(
            isDraft: isDraft,
            createdDate: createdDate,
            startDate: startDate,
            endDate: hasEndDate ? endDate : nil,
            tags: tags.map { $0.id },
            german: german.postFile,
            english: english.postFile,
            linkedPageId: linkedPage?.id)
    }
}

private extension LocalizedPost {

    var postFile: LocalizedPostFile {
        .init(images: images.map { $0.id },
              title: title.nonEmpty,
              content: text,
              lastModifiedDate: lastModified,
              linkPreviewImage: linkPreviewImage?.id,
              linkPreviewTitle: linkPreviewTitle,
              linkPreviewDescription: linkPreviewDescription)
    }
}
