module Teams
  class Entitlements
    ACTIVE_STREAM_STATUSES = %w[idle connecting live reconnecting paused].freeze

    def initialize(team)
      @team = team
    end

    def subscription
      @subscription ||= @team.subscription || ensure_free_subscription!
    end

    def plan
      subscription.plan
    end

    def active?
      subscription.active?
    end

    def premium_active?
      subscription.premium?
    end

    def premium_full?
      subscription.premium_full?
    end

    def youtube_enabled?
      active? && plan.youtube_enabled?
    end

    def phone_download_enabled?
      active? && plan.phone_download_enabled?
    end

    def max_staff_transmission
      plan.max_staff_transmission
    end

    def max_staff_regia
      plan.max_staff_regia
    end

    def max_staff
      plan.max_staff
    end

    def staff_count
      staff_count_for("transmission") + staff_count_for("regia")
    end

    def staff_count_for(kind)
      members_count_for(kind) + pending_invitations_count_for(kind)
    end

    def members_count
      @team.user_teams.where(role: "member").count
    end

    def members_count_for(kind)
      @team.user_teams.where(role: "member", staff_kind: kind).count
    end

    def pending_invitations_count
      @team.team_invitations.pending.count
    end

    def pending_invitations_count_for(kind)
      @team.team_invitations.pending.where(staff_kind: kind).count
    end

    def concurrent_streams_limit
      plan.concurrent_streams_limit
    end

    def concurrent_streams_used
      StreamSession.joins(:match)
                   .where(matches: { team_id: @team.id })
                   .where(status: ACTIVE_STREAM_STATUSES)
                   .count
    end

    def concurrent_streams_limit_reached?
      limit = concurrent_streams_limit
      return false if limit.nil?

      concurrent_streams_used >= limit
    end

    def can_stream_on?(platform)
      return false unless active?

      platform = platform.to_s
      return false unless plan.allows_platform?(platform)

      true
    end

    def assert_can_stream_on!(platform)
      platform = platform.to_s
      unless active?
        raise EntitlementError.new(
          "Abbonamento non attivo per questa squadra",
          code: "subscription_inactive",
          billing_url: billing_url
        )
      end

      if platform == "youtube" && !youtube_enabled?
        raise EntitlementError.new(
          "YouTube richiede un piano Premium",
          code: "premium_required",
          billing_url: billing_url
        )
      end

      if platform == "youtube" && premium_full? == false && plan.youtube_mode != "matchlivetv_light"
        raise EntitlementError.new(
          "Il canale YouTube della società richiede Premium Full",
          code: "premium_full_required",
          billing_url: billing_url
        )
      end

      return if plan.allows_platform?(platform)

      raise EntitlementError.new("Piattaforma non consentita", code: "platform_denied", billing_url: billing_url)
    end

    def assert_concurrent_stream!(excluding_session: nil)
      return unless active?

      used = concurrent_streams_used
      used -= 1 if excluding_session && ACTIVE_STREAM_STATUSES.include?(excluding_session.status)

      limit = concurrent_streams_limit
      return if limit.nil?
      return if used < limit

      raise EntitlementError.new(
        "Limite dirette concorrenti raggiunto (#{limit}). Chiudi una diretta o passa a un piano superiore.",
        code: "concurrent_limit_reached",
        billing_url: billing_url
      )
    end

    def assert_can_invite!(staff_kind: "transmission")
      return unless active?

      kind = staff_kind.to_s
      unless TeamInvitation::STAFF_KINDS.include?(kind)
        raise EntitlementError.new("Ruolo staff non valido", code: "invalid_staff_kind")
      end

      limit = staff_limit_for(kind)
      return if limit.nil?

      used = staff_count_for(kind)
      return if used < limit

      label = kind == "regia" ? "regia" : "trasmissione"
      raise EntitlementError.new(
        "Limite staff #{label} raggiunto (#{limit} all'anno). Passa a un piano superiore.",
        code: "staff_limit_reached",
        billing_url: billing_url
      )
    end

    def staff_limit_for(kind)
      kind == "regia" ? max_staff_regia : max_staff_transmission
    end

    def assert_can_connect_youtube!
      unless premium_full?
        raise EntitlementError.new(
          "Collegamento al canale YouTube della società richiede Premium Full",
          code: "premium_full_required",
          billing_url: billing_url
        )
      end

      assert_can_stream_on!("youtube")
    end

    def can_access_recordings?
      active? && plan.recordings_enabled?
    end

    def recording_enabled_for_mediamtx?
      can_access_recordings?
    end

    def recording_retention_days
      plan.recording_days
    end

    def billing_url
      "#{MatchLiveTv.app_public_url.chomp('/')}/teams/#{@team.id}/billing"
    end

    def staff_manage_url
      "#{MatchLiveTv.app_public_url.chomp('/')}/teams/#{@team.id}/dashboard"
    end

    def as_json
      {
        plan_slug: plan.slug,
        plan_name: plan.name,
        premium_active: premium_active?,
        premium_full: premium_full?,
        subscription_status: subscription.status,
        features: plan.features,
        billing_url: billing_url,
        staff_manage_url: staff_manage_url,
        max_staff: max_staff,
        max_staff_transmission: max_staff_transmission,
        max_staff_regia: max_staff_regia,
        staff_used: staff_count,
        staff_transmission_used: staff_count_for("transmission"),
        staff_regia_used: staff_count_for("regia"),
        concurrent_streams_used: concurrent_streams_used,
        concurrent_streams_limit: concurrent_streams_limit,
        recordings_enabled: can_access_recordings?,
        recording_retention_days: recording_retention_days,
        phone_download_enabled: phone_download_enabled?,
        youtube_enabled: youtube_enabled?,
        youtube_mode: plan.youtube_mode
      }
    end

    private

    def ensure_free_subscription!
      Billing::AssignPlan.call(team: @team, plan_slug: "free")
      @team.reload.subscription
    end
  end
end
