import CoreGraphics
import Foundation

public enum FinderTabSpaceAttributionPolicy {
    private static let finderBundleIdentifier = "com.apple.finder"
    private static let minimumOverlapRatio: CGFloat = 0.85
    private static let minimumBestScoreGap: CGFloat = 0.05

    public static func attributedRecords(_ records: [WindowEnumerationRecord]) -> [WindowEnumerationRecord] {
        let hosts = records.filter(isFinderFullscreenHost)
        guard !hosts.isEmpty else { return records }

        return records.map { record in
            guard isFinderTabCandidate(record),
                  let host = bestHost(for: record, in: hosts)
            else {
                return record
            }

            return copy(
                record,
                isFullscreen: true,
                spaceIDs: host.spaceIDs
            )
        }
    }

    private static func isFinderTabCandidate(_ record: WindowEnumerationRecord) -> Bool {
        WindowEnumerationPolicy.shouldInclude(record)
            && record.identifierSource == .cgWindow
            && record.app.bundleIdentifier == finderBundleIdentifier
            && record.spaceIDs.isEmpty
            && !record.isMinimized
            && !record.title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
            && record.frame?.isEmpty == false
    }

    private static func isFinderFullscreenHost(_ record: WindowEnumerationRecord) -> Bool {
        WindowEnumerationPolicy.shouldInclude(record)
            && record.app.bundleIdentifier == finderBundleIdentifier
            && record.isFullscreen
            && !record.spaceIDs.isEmpty
            && record.subrole == .standard
            && record.frame?.isEmpty == false
    }

    private static func bestHost(
        for candidate: WindowEnumerationRecord,
        in hosts: [WindowEnumerationRecord]
    ) -> WindowEnumerationRecord? {
        let compatibleHosts = hosts.filter { host in
            sameProcess(candidate, host)
        }
        let scoredHosts = compatibleHosts.compactMap { host -> (record: WindowEnumerationRecord, score: CGFloat)? in
            guard let score = overlapScore(candidate.frame, host.frame),
                  score >= minimumOverlapRatio
            else {
                return nil
            }

            return (host, score)
        }
        .sorted { lhs, rhs in
            if lhs.score != rhs.score {
                return lhs.score > rhs.score
            }
            return lhs.record.id < rhs.record.id
        }

        guard let best = scoredHosts.first else { return nil }
        if scoredHosts.count == 1 {
            return best.record
        }

        let sameSpaceCompetitors = scoredHosts.filter { $0.record.spaceIDs == best.record.spaceIDs }
        if sameSpaceCompetitors.count == scoredHosts.count {
            return best.record
        }

        let secondBest = scoredHosts[1]
        return best.score - secondBest.score >= minimumBestScoreGap ? best.record : nil
    }

    private static func sameProcess(
        _ lhs: WindowEnumerationRecord,
        _ rhs: WindowEnumerationRecord
    ) -> Bool {
        guard let lhsPID = lhs.app.processIdentifier,
              let rhsPID = rhs.app.processIdentifier
        else {
            return false
        }

        return lhsPID == rhsPID
    }

    private static func overlapScore(_ lhs: CGRect?, _ rhs: CGRect?) -> CGFloat? {
        guard let lhs,
              let rhs,
              !lhs.isEmpty,
              !rhs.isEmpty
        else {
            return nil
        }

        let intersection = lhs.intersection(rhs)
        guard !intersection.isNull,
              !intersection.isEmpty
        else {
            return nil
        }

        let denominator = min(lhs.width * lhs.height, rhs.width * rhs.height)
        guard denominator > 0 else { return nil }
        return (intersection.width * intersection.height) / denominator
    }

    private static func copy(
        _ record: WindowEnumerationRecord,
        isFullscreen: Bool,
        spaceIDs: [UInt64]
    ) -> WindowEnumerationRecord {
        WindowEnumerationRecord(
            id: record.id,
            app: record.app,
            activationPolicy: record.activationPolicy,
            title: record.title,
            identifierSource: record.identifierSource,
            size: record.size,
            frame: record.frame,
            subrole: record.subrole,
            isMinimized: record.isMinimized,
            isFullscreen: isFullscreen,
            isGhost: record.isGhost,
            isDesktopElement: record.isDesktopElement,
            isSystemCritical: record.isSystemCritical,
            isInteractable: record.isInteractable,
            hasAXBacking: record.hasAXBacking,
            isOnscreen: record.isOnscreen,
            spaceIDs: spaceIDs
        )
    }
}
