import Foundation

// MARK: - Cached Regex Patterns for TV Show Parsing
private enum TVShowRegex {
    static let seasonPattern: NSRegularExpression? = try? NSRegularExpression(
        pattern: "S(\\d+)", options: .caseInsensitive)
    static let episodePattern: NSRegularExpression? = try? NSRegularExpression(
        pattern: "E(\\d+)", options: .caseInsensitive)
    static let showNamePattern: NSRegularExpression? = try? NSRegularExpression(
        pattern: "\\s+S\\d+.*$", options: .caseInsensitive)
}

struct TVShow: Identifiable, Hashable, Sendable {
    let id: String
    let name: String
    let iconURL: String?
    let categoryID: String?
    let seasons: [Season]

    init(name: String, episodes: [VODItem]) {
        self.name = name
        self.id = name // Use show name as unique identifier

        // Use the first episode's metadata for show-level info
        if let firstEpisode = episodes.first {
            self.iconURL = firstEpisode.iconURL
            self.categoryID = firstEpisode.categoryID
        } else {
            self.iconURL = nil
            self.categoryID = nil
        }

        // Group episodes by season
        var seasonDict: [Int: [VODItem]] = [:]
        for episode in episodes {
            if let seasonNumber = Self.extractSeasonNumber(from: episode.name) {
                seasonDict[seasonNumber, default: []].append(episode)
            }
        }

        // Convert to Season objects and sort by season number
        self.seasons = seasonDict.map { seasonNumber, episodes in
            Season(number: seasonNumber, episodes: episodes.sorted {
                Self.extractEpisodeNumber(from: $0.name) ?? 0 < Self.extractEpisodeNumber(from: $1.name) ?? 0
            })
        }.sorted { $0.number < $1.number }
    }

    // Extract season number from episode name (e.g., "Breaking Bad S01 E01" -> 1)
    static func extractSeasonNumber(from name: String) -> Int? {
        guard let regex = TVShowRegex.seasonPattern,
              let match = regex.firstMatch(in: name, options: [], range: NSRange(name.startIndex..., in: name)),
              let range = Range(match.range(at: 1), in: name) else {
            return nil
        }
        return Int(name[range])
    }

    // Extract episode number from episode name (e.g., "Breaking Bad S01 E01" -> 1)
    static func extractEpisodeNumber(from name: String) -> Int? {
        guard let regex = TVShowRegex.episodePattern,
              let match = regex.firstMatch(in: name, options: [], range: NSRange(name.startIndex..., in: name)),
              let range = Range(match.range(at: 1), in: name) else {
            return nil
        }
        return Int(name[range])
    }

    // Extract show name from episode name (e.g., "Breaking Bad S01 E01" -> "Breaking Bad")
    static func extractShowName(from name: String) -> String {
        guard let regex = TVShowRegex.showNamePattern else {
            return name
        }
        let range = NSRange(name.startIndex..., in: name)
        let cleanName = regex.stringByReplacingMatches(in: name, options: [], range: range, withTemplate: "")
        return cleanName.trimmingCharacters(in: .whitespaces)
    }
}

struct Season: Identifiable, Hashable, Sendable {
    let id: String
    let number: Int
    let episodes: [VODItem]

    init(number: Int, episodes: [VODItem]) {
        self.number = number
        self.id = "season-\(number)"
        self.episodes = episodes
    }
}
